From 8f7fb744758964193ab6a508046ade270d942ca2 Mon Sep 17 00:00:00 2001 From: stbychkov Date: Sat, 4 Jul 2026 11:37:17 +0800 Subject: [PATCH] Fixed extracting log call location for member accessors inside the classes --- .../Mappers/CallLocationMapper.cs | 19 ++++++-- .../LocationContextExtractorTests.cs | 45 +++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/AutoLoggerMessageGenerator/Mappers/CallLocationMapper.cs b/src/AutoLoggerMessageGenerator/Mappers/CallLocationMapper.cs index a15dd14..1ef4a2b 100644 --- a/src/AutoLoggerMessageGenerator/Mappers/CallLocationMapper.cs +++ b/src/AutoLoggerMessageGenerator/Mappers/CallLocationMapper.cs @@ -9,8 +9,8 @@ internal static class CallLocationMapper { public static CallLocation? Map(SemanticModel semanticModel, InvocationExpressionSyntax invocationExpression) { - var memberAccessExpression = invocationExpression.Expression as MemberAccessExpressionSyntax; - if (memberAccessExpression?.Expression is not IdentifierNameSyntax identifierName) + var identifierName = GetIdentifierName(invocationExpression); + if (identifierName is null) return null; var skipSymbols = identifierName.Identifier.ValueText.Length + 1; // obj accessor + dot symbol @@ -37,7 +37,18 @@ internal static class CallLocationMapper return new CallLocation(filePath, line, character, interceptableLocation, location); } - #if PATH_BASED_INTERCEPTORS + private static SimpleNameSyntax? GetIdentifierName(InvocationExpressionSyntax invocationExpression) + { + var memberAccessExpression = invocationExpression.Expression as MemberAccessExpressionSyntax; + return memberAccessExpression?.Expression switch + { + IdentifierNameSyntax i => i, + MemberAccessExpressionSyntax ma => ma.Name, + _ => null + }; + } + +#if PATH_BASED_INTERCEPTORS private static string GeneratePathBasedInterceptableLocation(string filePath, int line, int character) { return $"[{Constants.InterceptorNamespace}.{Constants.InterceptorAttributeName}(" + @@ -46,5 +57,5 @@ private static string GeneratePathBasedInterceptableLocation(string filePath, in $"character: {character}" + $")]"; } - #endif +#endif } diff --git a/tests/AutoLoggerMessageGenerator.UnitTests/Extractors/LocationContextExtractorTests.cs b/tests/AutoLoggerMessageGenerator.UnitTests/Extractors/LocationContextExtractorTests.cs index 3da07e7..2968233 100644 --- a/tests/AutoLoggerMessageGenerator.UnitTests/Extractors/LocationContextExtractorTests.cs +++ b/tests/AutoLoggerMessageGenerator.UnitTests/Extractors/LocationContextExtractorTests.cs @@ -63,4 +63,49 @@ class Foo await Assert.That(className).IsEqualTo("Foo"); await Assert.That(methodName).IsEqualTo(string.Empty); } + + [Test] + public async Task Extract_WithMemberAccessModifier_ShouldReturnExpectedNamespaceAndClassName() + { + const string additionalDeclaration = """ + class Foo + { + private ILogger logger; + private void Bar() => this.logger.LogInformation("Hello world"); + } + """; + var (_, syntaxTree) = await CompileSourceCode(string.Empty, additionalDeclaration); + var (invocationExpression, _, _) = FindMethodInvocation(null, syntaxTree); + + var (ns, className, methodName) = LocationContextExtractor.Extract(invocationExpression); + + await Assert.That(ns).IsEqualTo(Namespace); + await Assert.That(className).IsEqualTo("Foo"); + await Assert.That(methodName).IsEqualTo("Bar"); + } + + [Test] + public async Task Extract_WithNestedMemberAccessModifier_ShouldReturnExpectedNamespaceAndClassName() + { + const string additionalDeclaration = """ + class Outer + { + private readonly Foo foo; + class Foo + { + public ILogger logger; + } + + private void Bar() => this.foo.logger.LogInformation("Hello world"); + } + """; + var (_, syntaxTree) = await CompileSourceCode(string.Empty, additionalDeclaration); + var (invocationExpression, _, _) = FindMethodInvocation(null, syntaxTree); + + var (ns, className, methodName) = LocationContextExtractor.Extract(invocationExpression); + + await Assert.That(ns).IsEqualTo(Namespace); + await Assert.That(className).IsEqualTo("Outer"); + await Assert.That(methodName).IsEqualTo("Bar"); + } }