Skip to content

Commit

Permalink
Add OverloadResolutionPriorityAttribute
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Oct 9, 2024
1 parent 5374551 commit fe273be
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.CompilerServices
{
/// <summary>
/// Specifies the priority of a member in overload resolution. When unspecified, the default priority is 0.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
internal sealed class OverloadResolutionPriorityAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="OverloadResolutionPriorityAttribute"/> class.
/// </summary>
/// <param name="priority">The priority of the attributed member. Higher numbers are prioritized, lower numbers are deprioritized. 0 is the default if no attribute is present.</param>
public OverloadResolutionPriorityAttribute(int priority)
{
Priority = priority;
}

/// <summary>
/// The priority of the member.
/// </summary>
public int Priority { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Meziantou.Framework.FullPath" Version="1.0.12" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.6.0" />
<PackageReference Include="Meziantou.Framework.FullPath" Version="1.0.13" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.11.0" />
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion Meziantou.Polyfill.Generator/PolyfillData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public static PolyfillData Get(CSharpCompilation compilation, string content)

if (symbol.DeclaredAccessibility is Accessibility.Public or Accessibility.Internal)
{
declaredMethods.Add(DocumentationCommentId.CreateDeclarationId(symbol));
var declarationId = DocumentationCommentId.CreateDeclarationId(symbol);
if (declarationId is not null)
{
declaredMethods.Add(declarationId);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.11.0" />
</ItemGroup>

<ItemGroup>
Expand Down
49 changes: 36 additions & 13 deletions Meziantou.Polyfill.SourceGenerator.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.IO.Compression;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
Expand All @@ -13,7 +15,7 @@ namespace Meziantou.Polyfill.SourceGenerator.Tests;

public class UnitTest1
{
private const string LatestDotnetPackageVersion = "9.0.0-preview.1.24080.9";
private const string LatestDotnetPackageVersion = "9.0.0-rc.2.24473.5";

[Fact]
public void PolyfillOptions_Included()
Expand All @@ -24,7 +26,7 @@ public void PolyfillOptions_Included()

Assert.False(options.Include("T:C"));
}

[Fact]
public void PolyfillOptions_Excluded()
{
Expand Down Expand Up @@ -55,7 +57,7 @@ public async Task ExcludedPolyfill()
result = GenerateFiles("", assemblyLocations: assemblies, excludedPolyfills: "T:System.Diagnostics.CodeAnalysis.UnscopedRefAttribute");
Assert.Empty(result.GeneratorResult.GeneratedTrees.Where(t => t.FilePath.Contains("UnscopedRefAttribute")));
}

[Fact]
public async Task IncludedPolyfill_Methods()
{
Expand All @@ -72,7 +74,7 @@ public async Task IncludedPolyfill_Methods()
[Fact]
public async Task InternalsVisibleTo_DoNotRegenerateExtensionMethods()
{
var assemblies = await NuGetHelpers.GetNuGetReferences("NETStandard.Library", "2.0.3", "ref/netstandard2.0/");
var assemblies = await NuGetHelpers.GetNuGetReferences("NETStandard.Library", "2.0.3", "build/");
var tempGeneration = GenerateFiles("""[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("main")]""", assemblyName: "temp", assemblyLocations: assemblies);
Assert.Single(tempGeneration.GeneratorResult.GeneratedTrees.Where(t => t.FilePath.EndsWith("T_System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.g.cs")));
Assert.Single(tempGeneration.GeneratorResult.GeneratedTrees.Where(t => t.FilePath.EndsWith("M_System.IO.TextReader.ReadToEndAsync(System.Threading.CancellationToken).g.cs")));
Expand All @@ -90,7 +92,7 @@ public async Task GeneratedCodeCompile(PackageReference[] packages)
var assemblies = new List<string>();
foreach (var package in packages)
{
assemblies.AddRange(await NuGetHelpers.GetNuGetReferences(package.Name, package.Version, package.Path));
assemblies.AddRange(await NuGetHelpers.GetNuGetReferences(package.Name, package.Version, package.Path, package.Exclusions));
}

GenerateFiles("", assemblyLocations: assemblies.ToArray());
Expand Down Expand Up @@ -163,9 +165,13 @@ public static TheoryData<PackageReference[]> GetConfigurations()
{ new[] { new PackageReference("Microsoft.NETFramework.ReferenceAssemblies.net461", "1.0.3", ""), new PackageReference("System.Memory", "4.5.5", "lib/net461/") ,new PackageReference("System.ValueTuple", "4.5.0", "lib/net461/"), new PackageReference("System.Net.Http", "4.3.4", "lib/net46/") } },
{ new[] { new PackageReference("Microsoft.NETFramework.ReferenceAssemblies.net46", "1.0.3", "") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", "") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""), new PackageReference("System.ValueTuple", "4.5.0", "lib/netstandard2.0/") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""), new PackageReference("System.Memory", "4.5.5", "lib/netstandard2.0/") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""), new PackageReference("System.ValueTuple", "4.5.0", "lib/netstandard2.0/"), new PackageReference("System.Memory", "4.5.5", "lib/netstandard2.0/") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""),
new PackageReference("System.ValueTuple", "4.5.0", "lib/netstandard2.0/") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""),
new PackageReference("System.Memory", "4.5.5", "lib/netstandard2.0/") } },
{ new[] { new PackageReference("NETStandard.Library", "2.0.3", ""),
new PackageReference("System.ValueTuple", "4.5.0", "lib/netstandard2.0/"),
new PackageReference("System.Memory", "4.5.5", "lib/netstandard2.0/") } },
};
}

Expand All @@ -175,6 +181,8 @@ public sealed class PackageReference : IXunitSerializable
public string Version { get; set; }
public string Path { get; set; }

public string[]? Exclusions { get; set; }

public PackageReference()
: this("", "", "")
{
Expand All @@ -192,13 +200,15 @@ public void Deserialize(IXunitSerializationInfo info)
Name = info.GetValue<string>("Name");
Version = info.GetValue<string>("Version");
Path = info.GetValue<string>("Path");
Exclusions = info.GetValue<string[]>("Exclusions");
}

public void Serialize(IXunitSerializationInfo info)
{
info.AddValue("Name", Name);
info.AddValue("Version", Version);
info.AddValue("Path", Path);
info.AddValue("Exclusions", Exclusions);
}
}

Expand Down Expand Up @@ -276,9 +286,10 @@ private static class NuGetHelpers
{
private static readonly ConcurrentDictionary<string, Lazy<Task<string[]>>> Cache = new(StringComparer.Ordinal);

public static Task<string[]> GetNuGetReferences(string packageName, string version, string path)
public static Task<string[]> GetNuGetReferences(string packageName, string version, string path, string[]? exclusions = null)
{
var task = Cache.GetOrAdd(packageName + '@' + version + ':' + path, key =>
string key = Convert.ToBase64String(SHA256.HashData(Encoding.UTF8.GetBytes(packageName + '@' + version + ':' + path + (exclusions is null ? "" : string.Join(":", exclusions)))));
var task = Cache.GetOrAdd(key, key =>
{
return new Lazy<Task<string[]>>(Download);
});
Expand All @@ -295,13 +306,15 @@ async Task<string[]> Download()
using var stream = await httpClient.GetStreamAsync(new Uri($"https://www.nuget.org/api/v2/package/{packageName}/{version}")).ConfigureAwait(false);
using var zip = new ZipArchive(stream, ZipArchiveMode.Read);

foreach (var entry in zip.Entries.Where(file => file.FullName.StartsWith(path, StringComparison.Ordinal)))
foreach (var entry in zip.Entries)
{
entry.ExtractToFile(Path.Combine(tempFolder, entry.Name), overwrite: true);
var extractPath = Path.Combine(tempFolder, entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(extractPath)!);
entry.ExtractToFile(extractPath, overwrite: true);
}
}

var dlls = Directory.GetFiles(tempFolder, "*.dll");
var dlls = Directory.GetFiles(tempFolder, "*.dll", SearchOption.AllDirectories);

// Filter invalid .NET assembly
var result = new List<string>();
Expand All @@ -310,6 +323,16 @@ async Task<string[]> Download()
if (Path.GetFileName(dll) == "System.EnterpriseServices.Wrapper.dll")
continue;

var relativePath = Path.GetRelativePath(tempFolder, dll).Replace('\\', '/');
if (!relativePath.StartsWith(path, StringComparison.OrdinalIgnoreCase))
continue;

if(exclusions != null)
{
if (exclusions.Any(exclusion => relativePath.StartsWith(exclusion, StringComparison.OrdinalIgnoreCase)))
continue;
}

try
{
using var stream = File.OpenRead(dll);
Expand Down
6 changes: 3 additions & 3 deletions Meziantou.Polyfill.Tests/Meziantou.Polyfill.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.6.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
1 change: 1 addition & 0 deletions Meziantou.Polyfill.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public void AttributesAreAvailables()
_ = new UnsupportedOSPlatformGuardAttribute("");
_ = new CollectionBuilderAttribute(typeof(string), "");
_ = new ExperimentalAttribute("test");
_ = new OverloadResolutionPriorityAttribute(1);

_ = typeof(IsExternalInit);
}
Expand Down
1 change: 1 addition & 0 deletions Meziantou.Polyfill/Internals/AllowNullAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma warning disable IDE0130 // Namespace does not match folder structure
namespace System.Diagnostics.CodeAnalysis;

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Meziantou.Polyfill/Meziantou.Polyfill.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>1.0.39</Version>
<Version>1.0.40</Version>
<TransformOnBuild>true</TransformOnBuild>

<LangVersion>preview</LangVersion>
Expand Down Expand Up @@ -36,7 +36,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Meziantou.DotNet.CodingStandard" Version="1.0.110">
<PackageReference Include="Meziantou.DotNet.CodingStandard" Version="1.0.133">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
6 changes: 4 additions & 2 deletions Meziantou.Polyfill/PolyfillGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
if (Environment.GetEnvironmentVariable("Meziantou_Polyfill_Debug") is "true" or "1")
{
Debugger.Launch();
Debugger.Break();
if (Debugger.Launch())
{
Debugger.Break();
}
}

var options = context.AnalyzerConfigOptionsProvider.Select((options, cancellationToken) =>
Expand Down
3 changes: 2 additions & 1 deletion Meziantou.Polyfill/PolyfillOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
#pragma warning disable IDE0290 // Use primary constructor
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ By default, all needed polyfills are generated. You can configure which polyfill
- `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute`
- `System.Runtime.CompilerServices.IsExternalInit`
- `System.Runtime.CompilerServices.ModuleInitializerAttribute`
- `System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute`
- `System.Runtime.CompilerServices.RequiredMemberAttribute`
- `System.Runtime.CompilerServices.SkipLocalsInitAttribute`
- `System.Runtime.CompilerServices.TupleElementNamesAttribute`
Expand All @@ -103,7 +104,7 @@ By default, all needed polyfills are generated. You can configure which polyfill

### Methods

- `System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd<TArg>(TKey key, System.Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument)`
- `System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd<TArg>(TKey key, System.Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument) where TArg : allows ref struct`
- `System.Collections.Generic.CollectionExtensions.GetValueOrDefault<TKey, TValue>(this System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> dictionary, TKey key)`
- `System.Collections.Generic.CollectionExtensions.GetValueOrDefault<TKey, TValue>(this System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)`
- `System.Collections.Generic.KeyValuePair<TKey, TValue>.Deconstruct(out TKey key, out TValue value)`
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "9.0.100-preview.1.24101.2",
"version": "9.0.100-rc.2.24474.11",
"rollForward": "patch"
}
}
Expand Down

0 comments on commit fe273be

Please sign in to comment.