Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Koritzinsky <jekoritz@microsoft.com>2021-09-08 21:10:41 +0300
committerGitHub <noreply@github.com>2021-09-08 21:10:41 +0300
commitd8775eea98c7ea5911f2752d7746dfe9e7d14fc6 (patch)
treeaa8190b349ab48d62088eaacac0cb5861a0bfe8f /src/libraries/System.Runtime.InteropServices/tests
parent02fa63e1f6198f7dadcbec4202d46b6e541c19ff (diff)
Move to using the new Roslyn IIncrementalGenerator API for better in-VS performance (dotnet/runtimelab#1374)
Commit migrated from https://github.com/dotnet/runtimelab/commit/90c617d39a9775e8eb0c5d4aba2f0cc6932bfb87
Diffstat (limited to 'src/libraries/System.Runtime.InteropServices/tests')
-rw-r--r--src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj1
-rw-r--r--src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs203
-rw-r--r--src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs56
3 files changed, 243 insertions, 17 deletions
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
index 7af1a40c40b..e19d9b4e5d9 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
@@ -3,7 +3,6 @@
<PropertyGroup>
<AssemblyName>Microsoft.Interop.Ancillary</AssemblyName>
<TargetFramework>net6.0</TargetFramework>
- <LangVersion>8.0</LangVersion>
<RootNamespace>System.Runtime.InteropServices</RootNamespace>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs
new file mode 100644
index 00000000000..e37e6fdd7ab
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs
@@ -0,0 +1,203 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+using static Microsoft.Interop.DllImportGenerator;
+
+namespace DllImportGenerator.UnitTests
+{
+ public class IncrementalGenerationTests
+ {
+ public const string RequiresIncrementalSyntaxTreeModifySupport = "The GeneratorDriver treats all SyntaxTree replace operations on a Compilation as an Add/Remove operation instead of a Modify operation"
+ + ", so all cached results based on that input are thrown out. As a result, we cannot validate that unrelated changes within the same SyntaxTree do not cause regeneration.";
+
+ [Fact]
+ public async Task AddingNewUnrelatedType_DoesNotRegenerateSource()
+ {
+ string source = CodeSnippets.BasicParametersAndModifiers<int>();
+
+ Compilation comp1 = await TestUtils.CreateCompilation(source);
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new IIncrementalGenerator[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct Foo {}", new CSharpParseOptions(LanguageVersion.Preview)));
+ driver.RunGenerators(comp2);
+
+ Assert.Collection(generator.IncrementalTracker.ExecutedSteps,
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step);
+ });
+ }
+
+ [Fact(Skip = RequiresIncrementalSyntaxTreeModifySupport)]
+ public async Task AppendingUnrelatedSource_DoesNotRegenerateSource()
+ {
+ string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers<int>()}}}";
+
+ SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview));
+
+ Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree });
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ SyntaxTree newTree = syntaxTree.WithRootAndOptions(syntaxTree.GetCompilationUnitRoot().AddMembers(SyntaxFactory.ParseMemberDeclaration("struct Foo {}")!), syntaxTree.Options);
+
+ Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree);
+ driver.RunGenerators(comp2);
+
+ Assert.Collection(generator.IncrementalTracker.ExecutedSteps,
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step);
+ });
+ }
+
+ [Fact]
+ public async Task AddingFileWithNewGeneratedDllImport_DoesNotRegenerateOriginalMethod()
+ {
+ string source = CodeSnippets.BasicParametersAndModifiers<int>();
+
+ Compilation comp1 = await TestUtils.CreateCompilation(source);
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers<bool>(), new CSharpParseOptions(LanguageVersion.Preview)));
+ driver.RunGenerators(comp2);
+
+ Assert.Equal(2, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.CalculateStubInformation));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.GenerateSingleStub));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.NormalizeWhitespace));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.ConcatenateStubs));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.OutputSourceFile));
+ }
+
+ [Fact]
+ public async Task ReplacingFileWithNewGeneratedDllImport_DoesNotRegenerateStubsInOtherFiles()
+ {
+ string source = CodeSnippets.BasicParametersAndModifiers<int>();
+
+ Compilation comp1 = await TestUtils.CreateCompilation(new string[] { CodeSnippets.BasicParametersAndModifiers<int>(), CodeSnippets.BasicParametersAndModifiers<bool>() });
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers<ulong>(), new CSharpParseOptions(LanguageVersion.Preview)));
+ driver.RunGenerators(comp2);
+
+ Assert.Equal(2, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.CalculateStubInformation));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.GenerateSingleStub));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.NormalizeWhitespace));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.ConcatenateStubs));
+ Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.OutputSourceFile));
+ }
+
+ [Fact]
+ public async Task ChangingMarshallingStrategy_RegeneratesStub()
+ {
+ string stubSource = CodeSnippets.BasicParametersAndModifiers("CustomType");
+
+ string customTypeImpl1 = "struct CustomType { System.IntPtr handle; }";
+
+ string customTypeImpl2 = "class CustomType : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public CustomType():base(true){} protected override bool ReleaseHandle(){return true;} }";
+
+
+ Compilation comp1 = await TestUtils.CreateCompilation(stubSource);
+
+ SyntaxTree customTypeImpl1Tree = CSharpSyntaxTree.ParseText(customTypeImpl1, new CSharpParseOptions(LanguageVersion.Preview));
+ comp1 = comp1.AddSyntaxTrees(customTypeImpl1Tree);
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ Compilation comp2 = comp1.ReplaceSyntaxTree(customTypeImpl1Tree, CSharpSyntaxTree.ParseText(customTypeImpl2, new CSharpParseOptions(LanguageVersion.Preview)));
+ driver.RunGenerators(comp2);
+
+ Assert.Collection(generator.IncrementalTracker.ExecutedSteps,
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step);
+ },
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.GenerateSingleStub, step.Step);
+ },
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.NormalizeWhitespace, step.Step);
+ },
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.ConcatenateStubs, step.Step);
+ },
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.OutputSourceFile, step.Step);
+ });
+ }
+
+ [Fact(Skip = RequiresIncrementalSyntaxTreeModifySupport)]
+ public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate()
+ {
+ string source = CodeSnippets.BasicParametersAndModifiers<bool>();
+
+ SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview));
+
+ Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree });
+
+ Microsoft.Interop.DllImportGenerator generator = new();
+ GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator });
+
+ driver = driver.RunGenerators(comp1);
+
+ generator.IncrementalTracker = new IncrementalityTracker();
+
+ SyntaxTree newTree = syntaxTree.WithRootAndOptions(
+ syntaxTree.GetCompilationUnitRoot().AddMembers(
+ SyntaxFactory.ParseMemberDeclaration(
+ CodeSnippets.MarshalAsParametersAndModifiers<bool>(System.Runtime.InteropServices.UnmanagedType.Bool))!),
+ syntaxTree.Options);
+
+ Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree);
+ driver.RunGenerators(comp2);
+
+ Assert.Collection(generator.IncrementalTracker.ExecutedSteps,
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step);
+ },
+ step =>
+ {
+ Assert.Equal(IncrementalityTracker.StepName.GenerateSingleStub, step.Step);
+ });
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs
index fd49c82ccf9..db7b0f3fecc 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs
@@ -45,14 +45,26 @@ namespace DllImportGenerator.UnitTests
/// <param name="outputKind">Output type</param>
/// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
/// <returns>The resulting compilation</returns>
- public static async Task<Compilation> CreateCompilation(string source, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable<string>? preprocessorSymbols = null)
+ public static Task<Compilation> CreateCompilation(string source, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable<string>? preprocessorSymbols = null)
{
- var (mdRefs, ancillary) = GetReferenceAssemblies();
+ return CreateCompilation(new[] { source }, outputKind, allowUnsafe, preprocessorSymbols);
+ }
- return CSharpCompilation.Create("compilation",
- new[] { CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: preprocessorSymbols)) },
- (await mdRefs.ResolveAsync(LanguageNames.CSharp, CancellationToken.None)).Add(ancillary),
- new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe));
+ /// <summary>
+ /// Create a compilation given sources
+ /// </summary>
+ /// <param name="sources">Sources to compile</param>
+ /// <param name="outputKind">Output type</param>
+ /// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
+ /// <returns>The resulting compilation</returns>
+ public static Task<Compilation> CreateCompilation(string[] sources, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable<string>? preprocessorSymbols = null)
+ {
+ return CreateCompilation(
+ sources.Select(source =>
+ CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: preprocessorSymbols))).ToArray(),
+ outputKind,
+ allowUnsafe,
+ preprocessorSymbols);
}
/// <summary>
@@ -62,13 +74,12 @@ namespace DllImportGenerator.UnitTests
/// <param name="outputKind">Output type</param>
/// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
/// <returns>The resulting compilation</returns>
- public static async Task<Compilation> CreateCompilation(string[] sources, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable<string>? preprocessorSymbols = null)
+ public static async Task<Compilation> CreateCompilation(SyntaxTree[] sources, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable<string>? preprocessorSymbols = null)
{
var (mdRefs, ancillary) = GetReferenceAssemblies();
return CSharpCompilation.Create("compilation",
- sources.Select(source =>
- CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: preprocessorSymbols))).ToArray(),
+ sources,
(await mdRefs.ResolveAsync(LanguageNames.CSharp, CancellationToken.None)).Add(ancillary),
new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe));
}
@@ -81,10 +92,23 @@ namespace DllImportGenerator.UnitTests
/// <param name="outputKind">Output type</param>
/// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
/// <returns>The resulting compilation</returns>
- public static async Task<Compilation> CreateCompilationWithReferenceAssemblies(string source, ReferenceAssemblies referenceAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true)
+ public static Task<Compilation> CreateCompilationWithReferenceAssemblies(string source, ReferenceAssemblies referenceAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true)
+ {
+ return CreateCompilationWithReferenceAssemblies(new[] { CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)) }, referenceAssemblies, outputKind, allowUnsafe);
+ }
+
+ /// <summary>
+ /// Create a compilation given source and reference assemblies
+ /// </summary>
+ /// <param name="source">Source to compile</param>
+ /// <param name="referenceAssemblies">Reference assemblies to include</param>
+ /// <param name="outputKind">Output type</param>
+ /// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
+ /// <returns>The resulting compilation</returns>
+ public static async Task<Compilation> CreateCompilationWithReferenceAssemblies(SyntaxTree[] sources, ReferenceAssemblies referenceAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true)
{
return CSharpCompilation.Create("compilation",
- new[] { CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)) },
+ sources,
(await referenceAssemblies.ResolveAsync(LanguageNames.CSharp, CancellationToken.None)),
new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe));
}
@@ -96,7 +120,7 @@ namespace DllImportGenerator.UnitTests
"net6.0",
new PackageIdentity(
"Microsoft.NETCore.App.Ref",
- "6.0.0-preview.6.21317.4"),
+ "6.0.0-preview.7.21377.19"),
Path.Combine("ref", "net6.0"))
.WithNuGetConfigFilePath(Path.Combine(Path.GetDirectoryName(typeof(TestUtils).Assembly.Location)!, "NuGet.config"));
@@ -114,7 +138,7 @@ namespace DllImportGenerator.UnitTests
/// <param name="diagnostics">Resulting diagnostics</param>
/// <param name="generators">Source generator instances</param>
/// <returns>The resulting compilation</returns>
- public static Compilation RunGenerators(Compilation comp, out ImmutableArray<Diagnostic> diagnostics, params ISourceGenerator[] generators)
+ public static Compilation RunGenerators(Compilation comp, out ImmutableArray<Diagnostic> diagnostics, params IIncrementalGenerator[] generators)
{
CreateDriver(comp, null, generators).RunGeneratorsAndUpdateCompilation(comp, out var d, out diagnostics);
return d;
@@ -127,15 +151,15 @@ namespace DllImportGenerator.UnitTests
/// <param name="diagnostics">Resulting diagnostics</param>
/// <param name="generators">Source generator instances</param>
/// <returns>The resulting compilation</returns>
- public static Compilation RunGenerators(Compilation comp, AnalyzerConfigOptionsProvider options, out ImmutableArray<Diagnostic> diagnostics, params ISourceGenerator[] generators)
+ public static Compilation RunGenerators(Compilation comp, AnalyzerConfigOptionsProvider options, out ImmutableArray<Diagnostic> diagnostics, params IIncrementalGenerator[] generators)
{
CreateDriver(comp, options, generators).RunGeneratorsAndUpdateCompilation(comp, out var d, out diagnostics);
return d;
}
- private static GeneratorDriver CreateDriver(Compilation c, AnalyzerConfigOptionsProvider? options, ISourceGenerator[] generators)
+ public static GeneratorDriver CreateDriver(Compilation c, AnalyzerConfigOptionsProvider? options, IIncrementalGenerator[] generators)
=> CSharpGeneratorDriver.Create(
- ImmutableArray.Create(generators),
+ ImmutableArray.Create(generators.Select(gen => gen.AsSourceGenerator()).ToArray()),
parseOptions: (CSharpParseOptions)c.SyntaxTrees.First().Options,
optionsProvider: options);
}