@@ -13,6 +13,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
13
13
{
14
14
context . RegisterPostInitializationOutput ( EmitConsoleAppTemplateSource ) ;
15
15
16
+ // ConsoleApp.Create(Action<IServiceCollection> configure)
17
+ var hasDependencyInjection = context . MetadataReferencesProvider
18
+ . Where ( x =>
19
+ {
20
+ return x . Display ? . EndsWith ( "Microsoft.Extensions.DependencyInjection.Abstractions.dll" ) ?? false ;
21
+ } )
22
+ . Collect ( )
23
+ . Select ( ( x , ct ) => x . Any ( ) ) ;
24
+
25
+ context . RegisterSourceOutput ( hasDependencyInjection , EmitConsoleAppCreateConfigure ) ;
26
+
16
27
// ConsoleApp.Run
17
28
var runSource = context . SyntaxProvider
18
29
. CreateSyntaxProvider ( ( node , ct ) =>
@@ -81,13 +92,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
81
92
. Where ( x =>
82
93
{
83
94
var model = x . Model . GetTypeInfo ( ( x . Node . Expression as MemberAccessExpressionSyntax ) ! . Expression , x . CancellationToken ) ;
84
- return model . Type ? . Name == "ConsoleAppBuilder" ;
95
+ return model . Type ? . Name is "ConsoleAppBuilder" ;
85
96
} )
86
97
. WithTrackingName ( "ConsoleApp.Builder.1_Where" )
87
98
. Collect ( )
88
99
. Select ( ( x , ct ) => new CollectBuilderContext ( x , ct ) )
89
100
. WithTrackingName ( "ConsoleApp.Builder.2_Collect" ) ;
90
101
102
+ // WIP
103
+ //var registerCommands = context.SyntaxProvider.ForAttributeWithMetadataName("ConsoleAppFramework.RegisterCommandsAttribute",
104
+ // (node, token) => true,
105
+ // (ctx, token) => ctx)
106
+ // .Collect()
107
+ // .Select((x, token) => new CollectBuilderContext(default, token));
108
+
109
+ //var lr = builderSource.Combine(registerCommands); // combine with registerCommands
110
+
91
111
context . RegisterSourceOutput ( builderSource , EmitConsoleAppBuilder ) ;
92
112
}
93
113
@@ -673,26 +693,37 @@ static void EmitConsoleAppBuilder(SourceProductionContext sourceProductionContex
673
693
emitter . EmitHelp ( help , commandIds ! ) ;
674
694
}
675
695
sourceProductionContext . AddSource ( "ConsoleApp.Builder.Help.g.cs" , help . ToString ( ) ) ;
696
+ }
676
697
677
- // emit Create(IServiceCollection) if exists Microsoft.Extensions.DependencyInjection.ServiceCollection
678
- if ( collectBuilderContext . HasDependencyInjectionReference )
698
+ static void EmitConsoleAppCreateConfigure ( SourceProductionContext sourceProductionContext , bool hasDependencyInjection )
699
+ {
700
+ var code = """
701
+ // <auto-generated/>
702
+ #nullable enable
703
+ namespace ConsoleAppFramework;
704
+
705
+ using System;
706
+ using Microsoft.Extensions.DependencyInjection;
707
+
708
+ internal static partial class ConsoleApp
709
+ {
710
+ public static ConsoleAppBuilder Create(Action<IServiceCollection> configure)
711
+ {
712
+ var services = new ServiceCollection();
713
+ configure(services);
714
+ ConsoleApp.ServiceProvider = services.BuildServiceProvider();
715
+ return ConsoleApp.Create();
716
+ }
717
+ }
718
+ """ ;
719
+
720
+ // emit empty if not exists
721
+ if ( ! hasDependencyInjection )
679
722
{
680
- var runBuilder = new SourceBuilder ( 0 ) ;
681
- runBuilder . AppendLine ( GeneratedCodeHeader ) ;
682
- runBuilder . AppendLine ( "using Microsoft.Extensions.DependencyInjection" ) ;
683
- runBuilder . AppendLine ( ) ;
684
- using ( runBuilder . BeginBlock ( "internal static partial class ConsoleApp" ) )
685
- {
686
- using ( runBuilder . BeginBlock ( "public static ConsoleAppBuilder Create(Action<IServiceCollection> configure)" ) )
687
- {
688
- runBuilder . AppendLine ( "var services = new ServiceCollection();" ) ;
689
- runBuilder . AppendLine ( "configure(services);" ) ;
690
- runBuilder . AppendLine ( "ConsoleApp.ServiceProvider = services.BuildServiceProvider();" ) ;
691
- runBuilder . AppendLine ( "return ConsoleApp.Create();" ) ;
692
- }
693
- }
694
- sourceProductionContext . AddSource ( "ConsoleApp.Builder.Run.g.cs" , runBuilder . ToString ( ) ) ;
723
+ code = "" ;
695
724
}
725
+
726
+ sourceProductionContext . AddSource ( "ConsoleApp.Create.g.cs" , code ) ;
696
727
}
697
728
698
729
class CommanContext ( Command ? command , bool isAsync , DiagnosticReporter diagnosticReporter , InvocationExpressionSyntax node ) : IEquatable < CommanContext >
@@ -720,18 +751,12 @@ class CollectBuilderContext : IEquatable<CollectBuilderContext>
720
751
public CancellationToken CancellationToken { get ; }
721
752
public bool HasRun { get ; }
722
753
public bool HasRunAsync { get ; }
723
- public bool HasDependencyInjectionReference { get ; }
724
754
725
755
public CollectBuilderContext ( ImmutableArray < BuilderContext > contexts , CancellationToken cancellationToken )
726
756
{
727
757
this . DiagnosticReporter = new DiagnosticReporter ( ) ;
728
758
this . CancellationToken = cancellationToken ;
729
759
730
- if ( contexts . Length == 0 )
731
- {
732
- return ;
733
- }
734
-
735
760
// validation, invoke in loop is not allowed.
736
761
foreach ( var item in contexts )
737
762
{
@@ -832,18 +857,58 @@ public CollectBuilderContext(ImmutableArray<BuilderContext> contexts, Cancellati
832
857
this . Commands = commands1 . Concat ( commands2 ! ) . ToArray ( ) ! ; // not null if no diagnostics
833
858
this . HasRun = methodGroup [ "Run" ] . Any ( ) ;
834
859
this . HasRunAsync = methodGroup [ "RunAsync" ] . Any ( ) ;
835
-
836
- var model = contexts [ 0 ] . Model ;
837
- var serviceCollectionSymbol = model . Compilation . GetTypeByMetadataName ( "Microsoft.Extensions.DependencyInjection.ServiceCollection" ) ;
838
- this . HasDependencyInjectionReference = serviceCollectionSymbol != null ;
860
+ }
861
+
862
+ // from ForAttributeWithMetadataName
863
+ public void AddRegisterAttributes ( ImmutableArray < GeneratorAttributeSyntaxContext > contexts )
864
+ {
865
+ if ( contexts . Length == 0 )
866
+ {
867
+ return ;
868
+ }
869
+
870
+ //var names = new HashSet<string>();
871
+
872
+ //var commands2 = methodGroup["Add<T>"]
873
+ // .SelectMany(x =>
874
+ // {
875
+ // var wellKnownTypes = new WellKnownTypes(x.Model.Compilation);
876
+ // var parser = new Parser(DiagnosticReporter, x.Node, x.Model, wellKnownTypes, DelegateBuildType.None, globalFilters);
877
+ // var commands = parser.ParseAndValidateForBuilderClassRegistration();
878
+
879
+ // // validation command name duplicate
880
+ // foreach (var command in commands)
881
+ // {
882
+ // if (command != null && !names.Add(command.Name))
883
+ // {
884
+ // DiagnosticReporter.ReportDiagnostic(DiagnosticDescriptors.DuplicateCommandName, x.Node.GetLocation(), command!.Name);
885
+ // return [null];
886
+ // }
887
+ // }
888
+
889
+ // return commands;
890
+ // });
891
+
892
+ //if (DiagnosticReporter.HasDiagnostics)
893
+ //{
894
+ // return;
895
+ //}
896
+
897
+ //// set properties
898
+ //this.Commands = commands1.Concat(commands2!).ToArray()!; // not null if no diagnostics
899
+ //this.HasRun = methodGroup["Run"].Any();
900
+ //this.HasRunAsync = methodGroup["RunAsync"].Any();
901
+
902
+ //var model = contexts[0].Model;
903
+ //var serviceCollectionSymbol = model.Compilation.GetTypeByMetadataName("Microsoft.Extensions.DependencyInjection.ServiceCollection");
904
+ //this.HasDependencyInjectionReference = serviceCollectionSymbol != null;
839
905
}
840
906
841
907
public bool Equals ( CollectBuilderContext other )
842
908
{
843
909
if ( DiagnosticReporter . HasDiagnostics || other . DiagnosticReporter . HasDiagnostics ) return false ;
844
910
if ( HasRun != other . HasRun ) return false ;
845
911
if ( HasRunAsync != other . HasRunAsync ) return false ;
846
- if ( HasDependencyInjectionReference != other . HasDependencyInjectionReference ) return false ;
847
912
848
913
return Commands . AsSpan ( ) . SequenceEqual ( other . Commands ) ;
849
914
}
0 commit comments