99namespace Npgsql . SourceGenerators ;
1010
1111[ Generator ]
12- public class NpgsqlConnectionStringBuilderSourceGenerator : ISourceGenerator
12+ public class NpgsqlConnectionStringBuilderSourceGenerator : IIncrementalGenerator
1313{
1414 static readonly DiagnosticDescriptor InternalError = new DiagnosticDescriptor (
1515 id : "PGXXXX" ,
@@ -19,106 +19,107 @@ public class NpgsqlConnectionStringBuilderSourceGenerator : ISourceGenerator
1919 DiagnosticSeverity . Error ,
2020 isEnabledByDefault : true ) ;
2121
22- public void Initialize ( GeneratorInitializationContext context ) { }
23-
24- public void Execute ( GeneratorExecutionContext context )
22+ public void Initialize ( IncrementalGeneratorInitializationContext context )
2523 {
26- if ( context . Compilation . Assembly . GetTypeByMetadataName ( "Npgsql.NpgsqlConnectionStringBuilder" ) is not { } type )
27- return ;
28-
29- if ( context . Compilation . Assembly . GetTypeByMetadataName ( "Npgsql.NpgsqlConnectionStringPropertyAttribute" ) is not
30- { } connectionStringPropertyAttribute )
31- {
32- context . ReportDiagnostic ( Diagnostic . Create (
33- InternalError ,
34- location : null ,
35- "Could not find Npgsql.NpgsqlConnectionStringPropertyAttribute" ) ) ;
36- return ;
37- }
38-
39- var obsoleteAttribute = context . Compilation . GetTypeByMetadataName ( "System.ObsoleteAttribute" ) ;
40- var displayNameAttribute = context . Compilation . GetTypeByMetadataName ( "System.ComponentModel.DisplayNameAttribute" ) ;
41- var defaultValueAttribute = context . Compilation . GetTypeByMetadataName ( "System.ComponentModel.DefaultValueAttribute" ) ;
42-
43- if ( obsoleteAttribute is null || displayNameAttribute is null || defaultValueAttribute is null )
24+ var compilationProvider = context . CompilationProvider ;
25+ context . RegisterSourceOutput ( compilationProvider , ( spc , compilation ) =>
4426 {
45- context . ReportDiagnostic ( Diagnostic . Create (
46- InternalError ,
47- location : null ,
48- "Could not find ObsoleteAttribute, DisplayNameAttribute or DefaultValueAttribute" ) ) ;
49- return ;
50- }
51-
52- var properties = new List < PropertyDetails > ( ) ;
53- var propertiesByKeyword = new Dictionary < string , PropertyDetails > ( ) ;
54- foreach ( var member in type . GetMembers ( ) )
55- {
56- if ( member is not IPropertySymbol property ||
57- property . GetAttributes ( ) . FirstOrDefault ( a => connectionStringPropertyAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) ) is not { } propertyAttribute ||
58- property . GetAttributes ( )
59- . FirstOrDefault ( a => displayNameAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) )
60- ? . ConstructorArguments [ 0 ] . Value is not string displayName )
27+ var type = compilation . Assembly . GetTypeByMetadataName ( "Npgsql.NpgsqlConnectionStringBuilder" ) ;
28+ if ( type is null )
29+ return ;
30+
31+ var connectionStringPropertyAttribute = compilation . Assembly . GetTypeByMetadataName ( "Npgsql.NpgsqlConnectionStringPropertyAttribute" ) ;
32+ if ( connectionStringPropertyAttribute is null )
6133 {
62- continue ;
34+ spc . ReportDiagnostic ( Diagnostic . Create (
35+ InternalError ,
36+ location : null ,
37+ "Could not find Npgsql.NpgsqlConnectionStringPropertyAttribute" ) ) ;
38+ return ;
6339 }
6440
65- var explicitDefaultValue = property . GetAttributes ( )
66- . FirstOrDefault ( a => defaultValueAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) )
67- ? . ConstructorArguments [ 0 ] . Value ;
68-
69- if ( explicitDefaultValue is string s )
70- explicitDefaultValue = '"' + s . Replace ( "\" " , "\" \" " ) + '"' ;
41+ var obsoleteAttribute = compilation . GetTypeByMetadataName ( "System.ObsoleteAttribute" ) ;
42+ var displayNameAttribute = compilation . GetTypeByMetadataName ( "System.ComponentModel.DisplayNameAttribute" ) ;
43+ var defaultValueAttribute = compilation . GetTypeByMetadataName ( "System.ComponentModel.DefaultValueAttribute" ) ;
7144
72- if ( explicitDefaultValue is not null && property . Type . TypeKind == TypeKind . Enum )
45+ if ( obsoleteAttribute is null || displayNameAttribute is null || defaultValueAttribute is null )
7346 {
74- explicitDefaultValue = $ "({ property . Type . Name } ){ explicitDefaultValue } ";
75- // var foo = property.Type.Name;
76- // explicitDefaultValue += $"/* {foo} */";
47+ spc . ReportDiagnostic ( Diagnostic . Create (
48+ InternalError ,
49+ location : null ,
50+ "Could not find ObsoleteAttribute, DisplayNameAttribute or DefaultValueAttribute" ) ) ;
51+ return ;
7752 }
7853
79- var propertyDetails = new PropertyDetails
54+ var properties = new List < PropertyDetails > ( ) ;
55+ var propertiesByKeyword = new Dictionary < string , PropertyDetails > ( ) ;
56+ foreach ( var member in type . GetMembers ( ) )
8057 {
81- Name = property . Name ,
82- CanonicalName = displayName ,
83- TypeName = property . Type . Name ,
84- IsEnum = property . Type . TypeKind == TypeKind . Enum ,
85- IsObsolete = property . GetAttributes ( ) . Any ( a => obsoleteAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) ) ,
86- DefaultValue = explicitDefaultValue
87- } ;
58+ if ( member is not IPropertySymbol property ||
59+ property . GetAttributes ( ) . FirstOrDefault ( a => connectionStringPropertyAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) ) is not { } propertyAttribute ||
60+ property . GetAttributes ( )
61+ . FirstOrDefault ( a => displayNameAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) )
62+ ? . ConstructorArguments [ 0 ] . Value is not string displayName )
63+ {
64+ continue ;
65+ }
8866
89- properties . Add ( propertyDetails ) ;
67+ var explicitDefaultValue = property . GetAttributes ( )
68+ . FirstOrDefault ( a => defaultValueAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) )
69+ ? . ConstructorArguments [ 0 ] . Value ;
9070
91- propertiesByKeyword [ displayName . ToUpperInvariant ( ) ] = propertyDetails ;
92- if ( property . Name != displayName )
93- {
94- var propertyName = property . Name . ToUpperInvariant ( ) ;
95- if ( ! propertiesByKeyword . ContainsKey ( propertyName ) )
96- propertyDetails . Alternatives . Add ( propertyName ) ;
97- }
71+ if ( explicitDefaultValue is string s )
72+ explicitDefaultValue = '"' + s . Replace ( "\" " , "\" \" " ) + '"' ;
9873
99- if ( propertyAttribute . ConstructorArguments . Length == 1 )
100- {
101- foreach ( var synonymArg in propertyAttribute . ConstructorArguments [ 0 ] . Values )
74+ if ( explicitDefaultValue is not null && property . Type . TypeKind == TypeKind . Enum )
10275 {
103- if ( synonymArg . Value is string synonym )
76+ explicitDefaultValue = $ "({ property . Type . Name } ){ explicitDefaultValue } ";
77+ }
78+
79+ var propertyDetails = new PropertyDetails
80+ {
81+ Name = property . Name ,
82+ CanonicalName = displayName ,
83+ TypeName = property . Type . Name ,
84+ IsEnum = property . Type . TypeKind == TypeKind . Enum ,
85+ IsObsolete = property . GetAttributes ( ) . Any ( a => obsoleteAttribute . Equals ( a . AttributeClass , SymbolEqualityComparer . Default ) ) ,
86+ DefaultValue = explicitDefaultValue
87+ } ;
88+
89+ properties . Add ( propertyDetails ) ;
90+
91+ propertiesByKeyword [ displayName . ToUpperInvariant ( ) ] = propertyDetails ;
92+ if ( property . Name != displayName )
93+ {
94+ var propertyName = property . Name . ToUpperInvariant ( ) ;
95+ if ( ! propertiesByKeyword . ContainsKey ( propertyName ) )
96+ propertyDetails . Alternatives . Add ( propertyName ) ;
97+ }
98+
99+ if ( propertyAttribute . ConstructorArguments . Length == 1 )
100+ {
101+ foreach ( var synonymArg in propertyAttribute . ConstructorArguments [ 0 ] . Values )
104102 {
105- var synonymName = synonym . ToUpperInvariant ( ) ;
106- if ( ! propertiesByKeyword . ContainsKey ( synonymName ) )
107- propertyDetails . Alternatives . Add ( synonymName ) ;
103+ if ( synonymArg . Value is string synonym )
104+ {
105+ var synonymName = synonym . ToUpperInvariant ( ) ;
106+ if ( ! propertiesByKeyword . ContainsKey ( synonymName ) )
107+ propertyDetails . Alternatives . Add ( synonymName ) ;
108+ }
108109 }
109110 }
110111 }
111- }
112112
113- var template = Template . Parse ( EmbeddedResource . GetContent ( "NpgsqlConnectionStringBuilder.snbtxt" ) , "NpgsqlConnectionStringBuilder.snbtxt" ) ;
113+ var template = Template . Parse ( EmbeddedResource . GetContent ( "NpgsqlConnectionStringBuilder.snbtxt" ) , "NpgsqlConnectionStringBuilder.snbtxt" ) ;
114114
115- var output = template . Render ( new
116- {
117- Properties = properties ,
118- PropertiesByKeyword = propertiesByKeyword
119- } ) ;
115+ var output = template . Render ( new
116+ {
117+ Properties = properties ,
118+ PropertiesByKeyword = propertiesByKeyword
119+ } ) ;
120120
121- context . AddSource ( type . Name + ".Generated.cs" , SourceText . From ( output , Encoding . UTF8 ) ) ;
121+ spc . AddSource ( type . Name + ".Generated.cs" , SourceText . From ( output , Encoding . UTF8 ) ) ;
122+ } ) ;
122123 }
123124
124125 sealed class PropertyDetails
0 commit comments