Skip to content

Commit

Permalink
Don't cache the Compilation object in steps in the interop source gen…
Browse files Browse the repository at this point in the history
…erators (#76474)

* Directly pass along target framework kind and version instead of StubEnvironment to avoid rooting the compilation. Update all generators to follow suit and add a test in LibraryImportGenerator to validate that we don't keep the compilation alive.

* Use a wrapper struct to make using elementwise equality for immutable arrays easier.

* Remove accidentally included file

* PR feedback
  • Loading branch information
jkoritzinsky authored Oct 7, 2022
1 parent f9e0bdf commit d83ec0e
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@ internal sealed class JSExportCodeGenerator : JSCodeGenerator
private readonly JSSignatureContext _signatureContext;

public JSExportCodeGenerator(
StubEnvironment environment,
TargetFramework targetFramework,
Version targetFrameworkVersion,
ImmutableArray<TypePositionInfo> argTypes,
JSExportData attributeData,
JSSignatureContext signatureContext,
Action<TypePositionInfo, MarshallingNotSupportedException> marshallingNotSupportedCallback,
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Diagnostic> 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<Diagnostic> Diagnostics);

public static class StepNames
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<Diagnostic>(generatorDiagnostics.Diagnostics.ToImmutableArray()));
}

private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options)
Expand All @@ -232,14 +210,14 @@ private static IncrementalStubGenerationContext CalculateStubInformation(
}

private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) 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,
Expand All @@ -252,7 +230,7 @@ private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@ internal sealed class JSImportCodeGenerator : JSCodeGenerator
private readonly JSSignatureContext _signatureContext;

public JSImportCodeGenerator(
StubEnvironment environment,
TargetFramework targetFramework,
Version targetFrameworkVersion,
ImmutableArray<TypePositionInfo> argTypes,
JSImportData attributeData,
JSSignatureContext signatureContext,
Action<TypePositionInfo, MarshallingNotSupportedException> marshallingNotSupportedCallback,
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Diagnostic> 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<Diagnostic> Diagnostics);

public static class StepNames
{
Expand Down Expand Up @@ -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<Diagnostic>(generatorDiagnostics.Diagnostics.ToImmutableArray()));
}

private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options)
Expand All @@ -253,7 +229,8 @@ private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) 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,
Expand All @@ -265,7 +242,7 @@ private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit d83ec0e

Please sign in to comment.