diff --git a/analyzers/src/SonarAnalyzer.CSharp/Common/Walkers/MutedSyntaxWalker.cs b/analyzers/src/SonarAnalyzer.CSharp/Common/Walkers/MutedSyntaxWalker.cs index 7e0c5baafde..e1cc2da5647 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Common/Walkers/MutedSyntaxWalker.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Common/Walkers/MutedSyntaxWalker.cs @@ -93,7 +93,7 @@ bool IsInTupleAssignmentTarget() => bool IsUsedInLocalFunction(ISymbol symbol) => // We don't mute it if it's declared and used in local function !(symbol.ContainingSymbol is IMethodSymbol containingSymbol && containingSymbol.MethodKind == MethodKindEx.LocalFunction) - && HasAncestor(node, SyntaxKindEx.LocalFunctionStatement); + && node.HasAncestor(SyntaxKindEx.LocalFunctionStatement); bool IsInUnsupportedExpression() => node.FirstAncestorOrSelf(x => x.IsAnyKind(SyntaxKindEx.IndexExpression, SyntaxKindEx.RangeExpression)) != null; @@ -113,18 +113,15 @@ private bool IsMutedState() => private void InspectTryCatch(SyntaxNode node) { - if (HasAncestor(node, SyntaxKind.TryStatement)) + if (node.HasAncestor(SyntaxKind.TryStatement)) { // We're only interested in "try" and "catch" blocks. Don't count "finally" block - isInTryOrCatch = isInTryOrCatch || !HasAncestor(node, SyntaxKind.FinallyClause); + isInTryOrCatch = isInTryOrCatch || !node.HasAncestor(SyntaxKind.FinallyClause); } else { isOutsideTryCatch = true; } } - - private static bool HasAncestor(SyntaxNode node, SyntaxKind kind) => - node.FirstAncestorOrSelf(x => x.IsKind(kind)) != null; } } diff --git a/analyzers/src/SonarAnalyzer.CSharp/Helpers/CSharpSyntaxHelper.cs b/analyzers/src/SonarAnalyzer.CSharp/Helpers/CSharpSyntaxHelper.cs index de2b74def00..59b9c53e346 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Helpers/CSharpSyntaxHelper.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Helpers/CSharpSyntaxHelper.cs @@ -35,24 +35,23 @@ public static class CSharpSyntaxHelper SyntaxFacts.GetText(SyntaxKind.NameOfKeyword); private static readonly SyntaxKind[] LiteralSyntaxKinds = - new[] - { + [ SyntaxKind.CharacterLiteralExpression, SyntaxKind.FalseLiteralExpression, SyntaxKind.NullLiteralExpression, SyntaxKind.NumericLiteralExpression, SyntaxKind.StringLiteralExpression, - SyntaxKind.TrueLiteralExpression, - }; + SyntaxKind.TrueLiteralExpression + ]; public static bool AnyOfKind(this IEnumerable nodes, SyntaxKind kind) => - nodes.Any(n => n.RawKind == (int)kind); + nodes.Any(x => x.RawKind == (int)kind); public static bool AnyOfKind(this IEnumerable tokens, SyntaxKind kind) => - tokens.Any(n => n.RawKind == (int)kind); + tokens.Any(x => x.RawKind == (int)kind); public static SyntaxNode GetTopMostContainingMethod(this SyntaxNode node) => - node.AncestorsAndSelf().LastOrDefault(ancestor => ancestor is BaseMethodDeclarationSyntax || ancestor is PropertyDeclarationSyntax); + node.AncestorsAndSelf().LastOrDefault(x => x is BaseMethodDeclarationSyntax || x is PropertyDeclarationSyntax); public static SyntaxNode GetSelfOrTopParenthesizedExpression(this SyntaxNode node) { @@ -70,46 +69,31 @@ public static ExpressionSyntax GetSelfOrTopParenthesizedExpression(this Expressi public static SyntaxNode GetFirstNonParenthesizedParent(this SyntaxNode node) => node.GetSelfOrTopParenthesizedExpression().Parent; + public static bool HasAncestor(this SyntaxNode syntaxNode, params SyntaxKind[] syntaxKinds) => + syntaxNode.Ancestors().Any(x => x.IsAnyKind(syntaxKinds)); + public static bool IsOnThis(this ExpressionSyntax expression) => IsOn(expression, SyntaxKind.ThisExpression); - public static bool IsOnBase(this ExpressionSyntax expression) => - IsOn(expression, SyntaxKind.BaseExpression); - - private static bool IsOn(this ExpressionSyntax expression, SyntaxKind onKind) - { - switch (expression.Kind()) + private static bool IsOn(this ExpressionSyntax expression, SyntaxKind onKind) => + expression switch { - case SyntaxKind.InvocationExpression: - return IsOn(((InvocationExpressionSyntax)expression).Expression, onKind); - - case SyntaxKind.AliasQualifiedName: - case SyntaxKind.GenericName: - case SyntaxKind.IdentifierName: - case SyntaxKind.QualifiedName: - // This is a simplification as we don't check where the method is defined (so this could be this or base) - return true; - - case SyntaxKind.PointerMemberAccessExpression: - case SyntaxKind.SimpleMemberAccessExpression: - return ((MemberAccessExpressionSyntax)expression).Expression.RemoveParentheses().IsKind(onKind); - - case SyntaxKind.ConditionalAccessExpression: - return ((ConditionalAccessExpressionSyntax)expression).Expression.RemoveParentheses().IsKind(onKind); - - default: - return false; - } - } + InvocationExpressionSyntax invocation => IsOn(invocation.Expression, onKind), + // Following statement is a simplification as we don't check where the method is defined (so this could be this or base) + AliasQualifiedNameSyntax or GenericNameSyntax or IdentifierNameSyntax or QualifiedNameSyntax => true, + MemberAccessExpressionSyntax memberAccess => memberAccess.Expression.RemoveParentheses().IsKind(onKind), + ConditionalAccessExpressionSyntax conditionalAccess => conditionalAccess.Expression.RemoveParentheses().IsKind(onKind), + _ => false, + }; public static bool IsInNameOfArgument(this ExpressionSyntax expression, SemanticModel semanticModel) { var parentInvocation = expression.FirstAncestorOrSelf(); - return parentInvocation != null && parentInvocation.IsNameof(semanticModel); + return parentInvocation is not null && parentInvocation.IsNameof(semanticModel); } public static bool IsNameof(this InvocationExpressionSyntax expression, SemanticModel semanticModel) => - expression != null && + expression is not null && expression.Expression is IdentifierNameSyntax identifierNameSyntax && identifierNameSyntax.Identifier.ValueText == NameOfKeywordText && semanticModel.GetSymbolInfo(expression).Symbol?.Kind != SymbolKind.Method; @@ -124,19 +108,19 @@ public static bool IsStringEmpty(this ExpressionSyntax expression, SemanticModel var nameSymbolInfo = semanticModel.GetSymbolInfo(((MemberAccessExpressionSyntax)expression).Name); - return nameSymbolInfo.Symbol != null && + return nameSymbolInfo.Symbol is not null && nameSymbolInfo.Symbol.IsInType(KnownType.System_String) && nameSymbolInfo.Symbol.Name == nameof(string.Empty); } public static bool IsNullLiteral(this SyntaxNode syntaxNode) => - syntaxNode != null && syntaxNode.IsKind(SyntaxKind.NullLiteralExpression); + syntaxNode is not null && syntaxNode.IsKind(SyntaxKind.NullLiteralExpression); public static bool IsAnyKind(this SyntaxNode syntaxNode, params SyntaxKind[] syntaxKinds) => - syntaxNode != null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); + syntaxNode is not null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); public static bool IsAnyKind(this SyntaxNode syntaxNode, ISet syntaxKinds) => - syntaxNode != null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); + syntaxNode is not null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); public static bool IsAnyKind(this SyntaxToken syntaxToken, params SyntaxKind[] syntaxKinds) => syntaxKinds.Contains((SyntaxKind)syntaxToken.RawKind); @@ -162,28 +146,19 @@ public static bool ContainsMethodInvocation(this BaseMethodDeclarationSyntax met return childNodes .OfType() .Where(syntaxPredicate) - .Select(e => e.Expression.SyntaxTree.GetSemanticModelOrDefault(semanticModel)?.GetSymbolInfo(e.Expression).Symbol) + .Select(x => x.Expression.SyntaxTree.GetSemanticModelOrDefault(semanticModel)?.GetSymbolInfo(x.Expression).Symbol) .OfType() .Any(symbolPredicate); } - public static SyntaxToken? GetIdentifierOrDefault(this BaseMethodDeclarationSyntax methodDeclaration) - { - switch (methodDeclaration?.Kind()) + public static SyntaxToken? GetIdentifierOrDefault(this BaseMethodDeclarationSyntax methodDeclaration) => + methodDeclaration switch { - case SyntaxKind.ConstructorDeclaration: - return ((ConstructorDeclarationSyntax)methodDeclaration).Identifier; - - case SyntaxKind.DestructorDeclaration: - return ((DestructorDeclarationSyntax)methodDeclaration).Identifier; - - case SyntaxKind.MethodDeclaration: - return ((MethodDeclarationSyntax)methodDeclaration).Identifier; - - default: - return null; - } - } + ConstructorDeclarationSyntax constructor => (SyntaxToken?)constructor.Identifier, + DestructorDeclarationSyntax destructor => (SyntaxToken?)destructor.Identifier, + MethodDeclarationSyntax method => (SyntaxToken?)method.Identifier, + _ => null, + }; public static bool IsMethodInvocation(this InvocationExpressionSyntax invocation, KnownType type, string methodName, SemanticModel semanticModel) => invocation.Expression.NameIs(methodName) && @@ -210,7 +185,7 @@ public static int GetDefaultLabelSectionIndex(this SwitchStatementSyntax node) = node.Sections.IndexOf(section => section.Labels.AnyOfKind(SyntaxKind.DefaultSwitchLabel)); public static bool HasBodyOrExpressionBody(this AccessorDeclarationSyntax node) => - node.Body != null || node.ExpressionBody() != null; + node.Body is not null || node.ExpressionBody() is not null; public static string GetName(this SyntaxNode node) => node.GetIdentifier()?.ValueText ?? string.Empty; @@ -224,7 +199,7 @@ public static bool NameIs(this SyntaxNode node, string name, params string[] orN || Array.Exists(orNames, x => nodeName.Equals(x, StringComparison.Ordinal))); public static bool HasConstantValue(this ExpressionSyntax expression, SemanticModel semanticModel) => - expression.RemoveParentheses().IsAnyKind(LiteralSyntaxKinds) || expression.FindConstantValue(semanticModel) != null; + expression.RemoveParentheses().IsAnyKind(LiteralSyntaxKinds) || expression.FindConstantValue(semanticModel) is not null; public static string StringValue(this SyntaxNode node, SemanticModel semanticModel) => node switch @@ -242,20 +217,12 @@ public static bool IsLeftSideOfAssignment(this ExpressionSyntax expression) && assignment.Left == topParenthesizedExpression; } - public static bool IsComment(this SyntaxTrivia trivia) - { - switch (trivia.Kind()) - { - case SyntaxKind.SingleLineCommentTrivia: - case SyntaxKind.MultiLineCommentTrivia: - case SyntaxKind.SingleLineDocumentationCommentTrivia: - case SyntaxKind.MultiLineDocumentationCommentTrivia: - return true; - - default: - return false; - } - } + public static bool IsComment(this SyntaxTrivia trivia) => + trivia.IsAnyKind( + SyntaxKind.SingleLineCommentTrivia, + SyntaxKind.MultiLineCommentTrivia, + SyntaxKind.SingleLineDocumentationCommentTrivia, + SyntaxKind.MultiLineDocumentationCommentTrivia); // creates a QualifiedNameSyntax "a.b" public static QualifiedNameSyntax BuildQualifiedNameSyntax(string a, string b) => @@ -277,7 +244,7 @@ public static QualifiedNameSyntax BuildQualifiedNameSyntax(string a, string b, s /// There can be zero, one or more results based on parameter type (Optional or ParamArray/params). /// public static ImmutableArray ArgumentValuesForParameter(SemanticModel semanticModel, ArgumentListSyntax argumentList, string parameterName) => - argumentList != null + argumentList is not null && new CSharpMethodParameterLookup(argumentList, semanticModel).TryGetSyntax(parameterName, out var expressions) ? expressions : ImmutableArray.Empty; diff --git a/analyzers/src/SonarAnalyzer.CSharp/ReuseClientBase.cs b/analyzers/src/SonarAnalyzer.CSharp/ReuseClientBase.cs index 4940635b65f..2af7d77b5b8 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/ReuseClientBase.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/ReuseClientBase.cs @@ -38,17 +38,16 @@ private static bool IsInVariableDeclaration(SyntaxNode node) => node.Parent is EqualsValueClauseSyntax { Parent: VariableDeclaratorSyntax { Parent: VariableDeclarationSyntax { Parent: LocalDeclarationStatementSyntax or UsingStatementSyntax } } }; private static bool IsInFieldOrPropertyInitializer(SyntaxNode node) => - node.Ancestors().Any(x => x.IsAnyKind(SyntaxKind.FieldDeclaration, SyntaxKind.PropertyDeclaration)) - && !node.Ancestors().Any(x => x.IsAnyKind(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration)) + node.HasAncestor(SyntaxKind.FieldDeclaration, SyntaxKind.PropertyDeclaration) + && !node.HasAncestor(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration) && !node.Parent.IsKind(SyntaxKind.ArrowExpressionClause); private static bool IsInConditionalCode(SyntaxNode node) => - node.Ancestors().Any(x => x.IsAnyKind( - SyntaxKind.IfStatement, + node.HasAncestor(SyntaxKind.IfStatement, SyntaxKind.SwitchStatement, SyntaxKindEx.SwitchExpression, SyntaxKind.ConditionalExpression, - SyntaxKindEx.CoalesceAssignmentExpression)); + SyntaxKindEx.CoalesceAssignmentExpression); private static bool IsAssignedToStaticFieldOrProperty(SonarSyntaxNodeReportingContext context) => context.Node.Parent.WalkUpParentheses() is AssignmentExpressionSyntax assignment diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/AspNet/ControllersReuseClient.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/AspNet/ControllersReuseClient.cs index 7553e397394..890a95d6186 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/AspNet/ControllersReuseClient.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/AspNet/ControllersReuseClient.cs @@ -67,5 +67,5 @@ public static bool IsInPublicMethod(SyntaxNode node) => && method.Modifiers.Any(x => x.IsKind(SyntaxKind.PublicKeyword))); private static bool IsInsideConstructor(SyntaxNode node) => - node.Ancestors().Any(x => x.IsAnyKind(SyntaxKind.ConstructorDeclaration, SyntaxKindEx.PrimaryConstructorBaseType)); + node.HasAncestor(SyntaxKind.ConstructorDeclaration, SyntaxKindEx.PrimaryConstructorBaseType); } diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/CallToAsyncMethodShouldNotBeBlocking.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/CallToAsyncMethodShouldNotBeBlocking.cs index 570bdd8c877..c0b091bc36d 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/CallToAsyncMethodShouldNotBeBlocking.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/CallToAsyncMethodShouldNotBeBlocking.cs @@ -85,7 +85,7 @@ private static void ReportOnViolation(SonarSyntaxNodeReportingContext context) || IsResultInContinueWithCall(memberAccessNameName, simpleMemberAccess) || IsChainedAfterThreadPoolCall(context.SemanticModel, simpleMemberAccess) || simpleMemberAccess.IsInNameOfArgument(context.SemanticModel) - || simpleMemberAccess.Ancestors().Any(x => x is GlobalStatementSyntax)) + || simpleMemberAccess.HasAncestor(SyntaxKind.GlobalStatement)) { return; } diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/Hotspots/HardcodedIpAddress.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/Hotspots/HardcodedIpAddress.cs index 3ad03c6cbb6..c5b80823dab 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/Hotspots/HardcodedIpAddress.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/Hotspots/HardcodedIpAddress.cs @@ -30,7 +30,7 @@ public HardcodedIpAddress() : this(AnalyzerConfiguration.Hotspot) { } public HardcodedIpAddress(IAnalyzerConfiguration analyzerConfiguration) : base(analyzerConfiguration) { } protected override bool HasAttributes(SyntaxNode literalExpression) => - literalExpression.Ancestors().AnyOfKind(SyntaxKind.Attribute); + literalExpression.HasAncestor(SyntaxKind.Attribute); protected override string GetAssignedVariableName(SyntaxNode stringLiteral) => stringLiteral.FirstAncestorOrSelf(IsVariableIdentifier)?.ToString(); diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/RedundantModifier.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/RedundantModifier.cs index e893fab18d2..66417534e86 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/RedundantModifier.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/RedundantModifier.cs @@ -307,7 +307,7 @@ public override void VisitCastExpression(CastExpressionSyntax node) } public static bool IsTopLevel(SyntaxNode node) => - !node.Ancestors().Any(x => x is CheckedStatementSyntax || x is CheckedExpressionSyntax); + !node.HasAncestor(SyntaxKind.CheckedStatement, SyntaxKind.CheckedExpression); private void VisitChecked(T node, SyntaxKind checkedKind, SyntaxToken tokenToReport, Action baseCall) where T : SyntaxNode diff --git a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs index bb2a6535d97..ab55f042c2e 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs @@ -85,11 +85,10 @@ public override void Visit(SyntaxNode node) public override void VisitIdentifierName(IdentifierNameSyntax node) => DereferencesMethodArguments |= argumentNames.Contains(node.GetName()) - && node.Ancestors().Any(x => x.IsAnyKind( - AwaitExpression, + && node.HasAncestor(AwaitExpression, ElementAccessExpression, ForEachStatement, ThrowStatement, - SimpleMemberAccessExpression)); + SimpleMemberAccessExpression); } } diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Helpers/VisualBasicSyntaxHelper.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Helpers/VisualBasicSyntaxHelper.cs index a12bc35577a..3ef36f19e19 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/Helpers/VisualBasicSyntaxHelper.cs +++ b/analyzers/src/SonarAnalyzer.VisualBasic/Helpers/VisualBasicSyntaxHelper.cs @@ -23,18 +23,17 @@ namespace SonarAnalyzer.Helpers; internal static class VisualBasicSyntaxHelper { private static readonly SyntaxKind[] LiteralSyntaxKinds = - new[] - { + [ SyntaxKind.CharacterLiteralExpression, SyntaxKind.FalseLiteralExpression, SyntaxKind.NothingLiteralExpression, SyntaxKind.NumericLiteralExpression, SyntaxKind.StringLiteralExpression, SyntaxKind.TrueLiteralExpression, - }; + ]; public static SyntaxNode GetTopMostContainingMethod(this SyntaxNode node) => - node.AncestorsAndSelf().LastOrDefault(ancestor => ancestor is MethodBaseSyntax || ancestor is PropertyBlockSyntax); + node.AncestorsAndSelf().LastOrDefault(x => x is MethodBaseSyntax || x is PropertyBlockSyntax); public static SyntaxNode RemoveParentheses(this SyntaxNode expression) { @@ -83,17 +82,20 @@ public static StatementSyntax GetSucceedingStatement(this StatementSyntax curren #endregion Statement + public static bool HasAncestor(this SyntaxNode syntaxNode, params SyntaxKind[] syntaxKinds) => + syntaxNode.Ancestors().Any(x => x.IsAnyKind(syntaxKinds)); + public static bool IsNothingLiteral(this SyntaxNode syntaxNode) => - syntaxNode != null && syntaxNode.IsKind(SyntaxKind.NothingLiteralExpression); + syntaxNode is not null && syntaxNode.IsKind(SyntaxKind.NothingLiteralExpression); public static bool IsAnyKind(this SyntaxNode syntaxNode, params SyntaxKind[] syntaxKinds) => - syntaxNode != null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); + syntaxNode is not null && syntaxKinds.Contains((SyntaxKind)syntaxNode.RawKind); public static bool IsAnyKind(this SyntaxToken syntaxToken, ISet collection) => collection.Contains((SyntaxKind)syntaxToken.RawKind); public static bool IsAnyKind(this SyntaxNode syntaxNode, ISet collection) => - syntaxNode != null && collection.Contains((SyntaxKind)syntaxNode.RawKind); + syntaxNode is not null && collection.Contains((SyntaxKind)syntaxNode.RawKind); public static bool IsAnyKind(this SyntaxToken syntaxToken, params SyntaxKind[] syntaxKinds) => syntaxKinds.Contains((SyntaxKind)syntaxToken.RawKind); @@ -102,7 +104,7 @@ public static bool IsAnyKind(this SyntaxTrivia syntaxTrivia, params SyntaxKind[] syntaxKinds.Contains((SyntaxKind)syntaxTrivia.RawKind); public static bool AnyOfKind(this IEnumerable nodes, SyntaxKind kind) => - nodes.Any(n => n.RawKind == (int)kind); + nodes.Any(x => x.RawKind == (int)kind); public static bool IsMethodInvocation(this InvocationExpressionSyntax expression, KnownType type, string methodName, SemanticModel semanticModel) => semanticModel.GetSymbolInfo(expression).Symbol is IMethodSymbol methodSymbol && @@ -113,30 +115,17 @@ public static bool IsMethodInvocation(this InvocationExpressionSyntax expression public static bool IsOnBase(this ExpressionSyntax expression) => IsOn(expression, SyntaxKind.MyBaseExpression); - private static bool IsOn(this ExpressionSyntax expression, SyntaxKind onKind) - { - switch (expression?.Kind()) + private static bool IsOn(this ExpressionSyntax expression, SyntaxKind onKind) => + expression switch { - case SyntaxKind.InvocationExpression: - return IsOn(((InvocationExpressionSyntax)expression).Expression, onKind); - - case SyntaxKind.GlobalName: - case SyntaxKind.GenericName: - case SyntaxKind.IdentifierName: - case SyntaxKind.QualifiedName: - // This is a simplification as we don't check where the method is defined (so this could be this or base) - return true; - - case SyntaxKind.SimpleMemberAccessExpression: - return ((MemberAccessExpressionSyntax)expression).Expression.RemoveParentheses().IsKind(onKind); - - case SyntaxKind.ConditionalAccessExpression: - return ((ConditionalAccessExpressionSyntax)expression).Expression.RemoveParentheses().IsKind(onKind); - - default: - return false; - } - } + InvocationExpressionSyntax invocation => IsOn(invocation.Expression, onKind), + // This is a simplification as we don't check where the method is defined (so this could be this or base) + GlobalNameSyntax or GenericNameSyntax or IdentifierNameSyntax or QualifiedNameSyntax => true, + MemberAccessExpressionSyntax memberAccessExpression when memberAccessExpression.IsKind(SyntaxKind.SimpleMemberAccessExpression) => + memberAccessExpression.Expression.RemoveParentheses().IsKind(onKind), + ConditionalAccessExpressionSyntax conditionalAccess => conditionalAccess.Expression.RemoveParentheses().IsKind(onKind), + _ => false, + }; public static string GetName(this SyntaxNode expression) => expression.GetIdentifier()?.ValueText ?? string.Empty; @@ -145,7 +134,7 @@ public static bool NameIs(this ExpressionSyntax expression, string name) => expression.GetName().Equals(name, StringComparison.InvariantCultureIgnoreCase); public static bool HasConstantValue(this ExpressionSyntax expression, SemanticModel semanticModel) => - expression.RemoveParentheses().IsAnyKind(LiteralSyntaxKinds) || expression.FindConstantValue(semanticModel) != null; + expression.RemoveParentheses().IsAnyKind(LiteralSyntaxKinds) || expression.FindConstantValue(semanticModel) is not null; public static string StringValue(this SyntaxNode node, SemanticModel semanticModel) => node switch @@ -163,49 +152,31 @@ topParenthesizedExpression.Parent is AssignmentStatementSyntax assignment && assignment.Left == topParenthesizedExpression; } - public static bool IsComment(this SyntaxTrivia trivia) - { - switch (trivia.Kind()) - { - case SyntaxKind.CommentTrivia: - case SyntaxKind.DocumentationCommentExteriorTrivia: - case SyntaxKind.DocumentationCommentTrivia: - return true; - - default: - return false; - } - } + public static bool IsComment(this SyntaxTrivia trivia) => + trivia.IsAnyKind( + SyntaxKind.CommentTrivia, + SyntaxKind.DocumentationCommentExteriorTrivia, + SyntaxKind.DocumentationCommentTrivia); public static Location FindIdentifierLocation(this MethodBlockBaseSyntax methodBlockBase) => GetIdentifierOrDefault(methodBlockBase)?.GetLocation(); - public static SyntaxToken? GetIdentifierOrDefault(this MethodBlockBaseSyntax methodBlockBase) - { - var blockStatement = methodBlockBase?.BlockStatement; - - switch (blockStatement?.Kind()) + public static SyntaxToken? GetIdentifierOrDefault(this MethodBlockBaseSyntax methodBlockBase) => + methodBlockBase?.BlockStatement switch { - case SyntaxKind.SubNewStatement: - return (blockStatement as SubNewStatementSyntax)?.NewKeyword; - - case SyntaxKind.FunctionStatement: - case SyntaxKind.SubStatement: - return (blockStatement as MethodStatementSyntax)?.Identifier; - - default: - return null; - } - } + SubNewStatementSyntax subNewStatement => subNewStatement.NewKeyword, + MethodStatementSyntax methodStatement => methodStatement.Identifier, + _ => null, + }; - public static string GetIdentifierText(this MethodBlockSyntax method) - => method.SubOrFunctionStatement.Identifier.ValueText; + public static string GetIdentifierText(this MethodBlockSyntax method) => + method.SubOrFunctionStatement.Identifier.ValueText; - public static SeparatedSyntaxList? GetParameters(this MethodBlockSyntax method) - => method.BlockStatement?.ParameterList?.Parameters; + public static SeparatedSyntaxList? GetParameters(this MethodBlockSyntax method) => + method.BlockStatement?.ParameterList?.Parameters; public static ExpressionSyntax Get(this ArgumentListSyntax argumentList, int index) => - argumentList != null && argumentList.Arguments.Count > index + argumentList is not null && argumentList.Arguments.Count > index ? argumentList.Arguments[index].GetExpression().RemoveParentheses() : null; @@ -215,7 +186,7 @@ public static ExpressionSyntax Get(this ArgumentListSyntax argumentList, int ind /// There can be zero, one or more results based on parameter type (Optional or ParamArray/params). /// public static ImmutableArray ArgumentValuesForParameter(SemanticModel semanticModel, ArgumentListSyntax argumentList, string parameterName) => - argumentList != null + argumentList is not null && new VisualBasicMethodParameterLookup(argumentList, semanticModel).TryGetSyntax(parameterName, out var expressions) ? expressions : ImmutableArray.Empty; diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/Hotspots/HardcodedIpAddress.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/Hotspots/HardcodedIpAddress.cs index abf449123b0..89bac13761d 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/Hotspots/HardcodedIpAddress.cs +++ b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/Hotspots/HardcodedIpAddress.cs @@ -30,7 +30,7 @@ public HardcodedIpAddress() : this(AnalyzerConfiguration.Hotspot) { } public HardcodedIpAddress(IAnalyzerConfiguration analyzerConfiguration) : base(analyzerConfiguration) { } protected override bool HasAttributes(SyntaxNode literalExpression) => - literalExpression.Ancestors().AnyOfKind(SyntaxKind.Attribute); + literalExpression.HasAncestor(SyntaxKind.Attribute); protected override string GetAssignedVariableName(SyntaxNode stringLiteral) => stringLiteral.FirstAncestorOrSelf(IsVariableIdentifier)?.ToString(); diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/StringLiteralShouldNotBeDuplicated.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/StringLiteralShouldNotBeDuplicated.cs index 5e8c974c225..1fb9b6f7cba 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/StringLiteralShouldNotBeDuplicated.cs +++ b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/StringLiteralShouldNotBeDuplicated.cs @@ -39,7 +39,7 @@ protected override bool IsMatchingMethodParameterName(LiteralExpressionSyntax li ?? false; protected override bool IsInnerInstance(SonarSyntaxNodeReportingContext context) => - context.Node.Ancestors().Any(x => x is ClassBlockSyntax || x is StructureBlockSyntax); + context.Node.HasAncestor(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock); protected override IEnumerable FindLiteralExpressions(SyntaxNode node) => node.DescendantNodes(n => !n.IsKind(SyntaxKind.AttributeList)) diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs index f57d5ce1b5e..a66d940c47e 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs +++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/PublicMethodArgumentsShouldBeCheckedForNull.cs @@ -85,11 +85,10 @@ public override void Visit(SyntaxNode node) public override void VisitIdentifierName(IdentifierNameSyntax node) => DereferencesMethodArguments |= argumentNames.Contains(node.GetName()) - && node.Ancestors().Any(x => x.IsAnyKind( - AwaitExpression, + && node.HasAncestor(AwaitExpression, InvocationExpression, // For array access ForEachStatement, ThrowStatement, - SimpleMemberAccessExpression)); + SimpleMemberAccessExpression); } }