1+ using System . Collections . Immutable ;
12using System . Linq ;
23using System . Text ;
34using Microsoft . CodeAnalysis ;
@@ -18,7 +19,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
1819 . CreateSyntaxProvider (
1920 predicate : static ( s , _ ) => s is InvocationExpressionSyntax ,
2021 transform : static ( ctx , _ ) => GetStubClassInfo ( ctx ) )
21- . Where ( static m => m is not null ) ;
22+ . Where ( static m => m is not null )
23+ . Collect ( ) ;
2224
2325 context . RegisterSourceOutput (
2426 classesToStub ,
@@ -78,17 +80,21 @@ static string GetInterceptorFilePath(SyntaxTree tree, Compilation compilation)
7880 }
7981 }
8082
81- private static void Execute ( StubClassInfo classInfo , SourceProductionContext context )
83+ private static void Execute ( ImmutableArray < StubClassInfo > classInfos , SourceProductionContext context )
8284 {
83- var didStubComponent = GenerateStubComponent ( classInfo , context ) ;
84- if ( didStubComponent is false )
85+ foreach ( var stubClassGrouped in classInfos . GroupBy ( c => c . UniqueQualifier ) )
8586 {
86- return ;
87- }
87+ var stubbedComponentGroup = stubClassGrouped . First ( ) ;
88+ var didStubComponent = GenerateStubComponent ( stubbedComponentGroup , context ) ;
89+ if ( didStubComponent is false )
90+ {
91+ return ;
92+ }
8893
89- // Generate the attribute
90- const string attribute = @"namespace System.Runtime.CompilerServices
94+ // Generate the attribute
95+ const string attribute = @"namespace System.Runtime.CompilerServices
9196{
97+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
9298 sealed file class InterceptsLocationAttribute : Attribute
9399 {
94100 public InterceptsLocationAttribute(string filePath, int line, int column)
@@ -100,25 +106,33 @@ public InterceptsLocationAttribute(string filePath, int line, int column)
100106 }
101107}" ;
102108
103- // Generate the interceptor
104- var interceptorSource = new StringBuilder ( ) ;
105- interceptorSource . AppendLine ( attribute ) ;
106- interceptorSource . AppendLine ( ) ;
107- interceptorSource . AppendLine ( "namespace Bunit" ) ;
108- interceptorSource . AppendLine ( "{" ) ;
109- interceptorSource . AppendLine ( $ "\t static class Interceptor{ classInfo . StubClassName } ") ;
110- interceptorSource . AppendLine ( "\t {" ) ;
111- interceptorSource . AppendLine (
112- $ "\t \t [System.Runtime.CompilerServices.InterceptsLocationAttribute(\" { classInfo . Path } \" , { classInfo . Line } , { classInfo . Column } )]") ;
113- interceptorSource . AppendLine ( "\t \t public static global::Bunit.ComponentFactoryCollection AddGeneratedStubInterceptor<TComponent>(this global::Bunit.ComponentFactoryCollection factories)" ) ;
114- interceptorSource . AppendLine ( "\t \t \t where TComponent : Microsoft.AspNetCore.Components.IComponent" ) ;
115- interceptorSource . AppendLine ( "\t \t {" ) ;
116- interceptorSource . AppendLine ( $ "\t \t \t return factories.Add<global::{ classInfo . TargetType . ToDisplayString ( ) } , { classInfo . TargetTypeNamespace } .{ classInfo . StubClassName } >();") ;
117- interceptorSource . AppendLine ( "\t \t }" ) ;
118- interceptorSource . AppendLine ( "\t }" ) ;
119- interceptorSource . AppendLine ( "}" ) ;
120-
121- context . AddSource ( $ "Interceptor{ classInfo . StubClassName } .g.cs", interceptorSource . ToString ( ) ) ;
109+ // Generate the interceptor
110+ var interceptorSource = new StringBuilder ( ) ;
111+ interceptorSource . AppendLine ( attribute ) ;
112+ interceptorSource . AppendLine ( ) ;
113+ interceptorSource . AppendLine ( "namespace Bunit" ) ;
114+ interceptorSource . AppendLine ( "{" ) ;
115+ interceptorSource . AppendLine ( $ "\t static class Interceptor{ stubbedComponentGroup . StubClassName } ") ;
116+ interceptorSource . AppendLine ( "\t {" ) ;
117+
118+ foreach ( var hit in stubClassGrouped )
119+ {
120+ interceptorSource . AppendLine (
121+ $ "\t \t [System.Runtime.CompilerServices.InterceptsLocationAttribute(\" { hit . Path } \" , { hit . Line } , { hit . Column } )]") ;
122+ }
123+
124+ interceptorSource . AppendLine (
125+ "\t \t public static global::Bunit.ComponentFactoryCollection AddGeneratedStubInterceptor<TComponent>(this global::Bunit.ComponentFactoryCollection factories)" ) ;
126+ interceptorSource . AppendLine ( "\t \t \t where TComponent : Microsoft.AspNetCore.Components.IComponent" ) ;
127+ interceptorSource . AppendLine ( "\t \t {" ) ;
128+ interceptorSource . AppendLine (
129+ $ "\t \t \t return factories.Add<global::{ stubbedComponentGroup . TargetType . ToDisplayString ( ) } , { stubbedComponentGroup . TargetTypeNamespace } .{ stubbedComponentGroup . StubClassName } >();") ;
130+ interceptorSource . AppendLine ( "\t \t }" ) ;
131+ interceptorSource . AppendLine ( "\t }" ) ;
132+ interceptorSource . AppendLine ( "}" ) ;
133+
134+ context . AddSource ( $ "Interceptor{ stubbedComponentGroup . StubClassName } .g.cs", interceptorSource . ToString ( ) ) ;
135+ }
122136 }
123137
124138 private static bool GenerateStubComponent ( StubClassInfo classInfo , SourceProductionContext context )
@@ -172,6 +186,7 @@ internal sealed class StubClassInfo
172186{
173187 public string StubClassName { get ; set ; }
174188 public string TargetTypeNamespace { get ; set ; }
189+ public string UniqueQualifier => $ "{ TargetTypeNamespace } .{ StubClassName } ";
175190 public ITypeSymbol TargetType { get ; set ; }
176191 public string Path { get ; set ; }
177192 public int Line { get ; set ; }
0 commit comments