From 348d46376b9a4d8835be49e1dd86b1918f82d276 Mon Sep 17 00:00:00 2001 From: stbychkov Date: Sat, 8 Feb 2025 11:53:10 +0800 Subject: [PATCH] Skipped log calls with generic arguments due to LoggerMessage constraint --- README.md | 1 + .../LogCallParametersExtractorTests.cs | 32 ++++++++++++++++--- .../Extractors/LogCallParametersExtractor.cs | 7 ++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2d26165..ef3f157 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Take a look at [benchmark](https://github.com/stbychkov/AutoLoggerMessage/wiki/B so if you pass more than that, the default `Logger.Log(*, params object[] args)` will be executed. * As this solution is based on interceptors, only .NET 8+ is supported * Hash-based interceptors are incompatible with .NET SDK versions earlier than 8.0.8, most likely due to differences in the compiler version. To resolve this issue, please update your SDK to version [8.0.8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) or later. +* Generic arguments are https://github.com/dotnet/extensions/blob/ca2fe808b3d6c55817467f46ca58657456b4a928/docs/list-of-diagnostics.md?plain=1#L66C4-L66C13. If you pass a generic argument to the log function, the default `Logger.Log(*, params object[] args)` will be executed. ## Is something wrong? diff --git a/src/AutoLoggerMessageGenerator.UnitTests/Extractors/LogCallParametersExtractorTests.cs b/src/AutoLoggerMessageGenerator.UnitTests/Extractors/LogCallParametersExtractorTests.cs index 63f8a70..7f796a5 100644 --- a/src/AutoLoggerMessageGenerator.UnitTests/Extractors/LogCallParametersExtractorTests.cs +++ b/src/AutoLoggerMessageGenerator.UnitTests/Extractors/LogCallParametersExtractorTests.cs @@ -24,14 +24,11 @@ private static void Log( """; var (compilation, syntaxTree) = await CompileSourceCode($"Log({parameters});", extensionDeclaration); - var invocationExpression = syntaxTree.GetRoot().DescendantNodes().OfType().First(); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocationExpression).Symbol!; + var (_, methodSymbol, _) = FindLoggerMethodInvocation(compilation, syntaxTree); var sut = new LogCallParametersExtractor(); - var result = sut.Extract(message, methodSymbol); + var result = sut.Extract(message, methodSymbol!); await Assert.That(result).IsEquivalentTo(new LogCallParameter[] { @@ -144,4 +141,29 @@ await Assert.That(result).IsEquivalentTo(new LogCallParameter[] new("global::System.Int32", "@time", LogCallParameterType.Others), }); } + + [Test] + [Arguments("T")] + [Arguments("List")] + public async Task Extract_WithGenericParameters_ShouldSkipExtractingParameters(string genericType) + { + var message = "{GenericParameter}"; + var (compilation, syntaxTree) = await CompileSourceCode(string.Empty, + $$""" + private static void Log(string {{MessageParameterName}}, T {{ParameterName}}) {} + + public void Foo({{genericType}} arg) + { + Log<{{genericType}}>("{{message}}", arg); + } + """); + var (_, methodSymbol, _) = FindLoggerMethodInvocation(compilation, syntaxTree); + + var sut = new LogCallParametersExtractor(); + + var result = sut.Extract(message, methodSymbol!); + + await Assert.That(result).IsNull(); + } } + diff --git a/src/AutoLoggerMessageGenerator/Extractors/LogCallParametersExtractor.cs b/src/AutoLoggerMessageGenerator/Extractors/LogCallParametersExtractor.cs index 28850d8..6144d1c 100644 --- a/src/AutoLoggerMessageGenerator/Extractors/LogCallParametersExtractor.cs +++ b/src/AutoLoggerMessageGenerator/Extractors/LogCallParametersExtractor.cs @@ -27,6 +27,10 @@ internal class LogCallParametersExtractor(LogPropertiesCheck? logPropertiesCheck if (templateParametersNames.Length < methodParameters.Length) return null; + // https://github.com/dotnet/extensions/blob/ca2fe808b3d6c55817467f46ca58657456b4a928/docs/list-of-diagnostics.md?plain=1#L66C4-L66C13 + if (methodParameters.Any(IsGenericParameter)) + return null; + var uniqueNameSuffix = ReservedParameterNameResolver.GenerateUniqueIdentifierSuffix(templateParametersNames); var utilityParameters = methodSymbol.Parameters @@ -70,4 +74,7 @@ private static LogCallParameter CreateLogCallParameter(ITypeSymbol @nativeType, private static string TransformParameterName(string parameterName) => parameterName.StartsWith("@") ? parameterName : '@' + parameterName; + + private static bool IsGenericParameter(IParameterSymbol parameterSymbol) => + parameterSymbol.Type is INamedTypeSymbol { IsGenericType: true } or ITypeParameterSymbol; }