13
13
14
14
namespace Flow . Launcher . Localization . SourceGenerators . Localize
15
15
{
16
+ /// <summary>
17
+ /// Generates properties for strings based on resource files.
18
+ /// </summary>
16
19
[ Generator ]
17
20
public partial class LocalizeSourceGenerator : IIncrementalGenerator
18
21
{
22
+ #region Fields
23
+
19
24
private const string CoreNamespace1 = "Flow.Launcher" ;
20
25
private const string CoreNamespace2 = "Flow.Launcher.Core" ;
21
26
private const string DefaultNamespace = "Flow.Launcher" ;
22
27
private const string ClassName = "Localize" ;
23
28
private const string PluginInterfaceName = "IPluginI18n" ;
24
29
private const string PluginContextTypeName = "PluginInitContext" ;
25
- private const string XamlTag = "String" ;
26
30
private const string XamlPrefix = "system" ;
27
- private const string DefaultLanguageFilePathEndsWith = @"\Languages\en.xaml" ;
28
- private static readonly Regex s_languagesXamlRegex = new Regex ( @"\\Languages\\[^\\]+\.xaml$" , RegexOptions . IgnoreCase ) ;
31
+ private const string XamlTag = "String" ;
32
+
33
+ private readonly Regex _languagesXamlRegex = new Regex ( @"\\Languages\\[^\\]+\.xaml$" , RegexOptions . IgnoreCase ) ;
34
+
35
+ #endregion
36
+
37
+ #region Incremental Generator
29
38
39
+ /// <summary>
40
+ /// Initializes the generator and registers source output based on resource files.
41
+ /// </summary>
42
+ /// <param name="context">The initialization context.</param>
30
43
public void Initialize ( IncrementalGeneratorInitializationContext context )
31
44
{
32
45
var xamlFiles = context . AdditionalTextsProvider
33
- . Where ( file => s_languagesXamlRegex . IsMatch ( file . Path ) ) ;
46
+ . Where ( file => _languagesXamlRegex . IsMatch ( file . Path ) ) ;
34
47
35
48
var localizedStrings = xamlFiles
36
49
. Select ( ( file , ct ) => ParseXamlFile ( file , ct ) )
@@ -94,78 +107,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
94
107
} ) ;
95
108
}
96
109
97
- private static void GenerateSource (
98
- SourceProductionContext context ,
99
- ImmutableArray < LocalizableString > localizedStrings ,
100
- IEnumerable < string > unusedKeys ,
101
- OptimizationLevel optimizationLevel ,
102
- string assemblyName ,
103
- bool isCoreAssembly ,
104
- PluginClassInfo pluginInfo )
105
- {
106
- var sourceBuilder = new StringBuilder ( ) ;
107
- sourceBuilder . AppendLine ( "// <auto-generated />" ) ;
108
- sourceBuilder . AppendLine ( "#nullable enable" ) ;
109
-
110
- if ( isCoreAssembly )
111
- {
112
- sourceBuilder . AppendLine ( "using Flow.Launcher.Core.Resource;" ) ;
113
- }
114
-
115
- sourceBuilder . AppendLine ( $ "namespace { assemblyName } ;") ;
116
- sourceBuilder . AppendLine ( ) ;
117
- sourceBuilder . AppendLine ( $ "[System.CodeDom.Compiler.GeneratedCode(\" { nameof ( LocalizeSourceGenerator ) } \" , \" 1.0.0\" )]") ;
118
- sourceBuilder . AppendLine ( $ "public static class { ClassName } ") ;
119
- sourceBuilder . AppendLine ( "{" ) ;
120
-
121
- foreach ( var ls in localizedStrings )
122
- {
123
- if ( optimizationLevel == OptimizationLevel . Release && unusedKeys . Contains ( ls . Key ) )
124
- continue ;
125
-
126
- GenerateDocComments ( sourceBuilder , ls ) ;
127
- GenerateLocalizationMethod ( sourceBuilder , ls , isCoreAssembly , pluginInfo ) ;
128
- }
129
-
130
- sourceBuilder . AppendLine ( "}" ) ;
131
-
132
- context . AddSource ( $ "{ ClassName } .g.cs", SourceText . From ( sourceBuilder . ToString ( ) , Encoding . UTF8 ) ) ;
133
- }
134
-
135
- private static void GenerateLocalizationMethod (
136
- StringBuilder sb ,
137
- LocalizableString ls ,
138
- bool isCoreAssembly ,
139
- PluginClassInfo pluginInfo )
140
- {
141
- sb . Append ( $ "public static string { ls . Key } (") ;
142
- var parameters = BuildParameters ( ls ) ;
143
- sb . Append ( string . Join ( ", " , parameters . Select ( p => $ "{ p . Type } { p . Name } ") ) ) ;
144
- sb . Append ( ") => " ) ;
145
-
146
- var formatArgs = parameters . Count > 0
147
- ? $ ", { string . Join ( ", " , parameters . Select ( p => p . Name ) ) } "
148
- : string . Empty ;
149
-
150
- if ( isCoreAssembly )
151
- {
152
- sb . AppendLine ( parameters . Count > 0
153
- ? $ "string.Format(InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
154
- : $ "InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" );") ;
155
- }
156
- else if ( pluginInfo ? . IsValid == true )
157
- {
158
- sb . AppendLine ( parameters . Count > 0
159
- ? $ "string.Format({ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
160
- : $ "{ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" );") ;
161
- }
162
- else
163
- {
164
- sb . AppendLine ( "\" LOCALIZATION_ERROR\" ;" ) ;
165
- }
110
+ #endregion
166
111
167
- sb . AppendLine ( ) ;
168
- }
112
+ #region Parse Xaml File
169
113
170
114
private static ImmutableArray < LocalizableString > ParseXamlFile ( AdditionalText file , CancellationToken ct )
171
115
{
@@ -219,6 +163,10 @@ private static (string Summary, ImmutableArray<LocalizableStringParam> Parameter
219
163
}
220
164
}
221
165
166
+ #endregion
167
+
168
+ #region Get Localization Keys
169
+
222
170
private static string GetLocalizationKeyFromInvocation ( GeneratorSyntaxContext context , CancellationToken ct )
223
171
{
224
172
var invocation = ( InvocationExpressionSyntax ) context . Node ;
@@ -232,6 +180,10 @@ private static string GetLocalizationKeyFromInvocation(GeneratorSyntaxContext co
232
180
return null ;
233
181
}
234
182
183
+ #endregion
184
+
185
+ #region Get Plugin Class Info
186
+
235
187
private static PluginClassInfo GetPluginClassInfo ( GeneratorSyntaxContext context , CancellationToken ct )
236
188
{
237
189
var classDecl = ( ClassDeclarationSyntax ) context . Node ;
@@ -276,19 +228,46 @@ private static PluginClassInfo GetValidPluginInfo(
276
228
return null ;
277
229
}
278
230
279
- private static List < MethodParameter > BuildParameters ( LocalizableString ls )
231
+ #endregion
232
+
233
+ #region Generate Source
234
+
235
+ private static void GenerateSource (
236
+ SourceProductionContext context ,
237
+ ImmutableArray < LocalizableString > localizedStrings ,
238
+ IEnumerable < string > unusedKeys ,
239
+ OptimizationLevel optimizationLevel ,
240
+ string assemblyName ,
241
+ bool isCoreAssembly ,
242
+ PluginClassInfo pluginInfo )
280
243
{
281
- var parameters = new List < MethodParameter > ( ) ;
282
- for ( var i = 0 ; i < 10 ; i ++ )
244
+ var sourceBuilder = new StringBuilder ( ) ;
245
+ sourceBuilder . AppendLine ( "// <auto-generated />" ) ;
246
+ sourceBuilder . AppendLine ( "#nullable enable" ) ;
247
+
248
+ if ( isCoreAssembly )
283
249
{
284
- if ( ! ls . Value . Contains ( $ "{{{i}}}") ) continue ;
250
+ sourceBuilder . AppendLine ( "using Flow.Launcher.Core.Resource;" ) ;
251
+ }
285
252
286
- var param = ls . Params . FirstOrDefault ( p => p . Index == i ) ;
287
- parameters . Add ( param is null
288
- ? new MethodParameter ( $ "arg{ i } ", "object?" )
289
- : new MethodParameter ( param . Name , param . Type ) ) ;
253
+ sourceBuilder . AppendLine ( $ "namespace { assemblyName } ;") ;
254
+ sourceBuilder . AppendLine ( ) ;
255
+ sourceBuilder . AppendLine ( $ "[System.CodeDom.Compiler.GeneratedCode(\" { nameof ( LocalizeSourceGenerator ) } \" , \" 1.0.0\" )]") ;
256
+ sourceBuilder . AppendLine ( $ "public static class { ClassName } ") ;
257
+ sourceBuilder . AppendLine ( "{" ) ;
258
+
259
+ foreach ( var ls in localizedStrings )
260
+ {
261
+ if ( optimizationLevel == OptimizationLevel . Release && unusedKeys . Contains ( ls . Key ) )
262
+ continue ;
263
+
264
+ GenerateDocComments ( sourceBuilder , ls ) ;
265
+ GenerateLocalizationMethod ( sourceBuilder , ls , isCoreAssembly , pluginInfo ) ;
290
266
}
291
- return parameters ;
267
+
268
+ sourceBuilder . AppendLine ( "}" ) ;
269
+
270
+ context . AddSource ( $ "{ ClassName } .g.cs", SourceText . From ( sourceBuilder . ToString ( ) , Encoding . UTF8 ) ) ;
292
271
}
293
272
294
273
private static void GenerateDocComments ( StringBuilder sb , LocalizableString ls )
@@ -307,6 +286,60 @@ private static void GenerateDocComments(StringBuilder sb, LocalizableString ls)
307
286
sb . AppendLine ( "/// </code>" ) ;
308
287
}
309
288
289
+ private static void GenerateLocalizationMethod (
290
+ StringBuilder sb ,
291
+ LocalizableString ls ,
292
+ bool isCoreAssembly ,
293
+ PluginClassInfo pluginInfo )
294
+ {
295
+ sb . Append ( $ "public static string { ls . Key } (") ;
296
+ var parameters = BuildParameters ( ls ) ;
297
+ sb . Append ( string . Join ( ", " , parameters . Select ( p => $ "{ p . Type } { p . Name } ") ) ) ;
298
+ sb . Append ( ") => " ) ;
299
+
300
+ var formatArgs = parameters . Count > 0
301
+ ? $ ", { string . Join ( ", " , parameters . Select ( p => p . Name ) ) } "
302
+ : string . Empty ;
303
+
304
+ if ( isCoreAssembly )
305
+ {
306
+ sb . AppendLine ( parameters . Count > 0
307
+ ? $ "string.Format(InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
308
+ : $ "InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" );") ;
309
+ }
310
+ else if ( pluginInfo ? . IsValid == true )
311
+ {
312
+ sb . AppendLine ( parameters . Count > 0
313
+ ? $ "string.Format({ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
314
+ : $ "{ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" );") ;
315
+ }
316
+ else
317
+ {
318
+ sb . AppendLine ( "\" LOCALIZATION_ERROR\" ;" ) ;
319
+ }
320
+
321
+ sb . AppendLine ( ) ;
322
+ }
323
+
324
+ private static List < MethodParameter > BuildParameters ( LocalizableString ls )
325
+ {
326
+ var parameters = new List < MethodParameter > ( ) ;
327
+ for ( var i = 0 ; i < 10 ; i ++ )
328
+ {
329
+ if ( ! ls . Value . Contains ( $ "{{{i}}}") ) continue ;
330
+
331
+ var param = ls . Params . FirstOrDefault ( p => p . Index == i ) ;
332
+ parameters . Add ( param is null
333
+ ? new MethodParameter ( $ "arg{ i } ", "object?" )
334
+ : new MethodParameter ( param . Name , param . Type ) ) ;
335
+ }
336
+ return parameters ;
337
+ }
338
+
339
+ #endregion
340
+
341
+ #region Classes
342
+
310
343
public class MethodParameter
311
344
{
312
345
public string Name { get ; }
@@ -364,5 +397,7 @@ public PluginClassInfo(string className, string propertyName, bool isValid)
364
397
IsValid = isValid ;
365
398
}
366
399
}
400
+
401
+ #endregion
367
402
}
368
403
}
0 commit comments