@@ -59,11 +59,18 @@ private static AddStubClassInfo GetStubClassInfo(GeneratorSyntaxContext context)
5959 var line = lineSpan . StartLinePosition . Line + 1 ;
6060 var column = lineSpan . Span . Start . Character + context . Node . ToString ( ) . IndexOf ( "AddStub" , StringComparison . Ordinal ) + 1 ;
6161
62+ var properties = symbol . GetMembers ( )
63+ . OfType < IPropertySymbol > ( )
64+ . Where ( IsParameterOrCascadingParameter )
65+ . Select ( CreateFromProperty )
66+ . ToImmutableArray ( ) ;
67+
6268 return new AddStubClassInfo
6369 {
6470 StubClassName = $ "{ symbol . Name } Stub",
6571 TargetTypeNamespace = symbol . ContainingNamespace . ToDisplayString ( ) ,
66- TargetType = symbol ,
72+ TargetTypeName = symbol . ToDisplayString ( ) ,
73+ Properties = properties ,
6774 Path = path ,
6875 Line = line ,
6976 Column = column ,
@@ -89,14 +96,31 @@ static string GetInterceptorFilePath(SyntaxTree tree, Compilation compilation)
8996 {
9097 return compilation . Options . SourceReferenceResolver ? . NormalizePath ( tree . FilePath , baseFilePath : null ) ?? tree . FilePath ;
9198 }
99+
100+ static bool IsParameterOrCascadingParameter ( ISymbol member )
101+ {
102+ return member . GetAttributes ( ) . Any ( attr =>
103+ attr . AttributeClass ? . ToDisplayString ( ) == "Microsoft.AspNetCore.Components.ParameterAttribute" ||
104+ attr . AttributeClass ? . ToDisplayString ( ) == "Microsoft.AspNetCore.Components.CascadingParameterAttribute" ) ;
105+ }
106+
107+ static StubPropertyInfo CreateFromProperty ( IPropertySymbol member )
108+ {
109+ return new StubPropertyInfo
110+ {
111+ Name = member . Name ,
112+ Type = member . Type . ToDisplayString ( ) ,
113+ AttributeLine = AttributeLineGenerator . GetAttributeLine ( member ) ,
114+ } ;
115+ }
92116 }
93117
94118 private static void Execute ( ImmutableArray < AddStubClassInfo > classInfos , SourceProductionContext context )
95119 {
96120 foreach ( var stubClassGrouped in classInfos . GroupBy ( c => c . UniqueQualifier ) )
97121 {
98122 var stubbedComponentGroup = stubClassGrouped . First ( ) ;
99- var didStubComponent = StubComponentBuilder . GenerateStubComponent ( stubbedComponentGroup , context ) ;
123+ var didStubComponent = GenerateStubComponent ( stubbedComponentGroup , context ) ;
100124 if ( didStubComponent )
101125 {
102126 GenerateInterceptorCode ( stubbedComponentGroup , stubClassGrouped , context ) ;
@@ -144,22 +168,65 @@ public InterceptsLocationAttribute(string filePath, int line, int column)
144168 interceptorSource . AppendLine ( "\t \t \t where TComponent : global::Microsoft.AspNetCore.Components.IComponent" ) ;
145169 interceptorSource . AppendLine ( "\t \t {" ) ;
146170 interceptorSource . AppendLine (
147- $ "\t \t \t return factories.Add<global::{ stubbedComponentGroup . TargetType . ToDisplayString ( ) } , global::{ stubbedComponentGroup . TargetTypeNamespace } .{ stubbedComponentGroup . StubClassName } >();") ;
171+ $ "\t \t \t return factories.Add<global::{ stubbedComponentGroup . TargetTypeName } , global::{ stubbedComponentGroup . TargetTypeNamespace } .{ stubbedComponentGroup . StubClassName } >();") ;
148172 interceptorSource . AppendLine ( "\t \t }" ) ;
149173 interceptorSource . AppendLine ( "\t }" ) ;
150174 interceptorSource . AppendLine ( "}" ) ;
151175
152176 context . AddSource ( $ "Interceptor{ stubbedComponentGroup . StubClassName } .g.cs", interceptorSource . ToString ( ) ) ;
153177 }
178+
179+ private static bool GenerateStubComponent ( AddStubClassInfo classInfo , SourceProductionContext context )
180+ {
181+ var hasSomethingToStub = false ;
182+ var sourceBuilder = new StringBuilder ( 1000 ) ;
183+
184+ sourceBuilder . AppendLine ( HeaderProvider . Header ) ;
185+ sourceBuilder . AppendLine ( $ "namespace { classInfo . TargetTypeNamespace } ;") ;
186+ sourceBuilder . AppendLine ( ) ;
187+ sourceBuilder . AppendLine ( $ "internal partial class { classInfo . StubClassName } : global::Microsoft.AspNetCore.Components.ComponentBase") ;
188+ sourceBuilder . Append ( "{" ) ;
189+
190+ foreach ( var member in classInfo . Properties )
191+ {
192+ sourceBuilder . AppendLine ( ) ;
193+
194+ hasSomethingToStub = true ;
195+ var propertyType = member . Type ;
196+ var propertyName = member . Name ;
197+
198+ var attributeLine = member . AttributeLine ;
199+ sourceBuilder . AppendLine ( attributeLine ) ;
200+
201+ sourceBuilder . AppendLine ( $ "\t public { propertyType } { propertyName } {{ get; set; }} = default!;") ;
202+ }
203+
204+ sourceBuilder . AppendLine ( "}" ) ;
205+
206+ if ( hasSomethingToStub )
207+ {
208+ context . AddSource ( $ "{ classInfo . StubClassName } .g.cs", sourceBuilder . ToString ( ) ) ;
209+ }
210+
211+ return hasSomethingToStub ;
212+ }
154213}
155214
156- internal sealed class AddStubClassInfo
215+ internal sealed record AddStubClassInfo
157216{
158217 public string StubClassName { get ; set ; }
159218 public string TargetTypeNamespace { get ; set ; }
219+ public string TargetTypeName { get ; set ; }
160220 public string UniqueQualifier => $ "{ TargetTypeNamespace } .{ StubClassName } ";
161- public ITypeSymbol TargetType { get ; set ; }
221+ public ImmutableArray < StubPropertyInfo > Properties { get ; set ; } = ImmutableArray < StubPropertyInfo > . Empty ;
162222 public string Path { get ; set ; }
163223 public int Line { get ; set ; }
164224 public int Column { get ; set ; }
165225}
226+
227+ internal sealed record StubPropertyInfo
228+ {
229+ public string Name { get ; set ; }
230+ public string Type { get ; set ; }
231+ public string AttributeLine { get ; set ; }
232+ }
0 commit comments