@@ -67,44 +67,65 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
67
67
68
68
var compilation = context . CompilationProvider ;
69
69
70
- var combined = localizedStrings . Combine ( invocationKeys ) . Combine ( pluginClasses ) . Combine ( compilation ) ;
70
+ var combined = localizedStrings . Combine ( invocationKeys ) . Combine ( pluginClasses ) . Combine ( compilation ) . Combine ( xamlFiles . Collect ( ) ) ;
71
71
72
- context . RegisterSourceOutput ( combined , ( spc , data ) =>
72
+ context . RegisterSourceOutput ( combined , Execute ) ;
73
+ }
74
+
75
+ /// <summary>
76
+ /// Executes the generation of string properties based on the provided data.
77
+ /// </summary>
78
+ /// <param name="spc">The source production context.</param>
79
+ /// <param name="data">The provided data.</param>
80
+ private void Execute ( SourceProductionContext spc ,
81
+ ( ( ( ( ImmutableArray < LocalizableString > LocalizableStrings ,
82
+ ImmutableHashSet < string > Strings ) ,
83
+ ImmutableArray < PluginClassInfo > PluginClassInfos ) ,
84
+ Compilation Compilation ) ,
85
+ ImmutableArray < AdditionalText > AdditionalTexts ) data )
86
+ {
87
+ var xamlFiles = data . AdditionalTexts ;
88
+ if ( xamlFiles . Length == 0 )
73
89
{
74
- var ( Left , Right ) = data ;
75
- var localizedStringsList = Left . Left . Left ;
76
- var usedKeys = Left . Left . Right ;
77
- var pluginClassesList = Left . Right ;
78
- var compilationData = Right ;
90
+ spc . ReportDiagnostic ( Diagnostic . Create (
91
+ SourceGeneratorDiagnostics . CouldNotFindResourceDictionaries ,
92
+ Location . None
93
+ ) ) ;
94
+ return ;
95
+ }
79
96
80
- var assemblyName = compilationData . AssemblyName ?? DefaultNamespace ;
81
- var optimizationLevel = compilationData . Options . OptimizationLevel ;
97
+ var compilationData = data . Item1 . Compilation ;
98
+ var pluginClassesList = data . Item1 . Item1 . PluginClassInfos ;
99
+ var usedKeys = data . Item1 . Item1 . Item1 . Strings ;
100
+ var localizedStringsList = data . Item1 . Item1 . Item1 . LocalizableStrings ;
82
101
83
- var unusedKeys = localizedStringsList
84
- . Select ( ls => ls . Key )
85
- . ToImmutableHashSet ( )
86
- . Except ( usedKeys ) ;
102
+ var assemblyName = compilationData . AssemblyName ?? DefaultNamespace ;
103
+ var optimizationLevel = compilationData . Options . OptimizationLevel ;
87
104
88
- foreach ( var key in unusedKeys )
89
- {
90
- spc . ReportDiagnostic ( Diagnostic . Create (
91
- SourceGeneratorDiagnostics . LocalizationKeyUnused ,
92
- Location . None ,
93
- key ) ) ;
94
- }
105
+ var unusedKeys = localizedStringsList
106
+ . Select ( ls => ls . Key )
107
+ . ToImmutableHashSet ( )
108
+ . Except ( usedKeys ) ;
95
109
96
- var pluginInfo = GetValidPluginInfo ( pluginClassesList , spc ) ;
97
- var isCoreAssembly = assemblyName == CoreNamespace1 || assemblyName == CoreNamespace2 ;
98
-
99
- GenerateSource (
100
- spc ,
101
- localizedStringsList ,
102
- unusedKeys ,
103
- optimizationLevel ,
104
- assemblyName ,
105
- isCoreAssembly ,
106
- pluginInfo ) ;
107
- } ) ;
110
+ foreach ( var key in unusedKeys )
111
+ {
112
+ spc . ReportDiagnostic ( Diagnostic . Create (
113
+ SourceGeneratorDiagnostics . LocalizationKeyUnused ,
114
+ Location . None ,
115
+ key ) ) ;
116
+ }
117
+
118
+ var pluginInfo = GetValidPluginInfo ( pluginClassesList , spc ) ;
119
+ var isCoreAssembly = assemblyName == CoreNamespace1 || assemblyName == CoreNamespace2 ;
120
+
121
+ GenerateSource (
122
+ spc ,
123
+ localizedStringsList ,
124
+ unusedKeys ,
125
+ optimizationLevel ,
126
+ assemblyName ,
127
+ isCoreAssembly ,
128
+ pluginInfo ) ;
108
129
}
109
130
110
131
#endregion
@@ -187,47 +208,93 @@ private static string GetLocalizationKeyFromInvocation(GeneratorSyntaxContext co
187
208
private static PluginClassInfo GetPluginClassInfo ( GeneratorSyntaxContext context , CancellationToken ct )
188
209
{
189
210
var classDecl = ( ClassDeclarationSyntax ) context . Node ;
211
+ var location = GetLocation ( context . SemanticModel . SyntaxTree , classDecl ) ;
190
212
if ( ! classDecl . BaseList ? . Types . Any ( t => t . Type . ToString ( ) == PluginInterfaceName ) ?? true )
213
+ {
214
+ // Cannot find class that implements IPluginI18n
191
215
return null ;
216
+ }
192
217
193
218
var property = classDecl . Members
194
219
. OfType < PropertyDeclarationSyntax > ( )
195
220
. FirstOrDefault ( p => p . Type . ToString ( ) == PluginContextTypeName ) ;
196
-
197
221
if ( property is null )
198
- return new PluginClassInfo ( classDecl . Identifier . Text , null , false ) ;
222
+ {
223
+ // Cannot find context
224
+ return new PluginClassInfo ( location , classDecl . Identifier . Text , null , false , false , false ) ;
225
+ }
199
226
200
227
var modifiers = property . Modifiers ;
201
- var isValid = modifiers . Any ( SyntaxKind . StaticKeyword ) &&
202
- ! modifiers . Any ( SyntaxKind . PrivateKeyword ) &&
203
- ! modifiers . Any ( SyntaxKind . ProtectedKeyword ) ;
204
-
205
228
return new PluginClassInfo (
229
+ location ,
206
230
classDecl . Identifier . Text ,
207
231
property . Identifier . Text ,
208
- isValid ) ;
232
+ modifiers . Any ( SyntaxKind . StaticKeyword ) ,
233
+ modifiers . Any ( SyntaxKind . PrivateKeyword ) ,
234
+ modifiers . Any ( SyntaxKind . ProtectedKeyword ) ) ;
209
235
}
210
236
211
237
private static PluginClassInfo GetValidPluginInfo (
212
238
ImmutableArray < PluginClassInfo > pluginClasses ,
213
239
SourceProductionContext context )
214
240
{
241
+ if ( pluginClasses . All ( p => p is null || p . PropertyName == null ) )
242
+ {
243
+ context . ReportDiagnostic ( Diagnostic . Create (
244
+ SourceGeneratorDiagnostics . CouldNotFindPluginEntryClass ,
245
+ Location . None
246
+ ) ) ;
247
+ return null ;
248
+ }
249
+
215
250
foreach ( var pluginClass in pluginClasses )
216
251
{
217
- if ( pluginClass ? . IsValid == true )
252
+ if ( pluginClass == null || pluginClass . PropertyName is null )
253
+ {
254
+ continue ;
255
+ }
256
+
257
+ if ( pluginClass . IsValid == true )
258
+ {
218
259
return pluginClass ;
260
+ }
261
+
262
+ if ( ! pluginClass . IsStatic )
263
+ {
264
+ context . ReportDiagnostic ( Diagnostic . Create (
265
+ SourceGeneratorDiagnostics . ContextPropertyNotStatic ,
266
+ pluginClass . Location ,
267
+ pluginClass . PropertyName
268
+ ) ) ;
269
+ }
270
+
271
+ if ( pluginClass . IsPrivate )
272
+ {
273
+ context . ReportDiagnostic ( Diagnostic . Create (
274
+ SourceGeneratorDiagnostics . ContextPropertyIsPrivate ,
275
+ pluginClass . Location ,
276
+ pluginClass . PropertyName
277
+ ) ) ;
278
+ }
219
279
220
- if ( pluginClass . IsValid == false )
280
+ if ( pluginClass . IsProtected )
221
281
{
222
- // TODO
223
- //context.ReportDiagnostic(Diagnostic.Create(
224
- // SourceGeneratorDiagnostics.InvalidPluginConfiguration,
225
- // Location.None));
282
+ context . ReportDiagnostic ( Diagnostic . Create (
283
+ SourceGeneratorDiagnostics . ContextPropertyIsProtected ,
284
+ pluginClass . Location ,
285
+ pluginClass . PropertyName
286
+ ) ) ;
226
287
}
227
288
}
289
+
228
290
return null ;
229
291
}
230
292
293
+ private static Location GetLocation ( SyntaxTree syntaxTree , CSharpSyntaxNode classDeclaration )
294
+ {
295
+ return Location . Create ( syntaxTree , classDeclaration . GetLocation ( ) . SourceSpan ) ;
296
+ }
297
+
231
298
#endregion
232
299
233
300
#region Generate Source
@@ -384,17 +451,24 @@ public LocalizableString(string key, string value, string summary, IEnumerable<L
384
451
385
452
public class PluginClassInfo
386
453
{
454
+ public Location Location { get ; }
387
455
public string ClassName { get ; }
388
456
public string PropertyName { get ; }
389
- public bool IsValid { get ; }
457
+ public bool IsStatic { get ; }
458
+ public bool IsPrivate { get ; }
459
+ public bool IsProtected { get ; }
390
460
391
461
public string ContextAccessor => $ "{ ClassName } .{ PropertyName } ";
462
+ public bool IsValid => PropertyName != null && IsStatic && ( ! IsPrivate ) && ( ! IsProtected ) ;
392
463
393
- public PluginClassInfo ( string className , string propertyName , bool isValid )
464
+ public PluginClassInfo ( Location location , string className , string propertyName , bool isStatic , bool isPrivate , bool isProtected )
394
465
{
466
+ Location = location ;
395
467
ClassName = className ;
396
468
PropertyName = propertyName ;
397
- IsValid = isValid ;
469
+ IsStatic = isStatic ;
470
+ IsPrivate = isPrivate ;
471
+ IsProtected = isProtected ;
398
472
}
399
473
}
400
474
0 commit comments