diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLogging.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLogging.cs index fc51818795cb..730691b4aa96 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLogging.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLogging.cs @@ -110,8 +110,7 @@ private static bool IsPotentiallyExpensive(IOperation? operation) return false; } - if (ICollectionExpressionOperationWrapper.IsInstance(operation) || - operation is IAnonymousObjectCreationOperation or IAwaitOperation or IWithOperation) + if (operation is IAnonymousObjectCreationOperation or IAwaitOperation or IWithOperation) { return true; } @@ -121,14 +120,31 @@ private static bool IsPotentiallyExpensive(IOperation? operation) return !IsTrivialInvocation(invocationOperation); } - if (operation is IObjectCreationOperation { Type.IsReferenceType: true }) + if (operation is IArrayCreationOperation arrayCreationOperation) { + if (IsImplicitParamsArrayCreation(arrayCreationOperation)) + { + return arrayCreationOperation.Initializer?.ElementValues.Any(IsPotentiallyExpensive) is true; + } + return true; } - if (operation is IArrayCreationOperation arrayCreationOperation) + if (ICollectionExpressionOperationWrapper.IsInstance(operation)) + { + var collectionExpression = ICollectionExpressionOperationWrapper.FromOperation(operation); + + if (collectionExpression.WrappedOperation.IsImplicit) + { + return collectionExpression.Elements.Any(IsPotentiallyExpensive); + } + + return true; + } + + if (operation is IObjectCreationOperation { Type.IsReferenceType: true }) { - return !IsEmptyImplicitParamsArrayCreation(arrayCreationOperation); + return true; } if (operation is IConversionOperation conversionOperation) @@ -224,12 +240,10 @@ static bool IsBoxing(IConversionOperation conversionOperation) => conversionOperation.Type?.IsReferenceType is true && conversionOperation.Operand.Type?.IsValueType is true; - static bool IsEmptyImplicitParamsArrayCreation(IArrayCreationOperation arrayCreationOperation) => + static bool IsImplicitParamsArrayCreation(IArrayCreationOperation arrayCreationOperation) => arrayCreationOperation.IsImplicit && arrayCreationOperation.DimensionSizes.Length == 1 && - arrayCreationOperation.DimensionSizes[0].ConstantValue.HasValue && - arrayCreationOperation.DimensionSizes[0].ConstantValue.Value is int size && - size == 0; + arrayCreationOperation.DimensionSizes[0].ConstantValue.HasValue; } internal sealed class RequiredSymbols( diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLoggingTests.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLoggingTests.cs index 8f3259d0eafd..7ecc6e970f67 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLoggingTests.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidPotentiallyExpensiveCallWhenLoggingTests.cs @@ -3103,6 +3103,24 @@ void M(ILogger logger) await VerifyCSharpDiagnosticAsync(source); } + [Fact] + public async Task ImplicitReferenceTypeParamsArrayCreation_NoDiagnostic_CS() + { + string source = """ + using Microsoft.Extensions.Logging; + + class C + { + void M(ILogger logger, string value) + { + logger.LogInformation("Test: {Value}", value); + } + } + """; + + await VerifyCSharpDiagnosticAsync(source); + } + // VB tests [Fact] @@ -5700,6 +5718,22 @@ End Class await VerifyBasicDiagnosticAsync(source); } + [Fact] + public async Task ImplicitReferenceTypeParamsArrayCreation_NoDiagnostic_VB() + { + string source = """ + Imports Microsoft.Extensions.Logging + + Class C + Sub M(logger As ILogger, value As String) + logger.LogInformation("Test: {Value}", value) + End Sub + End Class + """; + + await VerifyBasicDiagnosticAsync(source); + } + // Tests for trivial operations that should not be flagged [Fact]