From 5a268412edcb7a9b72d283f86408d85dde7a2975 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Fri, 5 Apr 2024 15:17:47 +0200 Subject: [PATCH 1/3] Check for the CollectionExpression syntax kind early in UseSearchValuesAnalyzer --- .../Performance/CSharpUseSearchValues.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs index 5a39ce4b80..4e471e774b 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs @@ -90,6 +90,8 @@ syntax is ExpressionSyntax expression && // ConstString.ToCharArray() internal static bool IsConstantByteOrCharArrayCreationExpression(SemanticModel semanticModel, ExpressionSyntax expression, List? values, out int length) { + const SyntaxKind CollectionExpressionSyntaxKind = (SyntaxKind)9076; + length = 0; InitializerExpressionSyntax? arrayInitializer = null; @@ -112,7 +114,7 @@ internal static bool IsConstantByteOrCharArrayCreationExpression(SemanticModel s return true; } } - else + else if (expression.IsKind(CollectionExpressionSyntaxKind)) { return semanticModel.GetOperation(expression) is { } operation && From 33417fba2f15962ca3f9a6850172e1ec3f512f3d Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Fri, 5 Apr 2024 16:09:03 +0200 Subject: [PATCH 2/3] Document where the magic constants are coming from --- .../Performance/CSharpUseSearchValues.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs index 4e471e774b..72d2a2e5e4 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs @@ -14,6 +14,12 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Performance [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpUseSearchValuesAnalyzer : UseSearchValuesAnalyzer { + // The referenced SDK version doesn't yet contain these SyntaxKind values + // https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs + private const SyntaxKind Utf8StringLiteralToken = (SyntaxKind)8520; + private const SyntaxKind Utf8StringLiteralExpression = (SyntaxKind)8756; + private const SyntaxKind CollectionExpression = (SyntaxKind)9076; + // char[] myField = new char[] { 'a', 'b', 'c' }; // char[] myField = new[] { 'a', 'b', 'c' }; // char[] myField = "abc".ToCharArray(); @@ -90,8 +96,6 @@ syntax is ExpressionSyntax expression && // ConstString.ToCharArray() internal static bool IsConstantByteOrCharArrayCreationExpression(SemanticModel semanticModel, ExpressionSyntax expression, List? values, out int length) { - const SyntaxKind CollectionExpressionSyntaxKind = (SyntaxKind)9076; - length = 0; InitializerExpressionSyntax? arrayInitializer = null; @@ -114,7 +118,7 @@ internal static bool IsConstantByteOrCharArrayCreationExpression(SemanticModel s return true; } } - else if (expression.IsKind(CollectionExpressionSyntaxKind)) + else if (expression.IsKind(CollectionExpression)) { return semanticModel.GetOperation(expression) is { } operation && @@ -167,9 +171,6 @@ expression is LiteralExpressionSyntax characterLiteral && private static bool IsUtf8StringLiteralExpression(ExpressionSyntax expression, out int length) { - const SyntaxKind Utf8StringLiteralExpression = (SyntaxKind)8756; - const SyntaxKind Utf8StringLiteralToken = (SyntaxKind)8520; - if (expression.IsKind(Utf8StringLiteralExpression) && expression is LiteralExpressionSyntax literal && literal.Token.IsKind(Utf8StringLiteralToken) && From 5705f3870d9455a9f5ed224be7a9ca9d2175c856 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Fri, 5 Apr 2024 20:53:14 +0200 Subject: [PATCH 3/3] Create SyntaxKindEx helper --- .../Performance/CSharpUseSearchValues.cs | 13 ++++--------- .../Analyzer.CSharp.Utilities.projitems | 1 + .../Compiler.CSharp/Lightup/SyntaxKindEx.cs | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 src/Utilities/Compiler.CSharp/Lightup/SyntaxKindEx.cs diff --git a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs index 72d2a2e5e4..d5a044a67f 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -14,12 +15,6 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Performance [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpUseSearchValuesAnalyzer : UseSearchValuesAnalyzer { - // The referenced SDK version doesn't yet contain these SyntaxKind values - // https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs - private const SyntaxKind Utf8StringLiteralToken = (SyntaxKind)8520; - private const SyntaxKind Utf8StringLiteralExpression = (SyntaxKind)8756; - private const SyntaxKind CollectionExpression = (SyntaxKind)9076; - // char[] myField = new char[] { 'a', 'b', 'c' }; // char[] myField = new[] { 'a', 'b', 'c' }; // char[] myField = "abc".ToCharArray(); @@ -118,7 +113,7 @@ internal static bool IsConstantByteOrCharArrayCreationExpression(SemanticModel s return true; } } - else if (expression.IsKind(CollectionExpression)) + else if (expression.IsKind(SyntaxKindEx.CollectionExpression)) { return semanticModel.GetOperation(expression) is { } operation && @@ -171,9 +166,9 @@ expression is LiteralExpressionSyntax characterLiteral && private static bool IsUtf8StringLiteralExpression(ExpressionSyntax expression, out int length) { - if (expression.IsKind(Utf8StringLiteralExpression) && + if (expression.IsKind(SyntaxKindEx.Utf8StringLiteralExpression) && expression is LiteralExpressionSyntax literal && - literal.Token.IsKind(Utf8StringLiteralToken) && + literal.Token.IsKind(SyntaxKindEx.Utf8StringLiteralToken) && literal.Token.Value is string value) { length = value.Length; diff --git a/src/Utilities/Compiler.CSharp/Analyzer.CSharp.Utilities.projitems b/src/Utilities/Compiler.CSharp/Analyzer.CSharp.Utilities.projitems index efd3b3e0e5..a60042f946 100644 --- a/src/Utilities/Compiler.CSharp/Analyzer.CSharp.Utilities.projitems +++ b/src/Utilities/Compiler.CSharp/Analyzer.CSharp.Utilities.projitems @@ -10,5 +10,6 @@ + \ No newline at end of file diff --git a/src/Utilities/Compiler.CSharp/Lightup/SyntaxKindEx.cs b/src/Utilities/Compiler.CSharp/Lightup/SyntaxKindEx.cs new file mode 100644 index 0000000000..fbe93dcdcc --- /dev/null +++ b/src/Utilities/Compiler.CSharp/Lightup/SyntaxKindEx.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp; + +namespace Analyzer.Utilities.Lightup +{ + internal static class SyntaxKindEx + { + // https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs + public const SyntaxKind Utf8StringLiteralToken = (SyntaxKind)8520; + public const SyntaxKind Utf8StringLiteralExpression = (SyntaxKind)8756; + public const SyntaxKind CollectionExpression = (SyntaxKind)9076; + } +}