diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 3c44d665748b5..614bad043f15a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -20,7 +20,8 @@ internal sealed class JSExportCodeGenerator : JSCodeGenerator private readonly JSSignatureContext _signatureContext; public JSExportCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, JSExportData attributeData, JSSignatureContext signatureContext, @@ -28,13 +29,13 @@ public JSExportCodeGenerator( IMarshallingGeneratorFactory generatorFactory) { _signatureContext = signatureContext; - ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _context = new JSExportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, null)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnNativeIdentifier); + innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnNativeIdentifier); _context = new JSExportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index c033637881673..ab4c93dc48cd2 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -17,33 +17,13 @@ namespace Microsoft.Interop.JavaScript public sealed class JSExportGenerator : IIncrementalGenerator { internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, JSSignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, JSExportData JSExportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && JSExportData.Equals(other.JSExportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -119,9 +99,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static (data, ct) => CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, data.Options, ct) ) .WithTrackingName(StepNames.CalculateStubInformation) - .Combine(stubOptions) .Select( - static (data, ct) => GenerateSource(data.Left, data.Right) + static (data, ct) => GenerateSource(data) ) .WithComparer(Comparers.GeneratedSyntax) .WithTrackingName(StepNames.GenerateSingleStub); @@ -215,14 +194,13 @@ private static IncrementalStubGenerationContext CalculateStubInformation( var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(originalSyntax), jsExportData, CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -232,14 +210,14 @@ private static IncrementalStubGenerationContext CalculateStubInformation( } private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( - IncrementalStubGenerationContext incrementalContext, - JSGeneratorOptions options) + IncrementalStubGenerationContext incrementalContext) { var diagnostics = new GeneratorDiagnostics(); // Generate stub code var stubGenerator = new JSExportCodeGenerator( - incrementalContext.Environment, + incrementalContext.GeneratorFactoryKey.Key.TargetFramework, + incrementalContext.GeneratorFactoryKey.Key.TargetFrameworkVersion, incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSExportData, incrementalContext.SignatureContext, @@ -252,7 +230,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax wrapper = stubGenerator.GenerateJSExportBody(); BlockSyntax registration = stubGenerator.GenerateJSExportRegistration(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs index b7c1a324b2c47..1f1ebdf81b626 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs @@ -27,7 +27,8 @@ internal sealed class JSImportCodeGenerator : JSCodeGenerator private readonly JSSignatureContext _signatureContext; public JSImportCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, JSImportData attributeData, JSSignatureContext signatureContext, @@ -35,13 +36,13 @@ public JSImportCodeGenerator( IMarshallingGeneratorFactory generatorFactory) { _signatureContext = signatureContext; - ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _context = new JSImportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, null)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnNativeIdentifier); + innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnNativeIdentifier); _context = new JSImportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs index 0ce77445a85a8..4a387419f8128 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Runtime.InteropServices; -using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -22,33 +19,13 @@ namespace Microsoft.Interop.JavaScript public sealed class JSImportGenerator : IIncrementalGenerator { internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, JSSignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, JSImportData JSImportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && JSImportData.Equals(other.JSImportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -228,14 +205,13 @@ private static IncrementalStubGenerationContext CalculateStubInformation( var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(originalSyntax), jsImportData, CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -253,7 +229,8 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou // Generate stub code var stubGenerator = new JSImportCodeGenerator( - incrementalContext.Environment, + incrementalContext.GeneratorFactoryKey.Key.TargetFramework, + incrementalContext.GeneratorFactoryKey.Key.TargetFrameworkVersion, incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSImportData, incrementalContext.SignatureContext, @@ -265,7 +242,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax code = stubGenerator.GenerateJSImportBody(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs index 77855eaee06e4..e2dba4aa0ae18 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -95,7 +95,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo bool mayRequireAdditionalWork = diagnostics.AnyDiagnostics; bool anyExplicitlyUnsupportedInfo = false; - var stubCodeContext = new ManagedToNativeStubCodeContext(env, "return", "nativeReturn"); + var stubCodeContext = new ManagedToNativeStubCodeContext(env.TargetFramework, env.TargetFrameworkVersion, "return", "nativeReturn"); var forwarder = new Forwarder(); // We don't actually need the bound generators. We just need them to be attempted to be bound to determine if the generator will be able to bind them. diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 70ada65966b06..88aaa11d82051 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -22,35 +22,14 @@ namespace Microsoft.Interop public sealed class LibraryImportGenerator : IIncrementalGenerator { internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, - ImmutableArray ForwardedAttributes, + SequenceEqualImmutableArray ForwardedAttributes, LibraryImportData LibraryImportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, LibraryImportGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && LibraryImportData.Equals(other.LibraryImportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && ForwardedAttributes.SequenceEqual(other.ForwardedAttributes, (IEqualityComparer)SyntaxEquivalentComparer.Instance) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version Version, LibraryImportGeneratorOptions Options)> GeneratorFactoryKey, + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -318,15 +297,15 @@ private static IncrementalStubGenerationContext CalculateStubInformation( List additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultDllImportSearchPathsAttribute); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(originalSyntax), - additionalAttributes.ToImmutableArray(), + new SequenceEqualImmutableArray(additionalAttributes.ToImmutableArray(), SyntaxEquivalentComparer.Instance), libraryImportData, LibraryImportGeneratorHelpers.CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()) + ); } private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( @@ -336,12 +315,13 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou var diagnostics = new GeneratorDiagnostics(); if (options.GenerateForwarders) { - return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, explicitForwarding: true, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, explicitForwarding: true, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } // Generate stub code var stubGenerator = new PInvokeStubCodeGenerator( - pinvokeStub.Environment, + pinvokeStub.GeneratorFactoryKey.Key.TargetFramework, + pinvokeStub.GeneratorFactoryKey.Key.Version, pinvokeStub.SignatureContext.ElementTypeInformation, pinvokeStub.LibraryImportData.SetLastError && !options.GenerateForwarders, (elementInfo, ex) => @@ -355,10 +335,10 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou if (stubGenerator.StubIsBasicForwarder || !stubGenerator.SupportsTargetFramework) { - return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, !stubGenerator.SupportsTargetFramework, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, !stubGenerator.SupportsTargetFramework, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } - ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes; + ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes.Array; const string innerPInvokeName = "__PInvoke"; @@ -379,7 +359,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou dllImport = dllImport.WithLeadingTrivia(Comment("// Local P/Invoke")); code = code.AddStatements(dllImport); - return (pinvokeStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(pinvokeStub.StubMethodSyntaxTemplate, pinvokeStub.SignatureContext, code)), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (pinvokeStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(pinvokeStub.StubMethodSyntaxTemplate, pinvokeStub.SignatureContext, code)), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static MemberDeclarationSyntax PrintForwarderStub(ContainingSyntax userDeclaredMethod, bool explicitForwarding, IncrementalStubGenerationContext stub, GeneratorDiagnostics diagnostics) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index 9077f4cf523cb..0a331d098e377 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -9,7 +9,7 @@ RS2008;$(NoWarn) - cs + cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs index 66b7c5f2f8544..71cb7e06968bd 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs @@ -4,9 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -49,7 +46,8 @@ internal sealed class PInvokeStubCodeGenerator private readonly ManagedToNativeStubCodeContext _context; public PInvokeStubCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, bool setLastError, Action marshallingNotSupportedCallback, @@ -61,21 +59,21 @@ public PInvokeStubCodeGenerator( // supports target framework value with this value. if (_setLastError) { - SupportsTargetFramework = environment.TargetFramework == TargetFramework.Net - && environment.TargetFrameworkVersion.Major >= 6; + SupportsTargetFramework = targetFramework == TargetFramework.Net + && targetFrameworkVersion.Major >= 6; } else { SupportsTargetFramework = true; } - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, _context)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); } bool noMarshallingNeeded = true; @@ -84,7 +82,7 @@ public PInvokeStubCodeGenerator( { // Check if marshalling info and generator support the current target framework. SupportsTargetFramework &= generator.TypeInfo.MarshallingAttributeInfo is not MissingSupportMarshallingInfo - && generator.Generator.IsSupported(environment.TargetFramework, environment.TargetFrameworkVersion); + && generator.Generator.IsSupported(targetFramework, targetFrameworkVersion); // Check if generator is either blittable or just a forwarder. noMarshallingNeeded &= generator is { Generator: BlittableMarshaller, TypeInfo.IsByRef: false } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs index 36b59f4600eac..c953e246a55e2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Text; - namespace Microsoft.Interop { public sealed record ManagedToNativeStubCodeContext : StubCodeContext @@ -22,12 +19,13 @@ public sealed record ManagedToNativeStubCodeContext : StubCodeContext private readonly string _nativeReturnIdentifier; public ManagedToNativeStubCodeContext( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, string returnIdentifier, string nativeReturnIdentifier) { - _framework = environment.TargetFramework; - _frameworkVersion = environment.TargetFrameworkVersion; + _framework = targetFramework; + _frameworkVersion = targetFrameworkVersion; _returnIdentifier = returnIdentifier; _nativeReturnIdentifier = nativeReturnIdentifier; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs new file mode 100644 index 0000000000000..f91d7be4ea2bc --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Microsoft.Interop +{ + /// + /// This method provides a wrapper for an that overrides the equality operation to provide elementwise comparison. + /// The default equality operation for an is reference equality of the underlying array, which is too strict + /// for many scenarios. This wrapper type allows us to use s in our other record types without having to write an Equals method + /// that we may forget to update if we add new elements to the record. + /// + public readonly record struct SequenceEqualImmutableArray(ImmutableArray Array, IEqualityComparer Comparer) + { + public SequenceEqualImmutableArray(ImmutableArray array) + : this(array, EqualityComparer.Default) + { + } + + public bool Equals(SequenceEqualImmutableArray other) + { + return Array.SequenceEqual(other.Array, Comparer); + } + + public override int GetHashCode() => throw new UnreachableException(); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs index 268749de6dd6a..769c391b238b4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs @@ -2,18 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop { @@ -21,21 +11,5 @@ public sealed record StubEnvironment( Compilation Compilation, TargetFramework TargetFramework, Version TargetFrameworkVersion, - bool ModuleSkipLocalsInit) - { - /// - /// Override for determining if two StubEnvironment instances are - /// equal. This intentionally excludes the Compilation instance - /// since that represents the actual compilation and not just the settings. - /// - /// The first StubEnvironment - /// The second StubEnvironment - /// True if the settings are equal, otherwise false. - public static bool AreCompilationSettingsEqual(StubEnvironment env1, StubEnvironment env2) - { - return env1.TargetFramework == env2.TargetFramework - && env1.TargetFrameworkVersion == env2.TargetFrameworkVersion - && env1.ModuleSkipLocalsInit == env2.ModuleSkipLocalsInit; - } - } + bool ModuleSkipLocalsInit); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs index e56165393330d..31887788c314c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; -using System.Text; using Microsoft.CodeAnalysis; namespace Microsoft.Interop @@ -12,8 +10,6 @@ public sealed class SyntaxEquivalentComparer : IEqualityComparer, IE { public static readonly SyntaxEquivalentComparer Instance = new(); - private SyntaxEquivalentComparer() { } - public bool Equals(SyntaxNode x, SyntaxNode y) { if ((x is null) != (y is null)) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs index 204864133c55a..215ee20ece159 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -66,11 +67,10 @@ public async Task AppendingUnrelatedSource_DoesNotRegenerateSource() GeneratorDriver driver2 = driver.RunGenerators(comp2); GeneratorRunResult runResult = driver2.GetRunResult().Results[0]; - Assert.Collection(runResult.TrackedSteps[StepNames.CalculateStubInformation], + Assert.Collection(runResult.TrackedSteps[StepNames.GenerateSingleStub], step => { - // The input contains symbols and Compilation objects, so it will always be different. - // However, we validate that the calculated stub information is identical. + // The calculated stub information will differ since we have a new syntax tree for where to report diagnostics. Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); @@ -210,5 +210,53 @@ public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate() output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); } + + [Fact] + public async Task GeneratorRun_WithNewCompilation_DoesNotKeepOldCompilationAlive() + { + string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers()}}}"; + + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); + + Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); + + var (reference, driver) = RunTwoGeneratorOnTwoIterativeCompilationsAndReturnFirst(comp1); + + GC.Collect(); + + Assert.False(reference.IsAlive); + GC.KeepAlive(driver); + + [MethodImpl(MethodImplOptions.NoInlining)] + static (WeakReference reference, GeneratorDriver driver) RunTwoGeneratorOnTwoIterativeCompilationsAndReturnFirst(Compilation startingCompilation) + { + Compilation comp2 = startingCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct NewType {}", new CSharpParseOptions(LanguageVersion.Preview))); + + Microsoft.Interop.LibraryImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp2, null, new[] { generator }, EnableIncrementalTrackingDriverOptions); + + driver = driver.RunGenerators(comp2); + + Compilation comp3 = comp2.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct NewType2 {}", new CSharpParseOptions(LanguageVersion.Preview))); + + GeneratorDriver driver2 = driver.RunGenerators(comp3); + + // Assert here that we did use the last result and didn't regenerate. + Assert.Collection(driver2.GetRunResult().Results, + result => + { + Assert.Collection(result.TrackedSteps[StepNames.CalculateStubInformation], + step => + { + Assert.Collection(step.Outputs, + output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); + }); + }); + + // Return a weak reference to the first edited compilation and the driver from the most recent run. + // The most recent run with comp3 shouldn't keep anything from comp2 alive. + return (new WeakReference(comp2), driver2); + } + } } }