@@ -19,6 +19,16 @@ public partial class SelectExprGenerator : IIncrementalGenerator
1919 // Fully qualified metadata name for the LinqraftMappingGenerateAttribute
2020 private const string LinqraftMappingGenerateAttributeFullName =
2121 "Linqraft.LinqraftMappingGenerateAttribute" ;
22+ private const string MappingGenerateMethodNameMissingDiagnosticId = "LINQRAFT001" ;
23+ private static readonly DiagnosticDescriptor MappingGenerateMethodNameMissingDescriptor =
24+ new (
25+ MappingGenerateMethodNameMissingDiagnosticId ,
26+ "LinqraftMappingGenerate requires a method name" ,
27+ "Method '{0}' must specify a mapping method name. Use [LinqraftMappingGenerate(\" MethodName\" )] on methods." ,
28+ "Linqraft" ,
29+ DiagnosticSeverity . Error ,
30+ isEnabledByDefault : true
31+ ) ;
2232
2333 /// <summary>
2434 /// Initialize the generator
@@ -55,6 +65,14 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5565 )
5666 . Where ( static info => info is not null )
5767 . Collect ( ) ;
68+ var mappingMethodDiagnostics = context
69+ . SyntaxProvider . ForAttributeWithMetadataName (
70+ fullyQualifiedMetadataName : LinqraftMappingGenerateAttributeFullName ,
71+ predicate : static ( node , _ ) => node is MethodDeclarationSyntax ,
72+ transform : static ( ctx , _ ) => GetMappingMethodDiagnostic ( ctx )
73+ )
74+ . Where ( static diag => diag is not null )
75+ . Collect ( ) ;
5876
5977 // Provider to detect classes that inherit from LinqraftMappingDeclare<T>
6078 // Using ForAttributeWithMetadataName for performance - now requires [LinqraftMappingGenerate] attribute
@@ -71,18 +89,25 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7189 var invocationsWithConfig = invocations . Combine ( configurationProvider ) ;
7290 var mappingMethodsWithConfig = mappingMethods . Combine ( configurationProvider ) ;
7391 var mappingDeclareClassesWithConfig = mappingDeclareClasses . Combine ( configurationProvider ) ;
92+ var mappingMethodDiagnosticsWithConfig = mappingMethodDiagnostics . Combine (
93+ configurationProvider
94+ ) ;
7495
7596 // Combine all providers
7697 var combinedData = invocationsWithConfig
7798 . Combine ( mappingMethodsWithConfig )
78- . Combine ( mappingDeclareClassesWithConfig ) ;
99+ . Combine ( mappingDeclareClassesWithConfig )
100+ . Combine ( mappingMethodDiagnosticsWithConfig ) ;
79101
80102 // Code generation
81103 context . RegisterSourceOutput (
82104 combinedData ,
83105 ( spc , data ) =>
84106 {
85- var ( ( ( infos , config ) , ( mappingInfos , _) ) , ( mappingDeclareInfos , _) ) = data ;
107+ var (
108+ ( ( ( infos , config ) , ( mappingInfos , _) ) , ( mappingDeclareInfos , _) ) ,
109+ ( mappingDiagnostics , _)
110+ ) = data ;
86111 var infoWithoutNulls = infos . Where ( info => info is not null ) . Select ( info => info ! ) ;
87112 var mappingInfoWithoutNulls = mappingInfos
88113 . Where ( info => info is not null )
@@ -112,6 +137,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
112137 }
113138 }
114139
140+ // Report diagnostics for invalid mapping methods
141+ foreach ( var diagnostic in mappingDiagnostics . Where ( diag => diag is not null ) )
142+ {
143+ spc . ReportDiagnostic ( diagnostic ! ) ;
144+ }
145+
115146 // Combine regular SelectExpr infos with mapping-generated ones
116147 var allInfos = infoWithoutNulls . Concat ( mappingSelectExprInfos ) ;
117148
@@ -559,6 +590,26 @@ GeneratorAttributeSyntaxContext context
559590 } ;
560591 }
561592
593+ private static Diagnostic ? GetMappingMethodDiagnostic ( GeneratorAttributeSyntaxContext context )
594+ {
595+ if ( context . TargetNode is not MethodDeclarationSyntax method )
596+ return null ;
597+
598+ var attributeData = context . Attributes . FirstOrDefault ( ) ;
599+ if ( attributeData is null )
600+ return null ;
601+
602+ var targetMethodName = attributeData . ConstructorArguments . FirstOrDefault ( ) . Value as string ;
603+ if ( ! string . IsNullOrWhiteSpace ( targetMethodName ) )
604+ return null ;
605+
606+ return Diagnostic . Create (
607+ MappingGenerateMethodNameMissingDescriptor ,
608+ method . Identifier . GetLocation ( ) ,
609+ method . Identifier . Text
610+ ) ;
611+ }
612+
562613 /// <summary>
563614 /// Gets mapping declare info from ForAttributeWithMetadataName context.
564615 /// This is more efficient than CreateSyntaxProvider because ForAttributeWithMetadataName
0 commit comments