33using System . Collections . Immutable ;
44using System . Linq ;
55using System . Text ;
6- using System . Text . RegularExpressions ;
76using System . Threading ;
87using System . Xml . Linq ;
8+ using Flow . Launcher . Localization . Shared ;
99using Microsoft . CodeAnalysis ;
1010using Microsoft . CodeAnalysis . CSharp ;
1111using Microsoft . CodeAnalysis . CSharp . Syntax ;
12+ using Microsoft . CodeAnalysis . Diagnostics ;
1213using Microsoft . CodeAnalysis . Text ;
1314
1415namespace Flow . Launcher . Localization . SourceGenerators . Localize
@@ -21,19 +22,6 @@ public partial class LocalizeSourceGenerator : IIncrementalGenerator
2122 {
2223 #region Fields
2324
24- private const string CoreNamespace1 = "Flow.Launcher" ;
25- private const string CoreNamespace2 = "Flow.Launcher.Core" ;
26- private const string DefaultNamespace = "Flow.Launcher" ;
27- private const string ClassName = "Localize" ;
28- private const string PluginInterfaceName = "IPluginI18n" ;
29- private const string PluginContextTypeName = "PluginInitContext" ;
30- private const string systemPrefixUri = "clr-namespace:System;assembly=mscorlib" ;
31- private const string xamlPrefixUri = "http://schemas.microsoft.com/winfx/2006/xaml" ;
32- private const string XamlTag = "String" ;
33- private const string KeyTag = "Key" ;
34-
35- private static readonly Regex _languagesXamlRegex = new Regex ( @"\\Languages\\[^\\]+\.xaml$" , RegexOptions . IgnoreCase ) ;
36-
3725 private static readonly Version PackageVersion = typeof ( LocalizeSourceGenerator ) . Assembly . GetName ( ) . Version ;
3826
3927 private static readonly ImmutableArray < LocalizableString > _emptyLocalizableStrings = ImmutableArray < LocalizableString > . Empty ;
@@ -50,7 +38,7 @@ public partial class LocalizeSourceGenerator : IIncrementalGenerator
5038 public void Initialize ( IncrementalGeneratorInitializationContext context )
5139 {
5240 var xamlFiles = context . AdditionalTextsProvider
53- . Where ( file => _languagesXamlRegex . IsMatch ( file . Path ) ) ;
41+ . Where ( file => Constants . LanguagesXamlRegex . IsMatch ( file . Path ) ) ;
5442
5543 var localizedStrings = xamlFiles
5644 . Select ( ( file , ct ) => ParseXamlFile ( file , ct ) )
@@ -75,7 +63,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7563
7664 var compilation = context . CompilationProvider ;
7765
78- var combined = localizedStrings . Combine ( invocationKeys ) . Combine ( pluginClasses ) . Combine ( compilation ) . Combine ( xamlFiles . Collect ( ) ) ;
66+ var configOptions = context . AnalyzerConfigOptionsProvider ;
67+
68+ var combined = localizedStrings . Combine ( invocationKeys ) . Combine ( pluginClasses ) . Combine ( configOptions ) . Combine ( compilation ) . Combine ( xamlFiles . Collect ( ) ) ;
7969
8070 context . RegisterSourceOutput ( combined , Execute ) ;
8171 }
@@ -86,10 +76,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
8676 /// <param name="spc">The source production context.</param>
8777 /// <param name="data">The provided data.</param>
8878 private void Execute ( SourceProductionContext spc ,
89- ( ( ( ( ImmutableArray < LocalizableString > LocalizableStrings ,
90- ImmutableHashSet < string > InvocationKeys ) ,
91- ImmutableArray < PluginClassInfo > PluginClassInfos ) ,
92- Compilation Compilation ) ,
79+ ( ( ( ( ( ImmutableArray < LocalizableString > LocalizableStrings ,
80+ ImmutableHashSet < string > InvocationKeys ) ,
81+ ImmutableArray < PluginClassInfo > PluginClassInfos ) ,
82+ AnalyzerConfigOptionsProvider ConfigOptionsProvider ) ,
83+ Compilation Compilation ) ,
9384 ImmutableArray < AdditionalText > AdditionalTexts ) data )
9485 {
9586 var xamlFiles = data . AdditionalTexts ;
@@ -103,23 +94,28 @@ private void Execute(SourceProductionContext spc,
10394 }
10495
10596 var compilation = data . Item1 . Compilation ;
106- var pluginClasses = data . Item1 . Item1 . PluginClassInfos ;
107- var usedKeys = data . Item1 . Item1 . Item1 . InvocationKeys ;
108- var localizedStrings = data . Item1 . Item1 . Item1 . LocalizableStrings ;
97+ var configOptions = data . Item1 . Item1 . ConfigOptionsProvider ;
98+ var pluginClasses = data . Item1 . Item1 . Item1 . PluginClassInfos ;
99+ var usedKeys = data . Item1 . Item1 . Item1 . Item1 . InvocationKeys ;
100+ var localizedStrings = data . Item1 . Item1 . Item1 . Item1 . LocalizableStrings ;
109101
110- var assemblyName = compilation . AssemblyName ?? DefaultNamespace ;
102+ var assemblyName = compilation . AssemblyName ?? Constants . DefaultNamespace ;
111103 var optimizationLevel = compilation . Options . OptimizationLevel ;
104+ var useDI = configOptions . GetFLLUseDependencyInjection ( ) ;
112105
113- var pluginInfo = GetValidPluginInfo ( pluginClasses , spc ) ;
114- var isCoreAssembly = assemblyName == CoreNamespace1 || assemblyName == CoreNamespace2 ;
115-
106+ PluginClassInfo pluginInfo = null ;
107+ if ( ! useDI )
108+ {
109+ pluginInfo = GetValidPluginInfo ( pluginClasses , spc ) ;
110+ }
111+
116112 GenerateSource (
117113 spc ,
118114 xamlFiles [ 0 ] ,
119115 localizedStrings ,
120116 optimizationLevel ,
121117 assemblyName ,
122- isCoreAssembly ,
118+ useDI ,
123119 pluginInfo ,
124120 usedKeys ) ;
125121 }
@@ -155,11 +151,11 @@ private static ImmutableArray<LocalizableString> ParseXamlFile(AdditionalText fi
155151 string uri = attr . Value ;
156152 string prefix = attr . Name . LocalName ;
157153
158- if ( uri == systemPrefixUri )
154+ if ( uri == Constants . SystemPrefixUri )
159155 {
160156 systemPrefix = prefix ;
161157 }
162- else if ( uri == xamlPrefixUri )
158+ else if ( uri == Constants . XamlPrefixUri )
163159 {
164160 xamlPrefix = prefix ;
165161 }
@@ -179,14 +175,14 @@ private static ImmutableArray<LocalizableString> ParseXamlFile(AdditionalText fi
179175 }
180176
181177 var localizableStrings = new List < LocalizableString > ( ) ;
182- foreach ( var element in doc . Descendants ( systemNs + XamlTag ) ) // "String" elements in system namespace
178+ foreach ( var element in doc . Descendants ( systemNs + Constants . XamlTag ) ) // "String" elements in system namespace
183179 {
184180 if ( ct . IsCancellationRequested )
185181 {
186182 return _emptyLocalizableStrings ;
187183 }
188184
189- var key = element . Attribute ( xNs + KeyTag ) ? . Value ; // "Key" attribute in xaml namespace
185+ var key = element . Attribute ( xNs + Constants . KeyAttribute ) ? . Value ; // "Key" attribute in xaml namespace
190186 var value = element . Value ;
191187 var comment = element . PreviousNode as XComment ;
192188
@@ -424,7 +420,7 @@ private static string GetLocalizationKeyFromInvocation(GeneratorSyntaxContext co
424420 parts . Reverse ( ) ;
425421
426422 // Check if the first part is ClassName and there's at least one more part
427- if ( parts . Count < 2 || parts [ 0 ] != ClassName )
423+ if ( parts . Count < 2 || parts [ 0 ] != Constants . ClassName )
428424 {
429425 return null ;
430426 }
@@ -440,15 +436,15 @@ private static PluginClassInfo GetPluginClassInfo(GeneratorSyntaxContext context
440436 {
441437 var classDecl = ( ClassDeclarationSyntax ) context . Node ;
442438 var location = GetLocation ( context . SemanticModel . SyntaxTree , classDecl ) ;
443- if ( ! classDecl . BaseList ? . Types . Any ( t => t . Type . ToString ( ) == PluginInterfaceName ) ?? true )
439+ if ( ! classDecl . BaseList ? . Types . Any ( t => t . Type . ToString ( ) == Constants . PluginInterfaceName ) ?? true )
444440 {
445441 // Cannot find class that implements IPluginI18n
446442 return null ;
447443 }
448444
449445 var property = classDecl . Members
450446 . OfType < PropertyDeclarationSyntax > ( )
451- . FirstOrDefault ( p => p . Type . ToString ( ) == PluginContextTypeName ) ;
447+ . FirstOrDefault ( p => p . Type . ToString ( ) == Constants . PluginContextTypeName ) ;
452448 if ( property is null )
453449 {
454450 // Cannot find context
@@ -532,7 +528,7 @@ private static void GenerateSource(
532528 ImmutableArray < LocalizableString > localizedStrings ,
533529 OptimizationLevel optimizationLevel ,
534530 string assemblyName ,
535- bool isCoreAssembly ,
531+ bool useDI ,
536532 PluginClassInfo pluginInfo ,
537533 IEnumerable < string > usedKeys )
538534 {
@@ -560,13 +556,6 @@ private static void GenerateSource(
560556 GeneratedHeaderFromPath ( sourceBuilder , xamlFile . Path ) ;
561557 sourceBuilder . AppendLine ( ) ;
562558
563- // Generate usings
564- if ( isCoreAssembly )
565- {
566- sourceBuilder . AppendLine ( "using Flow.Launcher.Core.Resource;" ) ;
567- sourceBuilder . AppendLine ( ) ;
568- }
569-
570559 // Generate nullable enable
571560 sourceBuilder . AppendLine ( "#nullable enable" ) ;
572561 sourceBuilder . AppendLine ( ) ;
@@ -603,11 +592,26 @@ private static void GenerateSource(
603592
604593 // Generate class
605594 sourceBuilder . AppendLine ( $ "[System.CodeDom.Compiler.GeneratedCode(\" { nameof ( LocalizeSourceGenerator ) } \" , \" { PackageVersion } \" )]") ;
606- sourceBuilder . AppendLine ( $ "public static class { ClassName } ") ;
595+ sourceBuilder . AppendLine ( $ "public static class { Constants . ClassName } ") ;
607596 sourceBuilder . AppendLine ( "{" ) ;
608597
609- // Generate localization methods
610598 var tabString = Spacing ( 1 ) ;
599+
600+ // Generate API instance
601+ string getTranslation = null ;
602+ if ( useDI )
603+ {
604+ sourceBuilder . AppendLine ( $ "{ tabString } private static Flow.Launcher.Plugin.IPublicAPI? api = null;") ;
605+ sourceBuilder . AppendLine ( $ "{ tabString } private static Flow.Launcher.Plugin.IPublicAPI Api => api ??= CommunityToolkit.Mvvm.DependencyInjection.Ioc.Default.GetRequiredService<Flow.Launcher.Plugin.IPublicAPI>();") ;
606+ sourceBuilder . AppendLine ( ) ;
607+ getTranslation = "Api.GetTranslation" ;
608+ }
609+ else if ( pluginInfo ? . IsValid == true )
610+ {
611+ getTranslation = $ "{ pluginInfo . ContextAccessor } .API.GetTranslation";
612+ }
613+
614+ // Generate localization methods
611615 foreach ( var ls in localizedStrings )
612616 {
613617 // TODO: Add support for usedKeys
@@ -617,13 +621,13 @@ private static void GenerateSource(
617621 }*/
618622
619623 GenerateDocComments ( sourceBuilder , ls , tabString ) ;
620- GenerateLocalizationMethod ( sourceBuilder , ls , isCoreAssembly , pluginInfo , tabString ) ;
624+ GenerateLocalizationMethod ( sourceBuilder , ls , getTranslation , tabString ) ;
621625 }
622626
623627 sourceBuilder . AppendLine ( "}" ) ;
624628
625629 // Add source to context
626- spc . AddSource ( $ "{ ClassName } .{ assemblyName } .g.cs", SourceText . From ( sourceBuilder . ToString ( ) , Encoding . UTF8 ) ) ;
630+ spc . AddSource ( $ "{ Constants . ClassName } .{ assemblyName } .g.cs", SourceText . From ( sourceBuilder . ToString ( ) , Encoding . UTF8 ) ) ;
627631 }
628632
629633 private static void GeneratedHeaderFromPath ( StringBuilder sb , string xamlFilePath )
@@ -673,8 +677,7 @@ private static void GenerateDocComments(StringBuilder sb, LocalizableString ls,
673677 private static void GenerateLocalizationMethod (
674678 StringBuilder sb ,
675679 LocalizableString ls ,
676- bool isCoreAssembly ,
677- PluginClassInfo pluginInfo ,
680+ string getTranslation ,
678681 string tabString )
679682 {
680683 sb . Append ( $ "{ tabString } public static string { ls . Key } (") ;
@@ -687,18 +690,8 @@ private static void GenerateLocalizationMethod(
687690 ? $ ", { string . Join ( ", " , parameters . Select ( p => p . Name ) ) } "
688691 : string . Empty ;
689692
690- if ( isCoreAssembly )
691- {
692- var getTranslation = "InternationalizationManager.Instance.GetTranslation" ;
693- sb . AppendLine ( parameters . Count > 0
694- ? ! ls . Format ?
695- $ "string.Format({ getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
696- : $ "string.Format(System.Globalization.CultureInfo.CurrentCulture, { getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
697- : $ "{ getTranslation } (\" { ls . Key } \" );") ;
698- }
699- else if ( pluginInfo ? . IsValid == true )
693+ if ( ! ( string . IsNullOrEmpty ( getTranslation ) ) )
700694 {
701- var getTranslation = $ "{ pluginInfo . ContextAccessor } .API.GetTranslation";
702695 sb . AppendLine ( parameters . Count > 0
703696 ? ! ls . Format ?
704697 $ "string.Format({ getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
0 commit comments