@@ -75,23 +75,31 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7575 . CreateSyntaxProvider (
7676 static ( node , ct ) => ShouldVisitNode ( node ) ,
7777 static ( context , ct ) =>
78- new
78+ {
79+ MethodDeclarationSyntax syntax = ( MethodDeclarationSyntax ) context . Node ;
80+ if ( context . SemanticModel . GetDeclaredSymbol ( syntax , ct ) is IMethodSymbol methodSymbol
81+ && methodSymbol . GetAttributes ( ) . Any ( static attribute => attribute . AttributeClass ? . ToDisplayString ( ) == TypeNames . GeneratedDllImportAttribute ) )
7982 {
80- Syntax = ( MethodDeclarationSyntax ) context . Node ,
81- Symbol = ( IMethodSymbol ) context . SemanticModel . GetDeclaredSymbol ( context . Node , ct ) !
82- } )
83+ return new { Syntax = syntax , Symbol = methodSymbol } ;
84+ }
85+
86+ return null ;
87+ } )
8388 . Where (
84- static modelData => modelData . Symbol . IsStatic && modelData . Symbol . GetAttributes ( ) . Any (
85- static attribute => attribute . AttributeClass ? . ToDisplayString ( ) == TypeNames . GeneratedDllImportAttribute )
86- ) ;
89+ static modelData => modelData is not null ) ;
8790
88- var methodsToGenerate = attributedMethods . Where ( static data => ! data . Symbol . ReturnsByRef && ! data . Symbol . ReturnsByRefReadonly ) ;
91+ var methodsWithDiagnostics = attributedMethods . Select ( static ( data , ct ) =>
92+ {
93+ Diagnostic ? diagnostic = GetDiagnosticIfInvalidMethodForGeneration ( data . Syntax , data . Symbol ) ;
94+ return new { Syntax = data . Syntax , Symbol = data . Symbol , Diagnostic = diagnostic } ;
95+ } ) ;
8996
90- var refReturnMethods = attributedMethods . Where ( static data => data . Symbol . ReturnsByRef || data . Symbol . ReturnsByRefReadonly ) ;
97+ var methodsToGenerate = methodsWithDiagnostics . Where ( static data => data . Diagnostic is null ) ;
98+ var invalidMethodDiagnostics = methodsWithDiagnostics . Where ( static data => data . Diagnostic is not null ) ;
9199
92- context . RegisterSourceOutput ( refReturnMethods , static ( context , refReturnMethod ) =>
100+ context . RegisterSourceOutput ( invalidMethodDiagnostics , static ( context , invalidMethod ) =>
93101 {
94- context . ReportDiagnostic ( Diagnostic . Create ( GeneratorDiagnostics . ReturnConfigurationNotSupported , refReturnMethod . Syntax . GetLocation ( ) , "ref return" , refReturnMethod . Symbol . ToDisplayString ( ) ) ) ;
102+ context . ReportDiagnostic ( invalidMethod . Diagnostic ) ;
95103 } ) ;
96104
97105 IncrementalValueProvider < ( Compilation compilation , TargetFramework targetFramework , Version targetFrameworkVersion ) > compilationAndTargetFramework = context . CompilationProvider
@@ -739,34 +747,38 @@ private static bool ShouldVisitNode(SyntaxNode syntaxNode)
739747 return false ;
740748 }
741749
742- var methodSyntax = ( MethodDeclarationSyntax ) syntaxNode ;
750+ // Filter out methods with no attributes early.
751+ return ( ( MethodDeclarationSyntax ) syntaxNode ) . AttributeLists . Count > 0 ;
752+ }
743753
754+ private static Diagnostic ? GetDiagnosticIfInvalidMethodForGeneration ( MethodDeclarationSyntax methodSyntax , IMethodSymbol method )
755+ {
744756 // Verify the method has no generic types or defined implementation
745757 // and is marked static and partial.
746758 if ( methodSyntax . TypeParameterList is not null
747759 || methodSyntax . Body is not null
748760 || ! methodSyntax . Modifiers . Any ( SyntaxKind . StaticKeyword )
749761 || ! methodSyntax . Modifiers . Any ( SyntaxKind . PartialKeyword ) )
750762 {
751- return false ;
763+ return Diagnostic . Create ( GeneratorDiagnostics . InvalidAttributedMethodSignature , methodSyntax . Identifier . GetLocation ( ) , method . Name ) ;
752764 }
753765
754766 // Verify that the types the method is declared in are marked partial.
755767 for ( SyntaxNode ? parentNode = methodSyntax . Parent ; parentNode is TypeDeclarationSyntax typeDecl ; parentNode = parentNode . Parent )
756768 {
757769 if ( ! typeDecl . Modifiers . Any ( SyntaxKind . PartialKeyword ) )
758770 {
759- return false ;
771+ return Diagnostic . Create ( GeneratorDiagnostics . InvalidAttributedMethodContainingTypeMissingModifiers , methodSyntax . Identifier . GetLocation ( ) , method . Name , typeDecl . Identifier ) ;
760772 }
761773 }
762774
763- // Filter out methods with no attributes early.
764- if ( methodSyntax . AttributeLists . Count == 0 )
775+ // Verify the method does not have a ref return
776+ if ( method . ReturnsByRef || method . ReturnsByRefReadonly )
765777 {
766- return false ;
778+ return Diagnostic . Create ( GeneratorDiagnostics . ReturnConfigurationNotSupported , methodSyntax . Identifier . GetLocation ( ) , "ref return" , method . ToDisplayString ( ) ) ;
767779 }
768780
769- return true ;
781+ return null ;
770782 }
771783 }
772784}
0 commit comments