Strip trivia from tokens. (#88856)
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Fri, 14 Jul 2023 02:10:18 +0000 (19:10 -0700)
committerGitHub <noreply@github.com>
Fri, 14 Jul 2023 02:10:18 +0000 (19:10 -0700)
* Strip trivia from tokens.

Fixes #88798

* Move the trivia stripping into ContainingSyntax record constructor

* Make ContainingSyntax a regular struct with a primary constructor instead of a record struct.

* Fix #88867

* Suppress compiler diagnostics based on the linked issue.

src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs
src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs

index cf64774..b0bfeef 100644 (file)
@@ -206,7 +206,7 @@ namespace Microsoft.Interop.JavaScript
 
             var containingTypeContext = new ContainingSyntaxContext(originalSyntax);
 
-            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
+            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers, SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
 
             return new IncrementalStubGenerationContext(
                 signatureContext,
index 99bdb63..87d0484 100644 (file)
@@ -194,7 +194,7 @@ namespace Microsoft.Interop.JavaScript
 
             var containingTypeContext = new ContainingSyntaxContext(originalSyntax);
 
-            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
+            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers, SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
             return new IncrementalStubGenerationContext(
                 signatureContext,
                 containingTypeContext,
index ddaff90..e1cc737 100644 (file)
@@ -307,7 +307,7 @@ namespace Microsoft.Interop
 
             var containingSyntaxContext = new ContainingSyntaxContext(syntax);
 
-            var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripAccessibilityModifiers().StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList);
+            var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripAccessibilityModifiers(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList);
 
             ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = VirtualMethodPointerStubGenerator.GenerateCallConvSyntaxFromAttributes(
                 suppressGCTransitionAttribute,
index dea2aca..e5faa6f 100644 (file)
@@ -278,7 +278,7 @@ namespace Microsoft.Interop
 
             var containingSyntaxContext = new ContainingSyntaxContext(syntax);
 
-            var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripAccessibilityModifiers().StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList);
+            var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripAccessibilityModifiers(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList);
 
             ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = VirtualMethodPointerStubGenerator.GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultCallingConventions: ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax>.Empty);
 
index 2d61f23..fcd915e 100644 (file)
@@ -288,7 +288,7 @@ namespace Microsoft.Interop
 
             var containingTypeContext = new ContainingSyntaxContext(originalSyntax);
 
-            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
+            var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers, SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList);
 
             List<AttributeSyntax> additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultDllImportSearchPathsAttribute);
             return new IncrementalStubGenerationContext(
index 5902831..1ac5eff 100644 (file)
@@ -12,8 +12,18 @@ using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
 namespace Microsoft.Interop
 {
-    public readonly record struct ContainingSyntax(SyntaxTokenList Modifiers, SyntaxKind TypeKind, SyntaxToken Identifier, TypeParameterListSyntax? TypeParameters)
+    public readonly struct ContainingSyntax(SyntaxTokenList modifiers, SyntaxKind typeKind, SyntaxToken identifier, TypeParameterListSyntax? typeParameters) : IEquatable<ContainingSyntax>
     {
+        public SyntaxTokenList Modifiers { get; init; } = modifiers.StripTriviaFromTokens();
+
+        public SyntaxToken Identifier { get; init; } = identifier.WithoutTrivia();
+
+        public SyntaxKind TypeKind { get; init; } = typeKind;
+
+        public TypeParameterListSyntax? TypeParameters { get; init; } = typeParameters;
+
+        public override bool Equals(object obj) => obj is ContainingSyntax other && Equals(other);
+
         public bool Equals(ContainingSyntax other)
         {
             return Modifiers.SequenceEqual(other.Modifiers, SyntaxEquivalentComparer.Instance)
@@ -42,8 +52,12 @@ namespace Microsoft.Interop
             ImmutableArray<ContainingSyntax>.Builder containingTypeInfoBuilder = ImmutableArray.CreateBuilder<ContainingSyntax>();
             for (SyntaxNode? parent = memberDeclaration.Parent; parent is TypeDeclarationSyntax typeDeclaration; parent = parent.Parent)
             {
-                containingTypeInfoBuilder.Add(new ContainingSyntax(typeDeclaration.Modifiers.StripTriviaFromTokens(), typeDeclaration.Kind(), typeDeclaration.Identifier.WithoutTrivia(),
-                    typeDeclaration.TypeParameterList));
+                containingTypeInfoBuilder.Add(
+                    new ContainingSyntax(
+                        typeDeclaration.Modifiers,
+                        typeDeclaration.Kind(),
+                        typeDeclaration.Identifier,
+                        typeDeclaration.TypeParameterList));
             }
 
             return containingTypeInfoBuilder.ToImmutable();
index b2a3c6a..c4e5f9b 100644 (file)
@@ -558,20 +558,12 @@ namespace ComInterfaceGenerator.Unit.Tests
 
             // [In] is default for all non-pinned marshalled types
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "int", paramNameWithLocation), new DiagnosticResult[] {
-                inAttributeIsDefaultDiagnostic,
-                //https://github.com/dotnet/runtime/issues/88540
                 inAttributeIsDefaultDiagnostic } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "byte", paramNameWithLocation), new DiagnosticResult[] {
-                inAttributeIsDefaultDiagnostic,
-                //https://github.com/dotnet/runtime/issues/88540
                 inAttributeIsDefaultDiagnostic } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] {
-                inAttributeIsDefaultDiagnostic,
-                //https://github.com/dotnet/runtime/issues/88540
                 inAttributeIsDefaultDiagnostic } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U2)]", "char", paramNameWithLocation), new DiagnosticResult[] {
-                inAttributeIsDefaultDiagnostic,
-                //https://github.com/dotnet/runtime/issues/88540
                 inAttributeIsDefaultDiagnostic } };
 
             // [Out] is not allowed on value types passed by value - there is no indirection for the callee to make visible modifications.
@@ -579,48 +571,32 @@ namespace ComInterfaceGenerator.Unit.Tests
                     .WithLocation(0)
                     .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName);
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters } };
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller,
                 new DiagnosticResult[] {
-                    outAttributeNotSupportedOnValueParameters,
-                    //https://github.com/dotnet/runtime/issues/88540
-                    outAttributeNotSupportedOnValueParameters,
+                    outAttributeNotSupportedOnValueParameters
                 } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters
             } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters
             } };
             // [In,Out] should only warn for Out attribute
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters } };
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller,
                 new DiagnosticResult[] {
-                    outAttributeNotSupportedOnValueParameters,
-                    //https://github.com/dotnet/runtime/issues/88540
-                    outAttributeNotSupportedOnValueParameters,
+                    outAttributeNotSupportedOnValueParameters
                 } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters
             } };
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] {
-                outAttributeNotSupportedOnValueParameters,
-                //https://github.com/dotnet/runtime/issues/88540
                 outAttributeNotSupportedOnValueParameters
             } };
 
@@ -688,12 +664,12 @@ namespace ComInterfaceGenerator.Unit.Tests
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute, "string", paramNameWithLocation, (StringMarshalling.Utf8, null)),
-                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic, inAttributeIsDefaultDiagnostic }
+                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic }
             };
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller,
-                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic, inAttributeIsDefaultDiagnostic }
+                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic }
             };
 
             var outNotAllowedOnRefTypes = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
@@ -704,21 +680,21 @@ namespace ComInterfaceGenerator.Unit.Tests
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(outAttribute, "string", paramNameWithLocation, (StringMarshalling.Utf8, null)),
-                new DiagnosticResult[] { outNotAllowedOnRefTypes, outNotAllowedOnRefTypes }
+                new DiagnosticResult[] { outNotAllowedOnRefTypes }
             };
 
             // [Out] warns on by value reference types
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(outAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller,
-                new DiagnosticResult[] { outNotAllowedOnRefTypes, outNotAllowedOnRefTypes }
+                new DiagnosticResult[] { outNotAllowedOnRefTypes }
             };
 
             // [In,Out] is fine on classes
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller,
-                new DiagnosticResult[] { outNotAllowedOnRefTypes, outNotAllowedOnRefTypes }
+                new DiagnosticResult[] { outNotAllowedOnRefTypes }
             };
 
             // All refkinds are okay on classes and strings
@@ -774,11 +750,10 @@ namespace ComInterfaceGenerator.Unit.Tests
                     .WithLocation(0)
                     .WithArguments(SR.InAttributeOnlyNotSupportedOnPinnedParameters, paramName);
             yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "int[]", paramNameWithLocation), new DiagnosticResult[] {
-                inAttributeNotSupportedOnPinnedParameter,
-                //https://github.com/dotnet/runtime/issues/88540
                 inAttributeNotSupportedOnPinnedParameter
             }};
-            // new issue before merge: char generated code doesn't seem to work well with [In, Out]
+            // blittable arrays don't support [In] only. Different diagnostics are issued because we can pin in one direction (managed->unmanaged)
+            // but not the other direction.
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)),
@@ -793,13 +768,13 @@ namespace ComInterfaceGenerator.Unit.Tests
                     "bool[]",
                     paramNameWithLocation,
                     (StringMarshalling.Utf16, null)),
-                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic, inAttributeIsDefaultDiagnostic}
+                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic }
             };
             // Overriding marshalling with a custom marshaller makes it not pinned
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute, "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1), MarshalUsing(ConstantElementCount = 10)]int[]", paramNameWithLocation) + CodeSnippets.IntMarshaller,
-                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic, inAttributeIsDefaultDiagnostic}
+                new DiagnosticResult[] { inAttributeIsDefaultDiagnostic }
             };
 
             // [In, Out] is default
@@ -811,12 +786,12 @@ namespace ComInterfaceGenerator.Unit.Tests
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "int[]", paramNameWithLocation),
-                new DiagnosticResult[] { inOutAttributeIsDefaultDiagnostic, inOutAttributeIsDefaultDiagnostic}
+                new DiagnosticResult[] { inOutAttributeIsDefaultDiagnostic }
             };
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)),
-                //https://github.com/dotnet/runtime/issues/88540
+                //https://github.com/dotnet/runtime/issues/88708
                 new DiagnosticResult[] { inOutAttributeIsDefaultDiagnostic }
             };
 
@@ -847,7 +822,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {
                 TestCode = source,
                 TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
-                // Our fallback mechanism for invalid code for unmanaged->managed stubs sometimes generates invalid code.
+                // https://github.com/dotnet/runtime/issues/88708
                 CompilerDiagnostics = diagnostics.Length != 0 ? CompilerDiagnostics.None : CompilerDiagnostics.Errors,
             };
             test.ExpectedDiagnostics.AddRange(diagnostics);