@@ -44,42 +44,47 @@ public override void Initialize(AnalysisContext context)
44
44
context . ConfigureGeneratedCodeAnalysis ( GeneratedCodeAnalysisFlags . Analyze | GeneratedCodeAnalysisFlags . ReportDiagnostics ) ;
45
45
context . EnableConcurrentExecution ( ) ;
46
46
47
- context . RegisterSymbolAction ( static context =>
47
+ // Defer the callback registration to when the compilation starts, so we can execute more
48
+ // preliminary checks and skip registering any kind of symbol analysis at all if not needed.
49
+ context . RegisterCompilationStartAction ( static context =>
48
50
{
49
- // The possible attribute targets are only fields, classes and methods
50
- if ( context . Symbol is not ( IFieldSymbol or INamedTypeSymbol { TypeKind : TypeKind . Class , IsImplicitlyDeclared : false } or IMethodSymbol ) )
51
+ // Check that the language version is not high enough, otherwise no diagnostic should ever be produced
52
+ if ( context . Compilation . HasLanguageVersionAtLeastEqualTo ( LanguageVersion . CSharp8 ) )
51
53
{
52
54
return ;
53
55
}
54
56
55
- // Check that the language version is not high enough, otherwise no diagnostic should be produced
56
- if ( context . Compilation . HasLanguageVersionAtLeastEqualTo ( LanguageVersion . CSharp8 ) )
57
+ context . RegisterSymbolAction ( static context =>
57
58
{
58
- return ;
59
- }
59
+ // The possible attribute targets are only fields, classes and methods
60
+ if ( context . Symbol is not ( IFieldSymbol or INamedTypeSymbol { TypeKind : TypeKind . Class , IsImplicitlyDeclared : false } or IMethodSymbol ) )
61
+ {
62
+ return ;
63
+ }
60
64
61
- ImmutableArray < AttributeData > attributes = context . Symbol . GetAttributes ( ) ;
65
+ ImmutableArray < AttributeData > attributes = context . Symbol . GetAttributes ( ) ;
62
66
63
- // If the symbol has no attributes, there's nothing left to do
64
- if ( attributes . IsEmpty )
65
- {
66
- return ;
67
- }
67
+ // If the symbol has no attributes, there's nothing left to do
68
+ if ( attributes . IsEmpty )
69
+ {
70
+ return ;
71
+ }
68
72
69
- foreach ( AttributeData attribute in attributes )
70
- {
71
- // Go over each attribute on the target symbol, and check if the attribute type name is a candidate.
72
- // If it is, double check by actually resolving the symbol from the compilation and comparing against it.
73
- // This minimizes the calls to CompilationGetTypeByMetadataName(string) to only cases where it's almost
74
- // guaranteed we'll actually get a match. If we do have one, then we can emit the diagnostic for the symbol.
75
- if ( attribute . AttributeClass is { Name : string attributeName } attributeClass &&
76
- GeneratorAttributeNamesToFullyQualifiedNamesMap . TryGetValue ( attributeName , out string ? fullyQualifiedAttributeName ) &&
77
- context . Compilation . GetTypeByMetadataName ( fullyQualifiedAttributeName ) is INamedTypeSymbol attributeSymbol &&
78
- SymbolEqualityComparer . Default . Equals ( attributeClass , attributeSymbol ) )
73
+ foreach ( AttributeData attribute in attributes )
79
74
{
80
- context . ReportDiagnostic ( Diagnostic . Create ( UnsupportedCSharpLanguageVersionError , context . Symbol . Locations . FirstOrDefault ( ) ) ) ;
75
+ // Go over each attribute on the target symbol, and check if the attribute type name is a candidate.
76
+ // If it is, double check by actually resolving the symbol from the compilation and comparing against it.
77
+ // This minimizes the calls to CompilationGetTypeByMetadataName(string) to only cases where it's almost
78
+ // guaranteed we'll actually get a match. If we do have one, then we can emit the diagnostic for the symbol.
79
+ if ( attribute . AttributeClass is { Name : string attributeName } attributeClass &&
80
+ GeneratorAttributeNamesToFullyQualifiedNamesMap . TryGetValue ( attributeName , out string ? fullyQualifiedAttributeName ) &&
81
+ context . Compilation . GetTypeByMetadataName ( fullyQualifiedAttributeName ) is INamedTypeSymbol attributeSymbol &&
82
+ SymbolEqualityComparer . Default . Equals ( attributeClass , attributeSymbol ) )
83
+ {
84
+ context . ReportDiagnostic ( Diagnostic . Create ( UnsupportedCSharpLanguageVersionError , context . Symbol . Locations . FirstOrDefault ( ) ) ) ;
85
+ }
81
86
}
82
- }
83
- } , SymbolKind . Field , SymbolKind . NamedType , SymbolKind . Method ) ;
87
+ } , SymbolKind . Field , SymbolKind . NamedType , SymbolKind . Method ) ;
88
+ } ) ;
84
89
}
85
90
}
0 commit comments