Skip to content

Commit

Permalink
NET-828: Reduce allocation of IsAnyKind
Browse files Browse the repository at this point in the history
  • Loading branch information
gregory-paidis-sonarsource authored and sonartech committed Dec 13, 2024
1 parent a5660e9 commit 244316a
Show file tree
Hide file tree
Showing 72 changed files with 359 additions and 325 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public override bool HasExactlyNArguments(SyntaxNode invocation, int count) =>

public override bool IsAnyKind(SyntaxNode node, ISet<SyntaxKind> syntaxKinds) => node.IsAnyKind(syntaxKinds);

[Obsolete("Either use '.Kind() is A or B' or the overload with the ISet instead.")]
public override bool IsAnyKind(SyntaxNode node, params SyntaxKind[] syntaxKinds) => node.IsAnyKind(syntaxKinds);

public override bool IsAnyKind(SyntaxTrivia trivia, params SyntaxKind[] syntaxKinds) => trivia.IsAnyKind(syntaxKinds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static bool IsInTupleAssignmentTarget(this ArgumentSyntax argument) =>

public static TupleExpressionSyntaxWrapper? OutermostTuple(this ArgumentSyntax argument) =>
argument.Ancestors()
.TakeWhile(x => x.IsAnyKind(SyntaxKind.Argument, SyntaxKindEx.TupleExpression))
.TakeWhile(x => x?.Kind() is SyntaxKind.Argument or SyntaxKindEx.TupleExpression)
.LastOrDefault(x => x.IsKind(SyntaxKindEx.TupleExpression)) is { } outerTuple
&& TupleExpressionSyntaxWrapper.IsInstance(outerTuple)
? (TupleExpressionSyntaxWrapper)outerTuple
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static class CompilationUnitSyntaxExtensions
{
public static IEnumerable<SyntaxNode> GetTopLevelMainBody(this CompilationUnitSyntax compilationUnit) =>
compilationUnit.ChildNodes()
.SkipWhile(x => x.IsAnyKind(SyntaxKind.UsingDirective, SyntaxKind.NamespaceDeclaration))
.SkipWhile(x => x.Kind() is SyntaxKind.UsingDirective or SyntaxKind.NamespaceDeclaration)
.TakeWhile(x => x.IsKind(SyntaxKind.GlobalStatement));

public static IEnumerable<IMethodDeclaration> GetMethodDeclarations(this CompilationUnitSyntax compilationUnitSyntax) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace SonarAnalyzer.CSharp.Core.Syntax.Extensions;

public static class ExpressionSyntaxExtensions
{
private static readonly SyntaxKind[] LiteralSyntaxKinds =
private static readonly HashSet<SyntaxKind> LiteralSyntaxKinds =
[
SyntaxKind.CharacterLiteralExpression,
SyntaxKind.FalseLiteralExpression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,39 @@ namespace SonarAnalyzer.CSharp.Core.Syntax.Extensions;
public static class SyntaxNodeExtensionsCSharp
{
private static readonly ControlFlowGraphCache CfgCache = new();
private static readonly SyntaxKind[] ParenthesizedNodeKinds = [SyntaxKind.ParenthesizedExpression, SyntaxKindEx.ParenthesizedPattern];

private static readonly SyntaxKind[] EnclosingScopeSyntaxKinds = [
SyntaxKind.AddAccessorDeclaration,
SyntaxKind.AnonymousMethodExpression,
SyntaxKind.BaseConstructorInitializer,
SyntaxKind.CompilationUnit,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.ConversionOperatorDeclaration,
SyntaxKind.DestructorDeclaration,
SyntaxKind.EnumMemberDeclaration,
SyntaxKind.FieldDeclaration,
SyntaxKind.GetAccessorDeclaration,
SyntaxKind.GroupClause,
SyntaxKindEx.InitAccessorDeclaration,
SyntaxKind.JoinClause,
SyntaxKind.LetClause,
SyntaxKindEx.LocalFunctionStatement,
SyntaxKind.MethodDeclaration,
SyntaxKind.OrderByClause,
SyntaxKind.OperatorDeclaration,
SyntaxKind.Parameter,
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKindEx.PrimaryConstructorBaseType,
SyntaxKind.PropertyDeclaration,
SyntaxKind.RemoveAccessorDeclaration,
SyntaxKind.QueryContinuation,
SyntaxKind.SelectClause,
SyntaxKind.SetAccessorDeclaration,
SyntaxKind.SimpleLambdaExpression,
SyntaxKind.ThisConstructorInitializer,
SyntaxKind.WhereClause];
private static readonly HashSet<SyntaxKind> EnclosingScopeSyntaxKinds =
[
SyntaxKind.AddAccessorDeclaration,
SyntaxKind.AnonymousMethodExpression,
SyntaxKind.BaseConstructorInitializer,
SyntaxKind.CompilationUnit,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.ConversionOperatorDeclaration,
SyntaxKind.DestructorDeclaration,
SyntaxKind.EnumMemberDeclaration,
SyntaxKind.FieldDeclaration,
SyntaxKind.GetAccessorDeclaration,
SyntaxKind.GroupClause,
SyntaxKindEx.InitAccessorDeclaration,
SyntaxKind.JoinClause,
SyntaxKind.LetClause,
SyntaxKindEx.LocalFunctionStatement,
SyntaxKind.MethodDeclaration,
SyntaxKind.OrderByClause,
SyntaxKind.OperatorDeclaration,
SyntaxKind.Parameter,
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKindEx.PrimaryConstructorBaseType,
SyntaxKind.PropertyDeclaration,
SyntaxKind.RemoveAccessorDeclaration,
SyntaxKind.QueryContinuation,
SyntaxKind.SelectClause,
SyntaxKind.SetAccessorDeclaration,
SyntaxKind.SimpleLambdaExpression,
SyntaxKind.ThisConstructorInitializer,
SyntaxKind.WhereClause
];

private static readonly SyntaxKind[] NegationOrConditionEnclosingSyntaxKinds = [
SyntaxKind.AnonymousMethodExpression,
Expand Down Expand Up @@ -152,7 +153,7 @@ public static ArrowExpressionClauseSyntax ArrowExpressionBody(this SyntaxNode no
public static SyntaxNode RemoveParentheses(this SyntaxNode expression)
{
var current = expression;
while (current is { } && current.IsAnyKind(ParenthesizedNodeKinds))
while (current is { } && current.Kind() is SyntaxKind.ParenthesizedExpression or SyntaxKindEx.ParenthesizedPattern)
{
current = current.IsKind(SyntaxKindEx.ParenthesizedPattern)
? ((ParenthesizedPatternSyntaxWrapper)current).Pattern
Expand Down Expand Up @@ -248,14 +249,14 @@ public static SyntaxNode FindAssignmentComplement(this SyntaxNode node)
}
// can be either outermost tuple, or DeclarationExpression if 'node' is SingleVariableDesignationExpression
var outermostParenthesesExpression = node.AncestorsAndSelf()
.TakeWhile(x => x.IsAnyKind(
SyntaxKind.Argument,
SyntaxKindEx.TupleExpression,
SyntaxKindEx.SingleVariableDesignation,
SyntaxKindEx.ParenthesizedVariableDesignation,
SyntaxKindEx.DiscardDesignation,
SyntaxKindEx.DeclarationExpression))
.LastOrDefault(x => x.IsAnyKind(SyntaxKindEx.DeclarationExpression, SyntaxKindEx.TupleExpression));
.TakeWhile(x => x?.Kind() is
SyntaxKind.Argument or
SyntaxKindEx.TupleExpression or
SyntaxKindEx.SingleVariableDesignation or
SyntaxKindEx.ParenthesizedVariableDesignation or
SyntaxKindEx.DiscardDesignation or
SyntaxKindEx.DeclarationExpression)
.LastOrDefault(x => x.Kind() is SyntaxKindEx.DeclarationExpression or SyntaxKindEx.TupleExpression);
if ((TupleExpressionSyntaxWrapper.IsInstance(outermostParenthesesExpression) || DeclarationExpressionSyntaxWrapper.IsInstance(outermostParenthesesExpression))
&& outermostParenthesesExpression.Parent is AssignmentExpressionSyntax assignment)
{
Expand Down Expand Up @@ -470,12 +471,19 @@ public static SyntaxNode GetSelfOrTopParenthesizedExpression(this SyntaxNode nod
public static SyntaxNode GetFirstNonParenthesizedParent(this SyntaxNode node) =>
node.GetSelfOrTopParenthesizedExpression().Parent;

public static bool HasAncestor(this SyntaxNode node, params SyntaxKind[] syntaxKinds) =>
public static bool HasAncestor(this SyntaxNode node, SyntaxKind syntaxKind) =>
node.Ancestors().Any(x => x.IsKind(syntaxKind));

public static bool HasAncestor(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2) =>
node.Ancestors().Any(x => x.IsKind(kind1) || x.IsKind(kind2));

public static bool HasAncestor(this SyntaxNode node, ISet<SyntaxKind> syntaxKinds) =>
node.Ancestors().Any(x => x.IsAnyKind(syntaxKinds));

public static bool IsNullLiteral(this SyntaxNode node) =>
node is not null && node.IsKind(SyntaxKind.NullLiteralExpression);

[Obsolete("Either use '.Kind() is A or B' or the overload with the ISet instead.")]
public static bool IsAnyKind(this SyntaxNode node, params SyntaxKind[] syntaxKinds) =>
node is not null && syntaxKinds.Contains((SyntaxKind)node.RawKind);

Expand All @@ -496,7 +504,7 @@ public static bool NameIs(this SyntaxNode node, string name, params string[] orN
public static string StringValue(this SyntaxNode node, SemanticModel model) =>
node switch
{
LiteralExpressionSyntax literal when literal.IsAnyKind(SyntaxKind.StringLiteralExpression, SyntaxKindEx.Utf8StringLiteralExpression) => literal.Token.ValueText,
LiteralExpressionSyntax literal when literal.Kind() is SyntaxKind.StringLiteralExpression or SyntaxKindEx.Utf8StringLiteralExpression => literal.Token.ValueText,
InterpolatedStringExpressionSyntax expression => expression.InterpolatedTextValue(model) ?? expression.ContentsText(),
_ => null
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private static NullCheck NullCheckState(SyntaxNode node, bool isPositive)
{
return NullCheckState(unary.Operand.RemoveParentheses(), !isPositive);
}
else if (node is BinaryExpressionSyntax binary && binary.IsAnyKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression))
else if (node is BinaryExpressionSyntax binary && binary.Kind() is SyntaxKind.EqualsExpression or SyntaxKind.NotEqualsExpression)
{
if (binary.IsKind(SyntaxKind.NotEqualsExpression))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ public static bool IsNodeContainerTypeDeclaration(SyntaxNode node) =>
IsNodeStructOrClassOrRecordDeclaration(node) || node.IsKind(SyntaxKind.InterfaceDeclaration);

private static bool IsNodeStructOrClassOrRecordDeclaration(SyntaxNode node) =>
node.IsAnyKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKindEx.RecordDeclaration, SyntaxKindEx.RecordStructDeclaration);
node?.Kind() is SyntaxKind.ClassDeclaration or SyntaxKind.StructDeclaration or SyntaxKindEx.RecordDeclaration or SyntaxKindEx.RecordStructDeclaration;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ namespace SonarAnalyzer.CSharp.Core.Syntax.Utilities;
public class MutedSyntaxWalker : CSharpSyntaxWalker
{
// All kinds that SonarAnalysisContextExtensions.RegisterExplodedGraphBasedAnalysis registers for
private static readonly SyntaxKind[] RootKinds =
[
SyntaxKind.AddAccessorDeclaration,
SyntaxKind.AnonymousMethodExpression,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.ConversionOperatorDeclaration,
SyntaxKind.DestructorDeclaration,
SyntaxKind.GetAccessorDeclaration,
SyntaxKindEx.InitAccessorDeclaration,
SyntaxKind.MethodDeclaration,
SyntaxKind.OperatorDeclaration,
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKind.PropertyDeclaration,
SyntaxKind.RemoveAccessorDeclaration,
SyntaxKind.SetAccessorDeclaration,
SyntaxKind.SimpleLambdaExpression
];
private static readonly HashSet<SyntaxKind> RootKinds =
[
SyntaxKind.AddAccessorDeclaration,
SyntaxKind.AnonymousMethodExpression,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.ConversionOperatorDeclaration,
SyntaxKind.DestructorDeclaration,
SyntaxKind.GetAccessorDeclaration,
SyntaxKindEx.InitAccessorDeclaration,
SyntaxKind.MethodDeclaration,
SyntaxKind.OperatorDeclaration,
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKind.PropertyDeclaration,
SyntaxKind.RemoveAccessorDeclaration,
SyntaxKind.SetAccessorDeclaration,
SyntaxKind.SimpleLambdaExpression
];

private readonly SemanticModel model;
private readonly SyntaxNode root;
Expand Down Expand Up @@ -89,6 +89,6 @@ bool IsUsedInLocalFunction(ISymbol symbol) =>
&& node.HasAncestor(SyntaxKindEx.LocalFunctionStatement);

bool IsInUnsupportedExpression() =>
node.FirstAncestorOrSelf<SyntaxNode>(x => x.IsAnyKind(SyntaxKindEx.IndexExpression, SyntaxKindEx.RangeExpression)) is not null;
node.FirstAncestorOrSelf<SyntaxNode>(x => x?.Kind() is SyntaxKindEx.IndexExpression or SyntaxKindEx.RangeExpression) is not null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ protected override bool IsAssignmentToIdentifier(SyntaxNode node, string identif
return false;
}

protected override bool IsIdentifierDeclaration(SyntaxNode node, string identifierName, out SyntaxNode initializer)
{
if (node.IsKind(SyntaxKindEx.GlobalStatement))
{
node = ((GlobalStatementSyntax)node).Statement;
}

if (node is LocalDeclarationStatementSyntax declarationStatement
&& declarationStatement.Declaration.Variables.SingleOrDefault(x => x.Identifier.ValueText == identifierName) is { } declaration)
{
initializer = declaration.Initializer?.Value;
return true;
}

initializer = null;
return false;
}

protected override bool IsLoop(SyntaxNode node) =>
node?.Kind() is SyntaxKind.ForStatement or SyntaxKind.ForEachStatement or SyntaxKind.WhileStatement or SyntaxKind.DoStatement;

/// <summary>
/// If <paramref name="identifierName"/> is mutated inside <paramref name="mutation"/> then
/// the expression representing the new value is returned. The returned expression might be
Expand Down Expand Up @@ -73,25 +94,4 @@ when assignment.MapAssignmentArguments().FirstOrDefault(x => x.Left.NameIs(ident
} when argumentExpression.NameIs(identifierName) => argumentExpression,
_ => null,
};

protected override bool IsIdentifierDeclaration(SyntaxNode node, string identifierName, out SyntaxNode initializer)
{
if (node.IsKind(SyntaxKindEx.GlobalStatement))
{
node = ((GlobalStatementSyntax)node).Statement;
}

if (node is LocalDeclarationStatementSyntax declarationStatement
&& declarationStatement.Declaration.Variables.SingleOrDefault(x => x.Identifier.ValueText == identifierName) is { } declaration)
{
initializer = declaration.Initializer?.Value;
return true;
}

initializer = null;
return false;
}

protected override bool IsLoop(SyntaxNode node) =>
node.IsAnyKind(SyntaxKind.ForStatement, SyntaxKind.ForEachStatement, SyntaxKind.WhileStatement, SyntaxKind.DoStatement);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected override bool IsMemberAccess(SyntaxNode node, out SyntaxNode memberAcc
}

protected override bool IsObjectCreation(SyntaxNode node) =>
node.IsAnyKind(SyntaxKind.ObjectCreationExpression, SyntaxKindEx.ImplicitObjectCreationExpression);
node?.Kind() is SyntaxKind.ObjectCreationExpression or SyntaxKindEx.ImplicitObjectCreationExpression;

protected override bool IsIdentifier(SyntaxNode node, out string identifierName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static IObjectCreation Create(SyntaxNode node) =>
};

public static IObjectCreation TryCreate(SyntaxNode node) =>
node.IsAnyKind(SyntaxKind.ObjectCreationExpression, SyntaxKindEx.ImplicitObjectCreationExpression)
node?.Kind() is SyntaxKind.ObjectCreationExpression or SyntaxKindEx.ImplicitObjectCreationExpression
? Create(node)
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public override void Visit(SyntaxNode node)
var arm = (SwitchExpressionArmSyntaxWrapper)node;
AddLocation(arm.EqualsGreaterThanToken);
}
else if (node.IsAnyKind(SyntaxKindEx.AndPattern, SyntaxKindEx.OrPattern))
else if (node?.Kind() is SyntaxKindEx.AndPattern or SyntaxKindEx.OrPattern)
{
var binaryPatternNode = (BinaryPatternSyntaxWrapper)node;
AddLocation(binaryPatternNode.OperatorToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private static bool IsInsideExpression(ExpressionSyntax expression) =>
expression.Parent.FirstAncestorOrSelf<ExpressionSyntax>() != null;

private static bool IsInInitializerExpression(ExpressionSyntax expression) =>
expression.Parent.IsAnyKind(SyntaxKindEx.WithInitializerExpression, SyntaxKind.ObjectInitializerExpression);
expression.Parent?.Kind() is SyntaxKindEx.WithInitializerExpression or SyntaxKind.ObjectInitializerExpression;

private static bool IsCompliantAssignmentInsideExpression(AssignmentExpressionSyntax assignment, ExpressionSyntax topParenthesizedExpression) =>
topParenthesizedExpression.Parent.FirstAncestorOrSelf<ExpressionSyntax>() is not { } expressionParent
Expand Down
18 changes: 9 additions & 9 deletions analyzers/src/SonarAnalyzer.CSharp/Rules/AsyncVoidMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ public sealed class AsyncVoidMethod : SonarDiagnosticAnalyzer
KnownType.Microsoft_VisualStudio_TestTools_UnitTesting_TestCleanupAttribute,
KnownType.Microsoft_VisualStudio_TestTools_UnitTesting_TestInitializeAttribute);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
private static readonly HashSet<SyntaxKind> ParentTypeSyntaxKinds =
[
SyntaxKind.ClassDeclaration,
SyntaxKind.StructDeclaration,
SyntaxKindEx.RecordDeclaration,
SyntaxKindEx.RecordStructDeclaration,
SyntaxKind.InterfaceDeclaration
];

private static readonly SyntaxKind[] ParentTypeSyntaxKinds =
{
SyntaxKind.ClassDeclaration,
SyntaxKind.StructDeclaration,
SyntaxKindEx.RecordDeclaration,
SyntaxKindEx.RecordStructDeclaration,
SyntaxKind.InterfaceDeclaration
};
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);

protected override void Initialize(SonarAnalysisContext context) =>
context.RegisterNodeAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ bool IsDuplicatedCast(SyntaxNode node)
{
return IsDuplicatedCastOnSameSymbol(cast.Expression, cast.Type);
}
else if (node is BinaryExpressionSyntax binary && binary.IsAnyKind(SyntaxKind.AsExpression, SyntaxKind.IsExpression))
else if (node is BinaryExpressionSyntax binary && binary.Kind() is SyntaxKind.AsExpression or SyntaxKind.IsExpression)
{
return IsDuplicatedCastOnSameSymbol(binary.Left, binary.Right);
}
Expand Down Expand Up @@ -115,7 +115,7 @@ private static void ProcessPatternExpression(SonarSyntaxNodeReportingContext ana
var leftVariable = expressionPatternPair.Key;
var targetTypes = GetTypesFromPattern(pattern);
var rightPartsToCheck = new Dictionary<SyntaxNode, Tuple<TypeSyntax, Location>>();
foreach (var subPattern in pattern.DescendantNodesAndSelf().Where(x => x.IsAnyKind(SyntaxKindEx.DeclarationPattern, SyntaxKindEx.RecursivePattern)))
foreach (var subPattern in pattern.DescendantNodesAndSelf().Where(x => x?.Kind() is SyntaxKindEx.DeclarationPattern or SyntaxKindEx.RecursivePattern))
{
if (DeclarationPatternSyntaxWrapper.IsInstance(subPattern) && (DeclarationPatternSyntaxWrapper)subPattern is var declarationPattern)
{
Expand Down
Loading

0 comments on commit 244316a

Please sign in to comment.