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 0dba53f9bf0b63..3c44d665748b5c 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -69,7 +69,7 @@ IMarshallingGenerator CreateGenerator(TypePositionInfo p) public BlockSyntax GenerateJSExportBody() { StatementSyntax invoke = InvokeSyntax(); - JSGeneratedStatements statements = JSGeneratedStatements.Create(_marshallers, _context, invoke); + GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToNative(_marshallers, _context, shouldInitializeVariables); @@ -88,7 +88,7 @@ public BlockSyntax GenerateJSExportBody() var tryStatements = new List(); tryStatements.AddRange(statements.Unmarshal); - tryStatements.AddRange(statements.InvokeStatements); + tryStatements.Add(invoke); if (!statements.GuaranteedUnmarshal.IsEmpty) { @@ -98,6 +98,7 @@ public BlockSyntax GenerateJSExportBody() } tryStatements.AddRange(statements.NotifyForSuccessfulInvoke); + tryStatements.AddRange(statements.PinnedMarshal); tryStatements.AddRange(statements.Marshal); List allStatements = setupStatements; 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 f6590136448336..c0336378816730 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -131,28 +131,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "JSExports.g.cs"); } - private static SyntaxTokenList StripTriviaFromModifiers(SyntaxTokenList tokenList) - { - SyntaxToken[] strippedTokens = new SyntaxToken[tokenList.Count]; - for (int i = 0; i < tokenList.Count; i++) - { - strippedTokens[i] = tokenList[i].WithoutTrivia(); - } - return new SyntaxTokenList(strippedTokens); - } - - private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDeclarationSyntax typeDeclaration) - { - return TypeDeclaration( - typeDeclaration.Kind(), - typeDeclaration.Identifier) - .WithTypeParameterList(typeDeclaration.TypeParameterList) - .WithModifiers(StripTriviaFromModifiers(typeDeclaration.Modifiers)); - } - private static MemberDeclarationSyntax PrintGeneratedSource( ContainingSyntax userDeclaredMethod, JSSignatureContext stub, + ContainingSyntaxContext containingSyntaxContext, BlockSyntax wrapperStatements, BlockSyntax registerStatements) { var WrapperName = "__Wrapper_" + userDeclaredMethod.Identifier + "_" + stub.TypesHash; @@ -176,35 +158,7 @@ private static MemberDeclarationSyntax PrintGeneratedSource( .WithBody(registerStatements); - MemberDeclarationSyntax toPrint = WrapMethodInContainingScopes(stub, wrappperMethod, registerMethod); - - return toPrint; - } - - private static MemberDeclarationSyntax WrapMethodInContainingScopes(JSSignatureContext stub, MemberDeclarationSyntax stubMethod, MemberDeclarationSyntax sigField) - { - // Stub should have at least one containing type - Debug.Assert(stub.StubContainingTypes.Any()); - - // Add stub function and JSExport declaration to the first (innermost) containing - MemberDeclarationSyntax containingType = CreateTypeDeclarationWithoutTrivia(stub.StubContainingTypes.First()) - .AddMembers(stubMethod, sigField); - - // Add type to the remaining containing types (skipping the first which was handled above) - foreach (TypeDeclarationSyntax typeDecl in stub.StubContainingTypes.Skip(1)) - { - containingType = CreateTypeDeclarationWithoutTrivia(typeDecl) - .WithMembers(SingletonList(containingType)); - } - - MemberDeclarationSyntax toPrint = containingType; - - // Add type to the containing namespace - if (stub.StubTypeNamespace is not null) - { - toPrint = NamespaceDeclaration(IdentifierName(stub.StubTypeNamespace)) - .AddMembers(toPrint); - } + MemberDeclarationSyntax toPrint = containingSyntaxContext.WrapMembersInContainingSyntaxWithUnsafeModifier(wrappperMethod, registerMethod); return toPrint; } @@ -286,7 +240,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou // Generate stub code var stubGenerator = new JSExportCodeGenerator( incrementalContext.Environment, - incrementalContext.SignatureContext.ElementTypeInformation, + incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSExportData, incrementalContext.SignatureContext, (elementInfo, ex) => @@ -298,7 +252,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax wrapper = stubGenerator.GenerateJSExportBody(); BlockSyntax registration = stubGenerator.GenerateJSExportRegistration(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, wrapper, registration), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratedStatements.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratedStatements.cs deleted file mode 100644 index 1a74113580dadb..00000000000000 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratedStatements.cs +++ /dev/null @@ -1,126 +0,0 @@ -// 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; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Microsoft.Interop.JavaScript -{ - internal struct JSGeneratedStatements - { - public ImmutableArray Setup { get; init; } - public ImmutableArray Marshal { get; init; } - public ImmutableArray Pin { get; init; } - public ImmutableArray PinnedMarshal { get; init; } - public ImmutableArray InvokeStatements { get; init; } - public ImmutableArray Unmarshal { get; init; } - public ImmutableArray NotifyForSuccessfulInvoke { get; init; } - public ImmutableArray GuaranteedUnmarshal { get; init; } - public ImmutableArray Cleanup { get; init; } - - public static JSGeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context, StatementSyntax statementToInvoke) - { - return new JSGeneratedStatements - { - Setup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Setup }), - Marshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Marshal }), - Pin = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Pin }).Cast().ToImmutableArray(), - PinnedMarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.PinnedMarshal }), - InvokeStatements = GenerateStatementForNativeInvoke(marshallers, context with { CurrentStage = StubCodeContext.Stage.Invoke }, statementToInvoke), - Unmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.UnmarshalCapture }) - .AddRange(GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Unmarshal })), - NotifyForSuccessfulInvoke = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.NotifyForSuccessfulInvoke }), - GuaranteedUnmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.GuaranteedUnmarshal }), - Cleanup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Cleanup }), - }; - } - - private static ImmutableArray GenerateStatementsForStubContext(BoundGenerators marshallers, StubCodeContext context) - { - ImmutableArray.Builder statementsToUpdate = ImmutableArray.CreateBuilder(); - if (marshallers.NativeReturnMarshaller.TypeInfo.ManagedType != SpecialTypeInfo.Void && (context.CurrentStage is StubCodeContext.Stage.Setup or StubCodeContext.Stage.Cleanup)) - { - IEnumerable retStatements = marshallers.NativeReturnMarshaller.Generator.Generate(marshallers.NativeReturnMarshaller.TypeInfo, context); - statementsToUpdate.AddRange(retStatements); - } - - if (context.CurrentStage is StubCodeContext.Stage.UnmarshalCapture or StubCodeContext.Stage.Unmarshal or StubCodeContext.Stage.GuaranteedUnmarshal) - { - // For Unmarshal and GuaranteedUnmarshal stages, use the topologically sorted - // marshaller list to generate the marshalling statements - - foreach (BoundGenerator marshaller in marshallers.AllMarshallers) - { - statementsToUpdate.AddRange(marshaller.Generator.Generate(marshaller.TypeInfo, context)); - } - } - else - { - // Generate code for each parameter for the current stage in declaration order. - foreach (BoundGenerator marshaller in marshallers.NativeParameterMarshallers) - { - IEnumerable generatedStatements = marshaller.Generator.Generate(marshaller.TypeInfo, context); - statementsToUpdate.AddRange(generatedStatements); - } - } - - if (statementsToUpdate.Count > 0) - { - // Comment separating each stage - SyntaxTriviaList newLeadingTrivia = GenerateStageTrivia(context.CurrentStage); - StatementSyntax firstStatementInStage = statementsToUpdate[0]; - newLeadingTrivia = newLeadingTrivia.AddRange(firstStatementInStage.GetLeadingTrivia()); - statementsToUpdate[0] = firstStatementInStage.WithLeadingTrivia(newLeadingTrivia); - } - return statementsToUpdate.ToImmutable(); - } - - private static ImmutableArray GenerateStatementForNativeInvoke(BoundGenerators marshallers, StubCodeContext context, StatementSyntax statementToInvoke) - { - if (context.CurrentStage != StubCodeContext.Stage.Invoke) - { - throw new ArgumentException("CurrentStage must be Invoke"); - } - - ImmutableArray.Builder statementsToUpdate = ImmutableArray.CreateBuilder(); - - foreach (BoundGenerator marshaller in marshallers.NativeParameterMarshallers) - { - IEnumerable generatedStatements = marshaller.Generator.Generate(marshaller.TypeInfo, context); - statementsToUpdate.AddRange(generatedStatements); - } - - statementsToUpdate.Add(statementToInvoke); - - return statementsToUpdate.ToImmutable(); - } - - private static SyntaxTriviaList GenerateStageTrivia(StubCodeContext.Stage stage) - { - string comment = stage switch - { - StubCodeContext.Stage.Setup => "Perform required setup.", - StubCodeContext.Stage.Marshal => "Convert managed data to native data.", - StubCodeContext.Stage.Pin => "Pin data in preparation for calling the P/Invoke.", - StubCodeContext.Stage.PinnedMarshal => "Convert managed data to native data that requires the managed data to be pinned.", - StubCodeContext.Stage.Invoke => "Call the P/Invoke.", - StubCodeContext.Stage.UnmarshalCapture => "Capture the native data into marshaller instances in case conversion to managed data throws an exception.", - StubCodeContext.Stage.Unmarshal => "Convert native data to managed data.", - StubCodeContext.Stage.Cleanup => "Perform required cleanup.", - StubCodeContext.Stage.NotifyForSuccessfulInvoke => "Keep alive any managed objects that need to stay alive across the call.", - StubCodeContext.Stage.GuaranteedUnmarshal => "Convert native data to managed data even in the case of an exception during the non-cleanup phases.", - _ => throw new ArgumentOutOfRangeException(nameof(stage)) - }; - - // Comment separating each stage - return TriviaList(Comment($"// {stage} - {comment}")); - } - } -} 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 9c10b08ef87570..b7c1a324b2c477 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs @@ -77,7 +77,7 @@ IMarshallingGenerator CreateGenerator(TypePositionInfo p) public BlockSyntax GenerateJSImportBody() { StatementSyntax invoke = InvokeSyntax(); - JSGeneratedStatements statements = JSGeneratedStatements.Create(_marshallers, _context, invoke); + GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToNative(_marshallers, _context, shouldInitializeVariables); @@ -96,8 +96,9 @@ public BlockSyntax GenerateJSImportBody() var tryStatements = new List(); tryStatements.AddRange(statements.Marshal); + tryStatements.AddRange(statements.PinnedMarshal); - tryStatements.AddRange(statements.InvokeStatements); + tryStatements.Add(invoke); if (!statements.GuaranteedUnmarshal.IsEmpty) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, 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 1d4ef3812b6401..0ce77445a85a8b 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -146,25 +146,17 @@ private static SyntaxTokenList StripTriviaFromModifiers(SyntaxTokenList tokenLis return new SyntaxTokenList(strippedTokens); } - private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDeclarationSyntax typeDeclaration) - { - return TypeDeclaration( - typeDeclaration.Kind(), - typeDeclaration.Identifier) - .WithTypeParameterList(typeDeclaration.TypeParameterList) - .WithModifiers(StripTriviaFromModifiers(typeDeclaration.Modifiers)); - } - private static MemberDeclarationSyntax PrintGeneratedSource( ContainingSyntax userDeclaredMethod, JSSignatureContext stub, + ContainingSyntaxContext containingSyntaxContext, BlockSyntax stubCode) { // Create stub function - MethodDeclarationSyntax stubMethod = MethodDeclaration(stub.StubReturnType, userDeclaredMethod.Identifier) - .AddAttributeLists(stub.AdditionalAttributes.ToArray()) + MethodDeclarationSyntax stubMethod = MethodDeclaration(stub.SignatureContext.StubReturnType, userDeclaredMethod.Identifier) + .AddAttributeLists(stub.SignatureContext.AdditionalAttributes.ToArray()) .WithModifiers(StripTriviaFromModifiers(userDeclaredMethod.Modifiers)) - .WithParameterList(ParameterList(SeparatedList(stub.StubParameters))) + .WithParameterList(ParameterList(SeparatedList(stub.SignatureContext.StubParameters))) .WithBody(stubCode); FieldDeclarationSyntax sigField = FieldDeclaration(VariableDeclaration(IdentifierName(Constants.JSFunctionSignatureGlobal)) @@ -173,35 +165,7 @@ private static MemberDeclarationSyntax PrintGeneratedSource( .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList( Attribute(IdentifierName(Constants.ThreadStaticGlobal)))))); - MemberDeclarationSyntax toPrint = WrapMethodInContainingScopes(stub, stubMethod, sigField); - return toPrint; - } - - private static MemberDeclarationSyntax WrapMethodInContainingScopes(JSSignatureContext stub, MemberDeclarationSyntax stubMethod, MemberDeclarationSyntax sigField) - { - // Stub should have at least one containing type - Debug.Assert(stub.StubContainingTypes.Any()); - - // Add stub function and JSImport declaration to the first (innermost) containing - MemberDeclarationSyntax containingType = CreateTypeDeclarationWithoutTrivia(stub.StubContainingTypes.First()) - .AddMembers(stubMethod, sigField); - - // Add type to the remaining containing types (skipping the first which was handled above) - foreach (TypeDeclarationSyntax typeDecl in stub.StubContainingTypes.Skip(1)) - { - containingType = CreateTypeDeclarationWithoutTrivia(typeDecl) - .WithMembers(SingletonList(containingType)); - } - - MemberDeclarationSyntax toPrint = containingType; - - // Add type to the containing namespace - if (stub.StubTypeNamespace is not null) - { - toPrint = NamespaceDeclaration(IdentifierName(stub.StubTypeNamespace)) - .AddMembers(toPrint); - } - + MemberDeclarationSyntax toPrint = containingSyntaxContext.WrapMembersInContainingSyntaxWithUnsafeModifier(stubMethod, sigField); return toPrint; } @@ -290,7 +254,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou // Generate stub code var stubGenerator = new JSImportCodeGenerator( incrementalContext.Environment, - incrementalContext.SignatureContext.ElementTypeInformation, + incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSImportData, incrementalContext.SignatureContext, (elementInfo, ex) => @@ -301,7 +265,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax code = stubGenerator.GenerateJSImportBody(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, code), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs deleted file mode 100644 index ad8d837df24000..00000000000000 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs +++ /dev/null @@ -1,256 +0,0 @@ -// 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.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading; - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Microsoft.Interop.JavaScript -{ - internal sealed class JSSignatureContext : IEquatable - { - private static SymbolDisplayFormat s_typeNameFormat { get; } = new SymbolDisplayFormat( - globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes - ); - - internal static readonly string GeneratorName = typeof(JSImportGenerator).Assembly.GetName().Name; - - internal static readonly string GeneratorVersion = typeof(JSImportGenerator).Assembly.GetName().Version.ToString(); - internal static bool MethodIsSkipLocalsInit(StubEnvironment env, IMethodSymbol method) - { - if (env.ModuleSkipLocalsInit) - { - return true; - } - - if (method.GetAttributes().Any(IsSkipLocalsInitAttribute)) - { - return true; - } - - for (INamedTypeSymbol type = method.ContainingType; type is not null; type = type.ContainingType) - { - if (type.GetAttributes().Any(IsSkipLocalsInitAttribute)) - { - return true; - } - } - - // We check the module case earlier, so we don't need to do it here. - - return false; - - static bool IsSkipLocalsInitAttribute(AttributeData a) - => a.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute; - } - - public static JSSignatureContext Create( - IMethodSymbol method, - StubEnvironment env, - GeneratorDiagnostics diagnostics, - CancellationToken token) - { - // Cancel early if requested - token.ThrowIfCancellationRequested(); - - // Determine the namespace - string? stubTypeNamespace = null; - if (!(method.ContainingNamespace is null) - && !method.ContainingNamespace.IsGlobalNamespace) - { - stubTypeNamespace = method.ContainingNamespace.ToString(); - } - - string stubTypeFullName = ""; - - // Determine containing type(s) - ImmutableArray.Builder containingTypes = ImmutableArray.CreateBuilder(); - INamedTypeSymbol currType = method.ContainingType; - while (!(currType is null)) - { - // Use the declaring syntax as a basis for this type declaration. - // Since we're generating source for the method, we know that the current type - // has to be declared in source. - TypeDeclarationSyntax typeDecl = (TypeDeclarationSyntax)currType.DeclaringSyntaxReferences[0].GetSyntax(token); - // Remove current members, attributes, and base list so we don't double declare them. - typeDecl = typeDecl.WithMembers(List()) - .WithAttributeLists(List()) - .WithBaseList(null); - - containingTypes.Add(typeDecl); - - stubTypeFullName = currType.Name + (string.IsNullOrEmpty(stubTypeFullName) ? "" : ".") + stubTypeFullName; - currType = currType.ContainingType; - } - stubTypeFullName = stubTypeNamespace == null ? stubTypeFullName : (stubTypeNamespace + "." + stubTypeFullName); - - (ImmutableArray typeInfos, IMarshallingGeneratorFactory generatorFactory) = GenerateTypeInformation(method, diagnostics, env); - - ImmutableArray.Builder additionalAttrs = ImmutableArray.CreateBuilder(); - - if (env.TargetFramework != TargetFramework.Unknown) - { - // Define additional attributes for the stub definition. - additionalAttrs.Add( - AttributeList( - SingletonSeparatedList( - Attribute(ParseName(TypeNames.System_CodeDom_Compiler_GeneratedCodeAttribute), - AttributeArgumentList( - SeparatedList( - new[] - { - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(GeneratorName))), - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(GeneratorVersion))) - })))))); - } - - // there could be multiple method signatures with the same name, get unique signature name - uint hash = 17; - unchecked - { - foreach (var param in typeInfos) - { - hash = hash * 31 + (uint)param.ManagedType.FullTypeName.GetHashCode(); - } - }; - int typesHash = Math.Abs((int)hash); - - var fullName = $"{method.ContainingType.ToDisplayString()}.{method.Name}"; - string qualifiedName = GetFullyQualifiedMethodName(env, method); - - return new JSSignatureContext() - { - StubReturnType = method.ReturnType.AsTypeSyntax(), - ElementTypeInformation = typeInfos, - StubTypeNamespace = stubTypeNamespace, - TypesHash = typesHash, - StubTypeFullName = stubTypeFullName, - StubContainingTypes = containingTypes.ToImmutable(), - AdditionalAttributes = additionalAttrs.ToImmutable(), - MethodName = fullName, - QualifiedMethodName = qualifiedName, - BindingName = "__signature_" + method.Name + "_" + typesHash, - GeneratorFactory = generatorFactory - }; - } - - private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSymbol method) - { - // Mono style nested class name format. - string typeName = method.ContainingType.ToDisplayString(s_typeNameFormat).Replace(".", "/"); - - if (!method.ContainingType.ContainingNamespace.IsGlobalNamespace) - typeName = $"{method.ContainingType.ContainingNamespace.ToDisplayString()}.{typeName}"; - - return $"[{env.Compilation.AssemblyName}]{typeName}:{method.Name}"; - } - - private static (ImmutableArray, IMarshallingGeneratorFactory) GenerateTypeInformation(IMethodSymbol method, GeneratorDiagnostics diagnostics, StubEnvironment env) - { - ImmutableArray useSiteAttributeParsers = ImmutableArray.Create(new JSMarshalAsAttributeParser(env.Compilation)); - var jsMarshallingAttributeParser = new MarshallingInfoParser( - diagnostics, - new MethodSignatureElementInfoProvider(env.Compilation, diagnostics, method, useSiteAttributeParsers), - useSiteAttributeParsers, - ImmutableArray.Create(new JSMarshalAsAttributeParser(env.Compilation)), - ImmutableArray.Create(new FallbackJSMarshallingInfoProvider())); - - // Determine parameter and return types - ImmutableArray.Builder typeInfos = ImmutableArray.CreateBuilder(); - for (int i = 0; i < method.Parameters.Length; i++) - { - IParameterSymbol param = method.Parameters[i]; - MarshallingInfo jsMarshallingInfo = jsMarshallingAttributeParser.ParseMarshallingInfo(param.Type, param.GetAttributes()); - - var typeInfo = TypePositionInfo.CreateForParameter(param, jsMarshallingInfo, env.Compilation) with - { - ManagedIndex = i, - NativeIndex = typeInfos.Count, - }; - typeInfos.Add(typeInfo); - } - - MarshallingInfo retJSMarshallingInfo = jsMarshallingAttributeParser.ParseMarshallingInfo(method.ReturnType, method.GetReturnTypeAttributes()); - - var retTypeInfo = new TypePositionInfo(ManagedTypeInfo.CreateTypeInfoForTypeSymbol(method.ReturnType), retJSMarshallingInfo) - { - ManagedIndex = TypePositionInfo.ReturnIndex, - NativeIndex = TypePositionInfo.ReturnIndex, - MarshallingAttributeInfo = retJSMarshallingInfo, - }; - - typeInfos.Add(retTypeInfo); - var jsGeneratorFactory = new JSGeneratorFactory(); - return (typeInfos.ToImmutable(), jsGeneratorFactory); - } - - public ImmutableArray ElementTypeInformation { get; init; } - - public string? StubTypeNamespace { get; init; } - public string? StubTypeFullName { get; init; } - public int TypesHash { get; init; } - - public ImmutableArray StubContainingTypes { get; init; } - - public TypeSyntax StubReturnType { get; init; } - - public IEnumerable StubParameters - { - get - { - foreach (TypePositionInfo typeInfo in ElementTypeInformation) - { - if (typeInfo.ManagedIndex != TypePositionInfo.UnsetIndex - && typeInfo.ManagedIndex != TypePositionInfo.ReturnIndex) - { - yield return Parameter(Identifier(typeInfo.InstanceIdentifier)) - .WithType(typeInfo.ManagedType.Syntax) - .WithModifiers(TokenList(Token(typeInfo.RefKindSyntax))); - } - } - } - } - - public ImmutableArray AdditionalAttributes { get; init; } - - public string MethodName { get; init; } - public string QualifiedMethodName { get; init; } - public string BindingName { get; init; } - - public IMarshallingGeneratorFactory GeneratorFactory { get; init; } - - public override bool Equals(object obj) - { - return obj is JSSignatureContext other && Equals(other); - } - - public bool Equals(JSSignatureContext other) - { - // We don't check if the generator factories are equal since - // the generator factory is deterministically created based on the ElementTypeInformation and Options. - return other is not null - && StubTypeNamespace == other.StubTypeNamespace - && StubTypeFullName == other.StubTypeFullName - && ElementTypeInformation.SequenceEqual(other.ElementTypeInformation) - && StubContainingTypes.SequenceEqual(other.StubContainingTypes, (IEqualityComparer)SyntaxEquivalentComparer.Instance) - && StubReturnType.IsEquivalentTo(other.StubReturnType) - && AdditionalAttributes.SequenceEqual(other.AdditionalAttributes, (IEqualityComparer)SyntaxEquivalentComparer.Instance) - ; - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallAsAttributeInfoParser.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshalAsAttributeInfoParser.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallAsAttributeInfoParser.cs rename to src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshalAsAttributeInfoParser.cs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs new file mode 100644 index 00000000000000..ec2882849cb5d0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs @@ -0,0 +1,96 @@ +// 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.Immutable; +using System.Threading; + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop.JavaScript +{ + internal sealed record JSSignatureContext + { + private static SymbolDisplayFormat TypeAndContainingTypesStyle { get; } = new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes + ); + + private static SymbolDisplayFormat TypeContainingTypesAndNamespacesStyle { get; } = new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); + + internal static readonly string GeneratorName = typeof(JSImportGenerator).Assembly.GetName().Name; + + internal static readonly string GeneratorVersion = typeof(JSImportGenerator).Assembly.GetName().Version.ToString(); + + public SignatureContext SignatureContext { get; private init; } + + public static JSSignatureContext Create( + IMethodSymbol method, + StubEnvironment env, + GeneratorDiagnostics diagnostics, + CancellationToken token) + { + // Cancel early if requested + token.ThrowIfCancellationRequested(); + + ImmutableArray useSiteAttributeParsers = ImmutableArray.Create(new JSMarshalAsAttributeParser(env.Compilation)); + var jsMarshallingAttributeParser = new MarshallingInfoParser( + diagnostics, + new MethodSignatureElementInfoProvider(env.Compilation, diagnostics, method, useSiteAttributeParsers), + useSiteAttributeParsers, + ImmutableArray.Create(new JSMarshalAsAttributeParser(env.Compilation)), + ImmutableArray.Create(new FallbackJSMarshallingInfoProvider())); + SignatureContext sigContext = SignatureContext.Create(method, jsMarshallingAttributeParser, env, typeof(JSImportGenerator).Assembly); + + string stubTypeFullName = method.ContainingType.ToDisplayString(TypeContainingTypesAndNamespacesStyle); + + // there could be multiple method signatures with the same name, get unique signature name + uint hash = 17; + unchecked + { + foreach (var param in sigContext.ElementTypeInformation) + { + hash = hash * 31 + (uint)param.ManagedType.FullTypeName.GetHashCode(); + } + }; + int typesHash = Math.Abs((int)hash); + + var fullName = $"{method.ContainingType.ToDisplayString()}.{method.Name}"; + string qualifiedName = GetFullyQualifiedMethodName(env, method); + + return new JSSignatureContext() + { + SignatureContext = sigContext, + TypesHash = typesHash, + StubTypeFullName = stubTypeFullName, + MethodName = fullName, + QualifiedMethodName = qualifiedName, + BindingName = "__signature_" + method.Name + "_" + typesHash + }; + } + + private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSymbol method) + { + // Mono style nested class name format. + string typeName = method.ContainingType.ToDisplayString(TypeAndContainingTypesStyle).Replace(".", "/"); + + if (!method.ContainingType.ContainingNamespace.IsGlobalNamespace) + typeName = $"{method.ContainingType.ContainingNamespace.ToDisplayString()}.{typeName}"; + + return $"[{env.Compilation.AssemblyName}]{typeName}:{method.Name}"; + } + public string? StubTypeFullName { get; init; } + public int TypesHash { get; init; } + + public string MethodName { get; init; } + public string QualifiedMethodName { get; init; } + public string BindingName { get; init; } + + public override int GetHashCode() + { + throw new UnreachableException(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs index ecbb1fcaa76c9e..fac67d0fc34fb9 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs @@ -53,7 +53,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu .Select(a => a.Syntax) .ToArray(); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source, jsty); } @@ -68,7 +68,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) { yield return ToJSMethod(target, source, jsty); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs index e3920e46765fbd..9bc6f13aa5d4ce 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs @@ -32,7 +32,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu ? Argument(IdentifierName(context.GetIdentifiers(info).native)) : _inner.AsArgument(info, context); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source); } @@ -47,7 +47,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) { yield return ToJSMethod(target, source); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs index df9cee6af62ba2..09aa239cd3ba41 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs @@ -45,7 +45,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu ? Argument(IdentifierName(context.GetIdentifiers(info).native)) : _inner.AsArgument(info, context); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToManagedMethodVoid(target, source) @@ -64,7 +64,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToJSMethodVoid(target, source) 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 be23c9e3e555c5..77855eaee06e4d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -88,7 +88,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo AnyDiagnosticsSink diagnostics = new(); StubEnvironment env = context.Compilation.CreateStubEnvironment(); AttributeData dllImportAttribute = method.GetAttributes().First(attr => attr.AttributeClass.ToDisplayString() == TypeNames.DllImportAttribute); - SignatureContext targetSignatureContext = SignatureContext.Create(method, CreateInteropAttributeDataFromDllImport(dllImportData), env, diagnostics, dllImportAttribute, typeof(ConvertToLibraryImportAnalyzer).Assembly); + SignatureContext targetSignatureContext = SignatureContext.Create(method, DefaultMarshallingInfoParser.Create(env, diagnostics, method, CreateInteropAttributeDataFromDllImport(dllImportData), dllImportAttribute), env, typeof(ConvertToLibraryImportAnalyzer).Assembly); var generatorFactoryKey = LibraryImportGeneratorHelpers.CreateGeneratorFactory(env, new LibraryImportGeneratorOptions(context.Options.AnalyzerConfigOptionsProvider.GlobalOptions)); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DefaultMarshallingInfoParser.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DefaultMarshallingInfoParser.cs new file mode 100644 index 00000000000000..d07cfd88010aeb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DefaultMarshallingInfoParser.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + internal static class DefaultMarshallingInfoParser + { + public static MarshallingInfoParser Create(StubEnvironment env, IGeneratorDiagnostics diagnostics, IMethodSymbol method, InteropAttributeData interopAttributeData, AttributeData unparsedAttributeData) + { + + // Compute the current default string encoding value. + CharEncoding defaultEncoding = CharEncoding.Undefined; + if (interopAttributeData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling)) + { + defaultEncoding = interopAttributeData.StringMarshalling switch + { + StringMarshalling.Utf16 => CharEncoding.Utf16, + StringMarshalling.Utf8 => CharEncoding.Utf8, + StringMarshalling.Custom => CharEncoding.Custom, + _ => CharEncoding.Undefined, // [Compat] Do not assume a specific value + }; + } + else if (interopAttributeData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType)) + { + defaultEncoding = CharEncoding.Custom; + } + + var defaultInfo = new DefaultMarshallingInfo(defaultEncoding, interopAttributeData.StringMarshallingCustomType); + + var useSiteAttributeParsers = ImmutableArray.Create( + new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo), + new MarshalUsingAttributeParser(env.Compilation, diagnostics)); + + return new MarshallingInfoParser( + diagnostics, + new MethodSignatureElementInfoProvider(env.Compilation, diagnostics, method, useSiteAttributeParsers), + useSiteAttributeParsers, + ImmutableArray.Create( + new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo), + new MarshalUsingAttributeParser(env.Compilation, diagnostics), + new NativeMarshallingAttributeParser(env.Compilation, diagnostics)), + ImmutableArray.Create( + new SafeHandleMarshallingInfoProvider(env.Compilation, method.ContainingType), + new ArrayMarshallingInfoProvider(env.Compilation), + new CharMarshallingInfoProvider(defaultInfo), + new StringMarshallingInfoProvider(env.Compilation, diagnostics, unparsedAttributeData, defaultInfo), + new BooleanMarshallingInfoProvider(), + new BlittableTypeMarshallingInfoProvider(env.Compilation))); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index f74db2f8d845ea..221cb32988497c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -312,7 +312,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( } // Create the stub. - var signatureContext = SignatureContext.Create(symbol, libraryImportData, environment, generatorDiagnostics, generatedDllImportAttr, typeof(LibraryImportGenerator).Assembly); + var signatureContext = SignatureContext.Create(symbol, DefaultMarshallingInfoParser.Create(environment, generatorDiagnostics, symbol, libraryImportData, generatedDllImportAttr), environment, typeof(LibraryImportGenerator).Assembly); var containingTypeContext = new ContainingSyntaxContext(originalSyntax); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs index 579dc15739bbf2..567d5c2f024b94 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs @@ -102,5 +102,31 @@ public MemberDeclarationSyntax WrapMemberInContainingSyntaxWithUnsafeModifier(Me } return wrappedMember; } + + public MemberDeclarationSyntax WrapMembersInContainingSyntaxWithUnsafeModifier(params MemberDeclarationSyntax[] members) + { + bool addedUnsafe = false; + MemberDeclarationSyntax? wrappedMember = null; + foreach (var containingType in ContainingSyntax) + { + TypeDeclarationSyntax type = TypeDeclaration(containingType.TypeKind, containingType.Identifier) + .WithModifiers(containingType.Modifiers) + .AddMembers(wrappedMember is not null ? new[] { wrappedMember } : members); + if (!addedUnsafe) + { + type = type.WithModifiers(type.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword)); + } + if (containingType.TypeParameters is not null) + { + type = type.AddTypeParameterListParameters(containingType.TypeParameters.Parameters.ToArray()); + } + wrappedMember = type; + } + if (ContainingNamespace is not null) + { + wrappedMember = NamespaceDeclaration(ParseName(ContainingNamespace)).AddMembers(wrappedMember); + } + return wrappedMember; + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs index 5f46ca36737818..241d4e1ab9acb2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs @@ -25,7 +25,7 @@ public struct GeneratedStatements public ImmutableArray GuaranteedUnmarshal { get; init; } public ImmutableArray Cleanup { get; init; } - public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke) + public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context) { return new GeneratedStatements { @@ -33,7 +33,7 @@ public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeCo Marshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Marshal }), Pin = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Pin }).Cast().ToImmutableArray(), PinnedMarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.PinnedMarshal }), - InvokeStatement = GenerateStatementForNativeInvoke(marshallers, context with { CurrentStage = StubCodeContext.Stage.Invoke }, expressionToInvoke), + InvokeStatement = EmptyStatement(), Unmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.UnmarshalCapture }) .AddRange(GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Unmarshal })), NotifyForSuccessfulInvoke = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.NotifyForSuccessfulInvoke }), @@ -41,6 +41,13 @@ public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeCo Cleanup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Cleanup }), }; } + public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke) + { + return Create(marshallers, context) with + { + InvokeStatement = GenerateStatementForNativeInvoke(marshallers, context with { CurrentStage = StubCodeContext.Stage.Invoke }, expressionToInvoke) + }; + } private static ImmutableArray GenerateStatementsForStubContext(BoundGenerators marshallers, StubCodeContext context) { diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SignatureContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SignatureContext.cs index b9df1831512e7c..ce4cab52f67792 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SignatureContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SignatureContext.cs @@ -53,13 +53,11 @@ public IEnumerable StubParameters public static SignatureContext Create( IMethodSymbol method, - InteropAttributeData interopAttributeData, + MarshallingInfoParser marshallingInfoParser, StubEnvironment env, - IGeneratorDiagnostics diagnostics, - AttributeData signatureWideMarshallingAttributeData, Assembly generatorInfoAssembly) { - ImmutableArray typeInfos = GenerateTypeInformation(method, interopAttributeData, diagnostics, env, signatureWideMarshallingAttributeData); + ImmutableArray typeInfos = GenerateTypeInformation(method, marshallingInfoParser, env); ImmutableArray.Builder additionalAttrs = ImmutableArray.CreateBuilder(); @@ -102,49 +100,9 @@ public static SignatureContext Create( private static ImmutableArray GenerateTypeInformation( IMethodSymbol method, - InteropAttributeData interopAttributeData, - IGeneratorDiagnostics diagnostics, - StubEnvironment env, - AttributeData signatureWideMarshallingAttributeData) + MarshallingInfoParser marshallingInfoParser, + StubEnvironment env) { - // Compute the current default string encoding value. - CharEncoding defaultEncoding = CharEncoding.Undefined; - if (interopAttributeData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling)) - { - defaultEncoding = interopAttributeData.StringMarshalling switch - { - StringMarshalling.Utf16 => CharEncoding.Utf16, - StringMarshalling.Utf8 => CharEncoding.Utf8, - StringMarshalling.Custom => CharEncoding.Custom, - _ => CharEncoding.Undefined, // [Compat] Do not assume a specific value - }; - } - else if (interopAttributeData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType)) - { - defaultEncoding = CharEncoding.Custom; - } - - var defaultInfo = new DefaultMarshallingInfo(defaultEncoding, interopAttributeData.StringMarshallingCustomType); - - var useSiteAttributeParsers = ImmutableArray.Create( - new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo), - new MarshalUsingAttributeParser(env.Compilation, diagnostics)); - - var marshallingInfoParser = new MarshallingInfoParser( - diagnostics, - new MethodSignatureElementInfoProvider(env.Compilation, diagnostics, method, useSiteAttributeParsers), - useSiteAttributeParsers, - ImmutableArray.Create( - new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo), - new MarshalUsingAttributeParser(env.Compilation, diagnostics), - new NativeMarshallingAttributeParser(env.Compilation, diagnostics)), - ImmutableArray.Create( - new SafeHandleMarshallingInfoProvider(env.Compilation, method.ContainingType), - new ArrayMarshallingInfoProvider(env.Compilation), - new CharMarshallingInfoProvider(defaultInfo), - new StringMarshallingInfoProvider(env.Compilation, diagnostics, signatureWideMarshallingAttributeData, defaultInfo), - new BooleanMarshallingInfoProvider(), - new BlittableTypeMarshallingInfoProvider(env.Compilation))); // Determine parameter and return types ImmutableArray.Builder typeInfos = ImmutableArray.CreateBuilder();