22using System . Text ;
33using Microsoft . CodeAnalysis ;
44using Microsoft . CodeAnalysis . CSharp . Syntax ;
5+ using Microsoft . CodeAnalysis . CSharp ; // For GetInterceptableLocation API and InterceptableLocation type
56
67namespace Bunit . Web . Stubs . AddStubMethodStubGenerator ;
78
@@ -50,10 +51,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5051 return null ;
5152 }
5253
53- var path = GetInterceptorFilePath ( context . Node . SyntaxTree , context . SemanticModel . Compilation ) ;
54- var lineSpan = context . SemanticModel . SyntaxTree . GetLineSpan ( context . Node . Span ) ;
55- var line = lineSpan . StartLinePosition . Line + 1 ;
56- var column = lineSpan . Span . Start . Character + context . Node . ToString ( ) . IndexOf ( "AddStub" , StringComparison . Ordinal ) + 1 ;
54+ var interceptableLocation = context . SemanticModel . GetInterceptableLocation ( invocation ) ;
55+ if ( interceptableLocation is null )
56+ {
57+ return null ;
58+ }
5759
5860 var properties = symbol . GetAllMembersRecursively ( )
5961 . OfType < IPropertySymbol > ( )
@@ -67,9 +69,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
6769 TargetTypeNamespace = symbol . ContainingNamespace . ToDisplayString ( ) ,
6870 TargetTypeName = symbol . ToDisplayString ( ) ,
6971 Properties = properties ,
70- Path = path ,
71- Line = line ,
72- Column = column ,
72+ Location = interceptableLocation ,
7373 } ;
7474
7575 static bool IsComponentFactoryStubMethod ( InvocationExpressionSyntax invocation , SemanticModel semanticModel )
@@ -88,11 +88,6 @@ static bool IsComponentFactoryStubMethod(InvocationExpressionSyntax invocation,
8888 return semanticModel . GetSymbolInfo ( invocation ) . Symbol is IMethodSymbol { IsExtensionMethod : true , ReceiverType . Name : "ComponentFactoryCollection" } ;
8989 }
9090
91- static string GetInterceptorFilePath ( SyntaxTree tree , Compilation compilation )
92- {
93- return compilation . Options . SourceReferenceResolver ? . NormalizePath ( tree . FilePath , baseFilePath : null ) ?? tree . FilePath ;
94- }
95-
9691 static bool IsParameterOrCascadingParameter ( ISymbol member )
9792 {
9893 return member . GetAttributes ( ) . Any ( SupportedAttributes . IsSupportedAttribute ) ;
@@ -124,27 +119,21 @@ private static void Execute(ImmutableArray<AddStubClassInfo> classInfos, SourceP
124119
125120 private static void GenerateInterceptorCode ( AddStubClassInfo stubbedComponentGroup , IEnumerable < AddStubClassInfo > stubClassGrouped , SourceProductionContext context )
126121 {
127- // Generate the attribute
128- const string attribute = """
129- namespace System.Runtime.CompilerServices
130- {
131- [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
132- sealed file class InterceptsLocationAttribute : Attribute
133- {
134- public InterceptsLocationAttribute(string filePath, int line, int column)
135- {
136- _ = filePath;
137- _ = line;
138- _ = column;
139- }
140- }
141- }
142- """ ;
143-
144122 // Generate the interceptor
145123 var interceptorSource = new StringBuilder ( 1000 ) ;
146124 interceptorSource . AppendLine ( HeaderProvider . Header ) ;
147- interceptorSource . AppendLine ( attribute ) ;
125+ interceptorSource . AppendLine ( "namespace System.Runtime.CompilerServices" ) ;
126+ interceptorSource . AppendLine ( "{" ) ;
127+ interceptorSource . AppendLine ( "\t [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]" ) ;
128+ interceptorSource . AppendLine ( "\t sealed file class InterceptsLocationAttribute : global::System.Attribute" ) ;
129+ interceptorSource . AppendLine ( "\t {" ) ;
130+ interceptorSource . AppendLine ( "\t \t public InterceptsLocationAttribute(int version, string data)" ) ;
131+ interceptorSource . AppendLine ( "\t \t {" ) ;
132+ interceptorSource . AppendLine ( "\t \t \t _ = version;" ) ;
133+ interceptorSource . AppendLine ( "\t \t \t _ = data;" ) ;
134+ interceptorSource . AppendLine ( "\t \t }" ) ;
135+ interceptorSource . AppendLine ( "\t }" ) ;
136+ interceptorSource . AppendLine ( "}" ) ;
148137 interceptorSource . AppendLine ( ) ;
149138 interceptorSource . AppendLine ( "namespace Bunit" ) ;
150139 interceptorSource . AppendLine ( "{" ) ;
@@ -153,8 +142,7 @@ public InterceptsLocationAttribute(string filePath, int line, int column)
153142
154143 foreach ( var hit in stubClassGrouped )
155144 {
156- interceptorSource . AppendLine (
157- $ "\t \t [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(@\" { hit . Path } \" , { hit . Line } , { hit . Column } )]") ;
145+ interceptorSource . AppendLine ( $ "\t \t { hit . Location . GetInterceptsLocationAttributeSyntax ( ) } ") ;
158146 }
159147
160148 interceptorSource . AppendLine (
@@ -213,9 +201,7 @@ internal sealed record AddStubClassInfo
213201 public required string TargetTypeName { get ; set ; }
214202 public string UniqueQualifier => $ "{ TargetTypeNamespace } .{ StubClassName } ";
215203 public ImmutableArray < StubPropertyInfo > Properties { get ; set ; } = ImmutableArray < StubPropertyInfo > . Empty ;
216- public required string Path { get ; set ; }
217- public int Line { get ; set ; }
218- public int Column { get ; set ; }
204+ public required InterceptableLocation Location { get ; set ; }
219205}
220206
221207internal sealed record StubPropertyInfo
0 commit comments