From 093f9288816666598bc705442a2b2b01137c1bcf Mon Sep 17 00:00:00 2001 From: Azarasi Date: Sat, 21 Sep 2024 10:42:42 +0900 Subject: [PATCH 1/2] SA1313: Adding features and tests. --- .../NamingRules/SA1313CSharp8UnitTests.cs | 32 ++++++ .../NamingRules/SA1313CSharp9UnitTests.cs | 26 +++++ .../NamingRules/SA1313UnitTests.cs | 106 +++++++++++++++++- .../Helpers/SyntaxTreeHelpers.cs | 65 +++++++++++ ...ameterNamesMustBeginWithLowerCaseLetter.cs | 101 +++++++++++++++-- documentation/SA1313.md | 8 +- 6 files changed, 324 insertions(+), 14 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1313CSharp8UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1313CSharp8UnitTests.cs index 37032ad83..bf2445606 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1313CSharp8UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1313CSharp8UnitTests.cs @@ -5,11 +5,43 @@ namespace StyleCop.Analyzers.Test.CSharp8.NamingRules { + using System.Threading; + using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using StyleCop.Analyzers.Test.CSharp7.NamingRules; + using Xunit; + using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier< + StyleCop.Analyzers.NamingRules.SA1313ParameterNamesMustBeginWithLowerCaseLetter, + StyleCop.Analyzers.NamingRules.RenameToLowerCaseCodeFixProvider>; public partial class SA1313CSharp8UnitTests : SA1313CSharp7UnitTests { + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestClosureParameterNamedUnusedAsync() + { + var testCode = @"public class TypeName +{ + public int MethodName(int _used, int _unused, int _1, int _2, int _, int __) + { + return _used + Closure(0, 1); + + int Closure(int _10, int _11) + { + return _2 + _11; + } + } +}"; + + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("_used").WithLocation(3, 31), + Diagnostic().WithArguments("_2").WithLocation(3, 63), + Diagnostic().WithArguments("_11").WithLocation(7, 34), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + protected override DiagnosticResult[] GetInvalidMethodOverrideShouldNotProduceDiagnosticAsyncDiagnostics() { return new DiagnosticResult[] diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1313CSharp9UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1313CSharp9UnitTests.cs index bd393fb24..53e31ba71 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1313CSharp9UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1313CSharp9UnitTests.cs @@ -41,5 +41,31 @@ public R(int a, int b) await VerifyCSharpFixAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, fixedCode, CancellationToken.None).ConfigureAwait(false); } + + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestLambdaParameterWithAllUnderscoresAsync() + { + var testCode = @"public class TypeName +{ + public void MethodName() + { + System.Action action1 = _ => { }; + System.Action action2 = (_, _) => { }; + System.Action action3 = (_, _, _) => { }; + System.Action action4 = (_, _, _, _) => { }; + System.Action action5 = delegate(int _) { }; + System.Action action6 = delegate(int _, int _) { }; + System.Action action7 = delegate(int _, int _, int _) { }; + System.Action action8 = delegate(int _, int _, int _, int _) { }; + + System.Action action9 = (_, a) => { }; + System.Action action10 = (a, _) => { }; + System.Action action11 = (_, a, _) => { }; + System.Action action12 = (a, _, _) => { }; + } +}"; + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs index 216a0e9b8..d9d253779 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs @@ -436,6 +436,7 @@ public void MethodName() [Fact] [WorkItem(1606, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1606")] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] public async Task TestLambdaParameterNamedDoubleUnderscoreAsync() { var testCode = @"public class TypeName @@ -448,7 +449,13 @@ public void MethodName() } }"; - await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("__").WithLocation(5, 38), + Diagnostic().WithArguments("__").WithLocation(6, 39), + Diagnostic().WithArguments("__").WithLocation(7, 51), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); } /// @@ -457,6 +464,7 @@ public void MethodName() /// A representing the asynchronous operation. [Fact] [WorkItem(1606, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1606")] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] public async Task TestLambdaParameterNamedDoubleUnderscoreUsageAsync() { var testCode = @"public class TypeName @@ -469,7 +477,13 @@ public void MethodName() } }"; - await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("__").WithLocation(5, 43), + Diagnostic().WithArguments("__").WithLocation(6, 44), + Diagnostic().WithArguments("__").WithLocation(7, 56), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); } [Fact] @@ -492,17 +506,52 @@ public void MethodName() Diagnostic().WithArguments("___").WithLocation(6, 39), Diagnostic().WithArguments("___").WithLocation(7, 51), }; - await VerifyCSharpFixAsync(testCode, expected, testCode, CancellationToken.None).ConfigureAwait(false); + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestLambdaParameterWithIncreasingNumberOfUnderscoresAsync() + { + var testCode = @"public class TypeName +{ + public void MethodName() + { + System.Action action1 = _ => { }; + System.Action action2 = (_, __) => { }; + System.Action action3 = (_, __, ___) => { }; + System.Action action4 = (_, __, ___, ____) => { }; + System.Action action5 = delegate(int _) { }; + System.Action action6 = delegate(int _, int __) { }; + System.Action action7 = delegate(int _, int __, int ___) { }; + System.Action action8 = delegate(int _, int __, int ___, int ____) { }; + + System.Action action9 = (a, _) => { }; + System.Action action10 = (a, __) => { }; + System.Action action11 = (_, a, __) => { }; + System.Action action12 = (_, __, a) => { }; + System.Action action13 = (_, a, ___) => { }; + } +}"; + + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("__").WithLocation(15, 48), + Diagnostic().WithArguments("___").WithLocation(18, 56), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); } [Fact] [WorkItem(1343, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1343")] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] public async Task TestMethodParameterNamedUnderscoreAsync() { var testCode = @"public class TypeName { public void MethodName(int _) { + ++_; } }"; @@ -510,6 +559,35 @@ public void MethodName(int _) await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); } + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestMethodParameterNamedUnderscoresUsedAsync() + { + var testCode = @"public class TypeName +{ + public void MethodName1(int _1, short _2) + { + ++_1; + ++_2; + } + + public void MethodName2(int _, short __) + { + ++_; + ++__; + } +}"; + + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("_1").WithLocation(3, 33), + Diagnostic().WithArguments("_2").WithLocation(3, 43), + Diagnostic().WithArguments("_").WithLocation(9, 33), + Diagnostic().WithArguments("__").WithLocation(9, 42), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + [Fact] [WorkItem(1606, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1606")] public async Task TestMethodParameterNamedDoubleUnderscoreAsync() @@ -588,6 +666,28 @@ public TestClass(string text, bool flag) await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); } + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestMethodParameterNamedUnusedAsync() + { + var testCode = @"public class TypeName +{ + public int MethodName(int _used, int _unused, int _, int _1, int _2, int ___, int __) + { + return _used + _2; + } +}"; + + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("_used").WithLocation(3, 31), + Diagnostic().WithArguments("_2").WithLocation(3, 70), + Diagnostic().WithArguments("___").WithLocation(3, 78), + Diagnostic().WithArguments("__").WithLocation(3, 87), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + /// /// Verify that an invalid method override will not produce a diagnostic nor crash the analyzer. /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs index c917df7a5..6c90a1733 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs @@ -7,6 +7,7 @@ namespace StyleCop.Analyzers.Helpers { using System; using System.Collections.Concurrent; + using System.Collections.Generic; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; @@ -72,6 +73,70 @@ public static bool IsWhitespaceOnly(this SyntaxTree tree, CancellationToken canc && TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1; } + /// + /// Recursively descends through the tree structure, enumerating all Statement nodes encountered during the traversal. + /// + /// The syntax node to recursively. + /// Enumerated StatementSyntax. + public static IEnumerable StatementDescendRecursively(this SyntaxNode syntaxNode) + { + foreach (var statement in syntaxNode.ChildNodes().OfType()) + { + yield return statement; + + foreach (var innerItem in StatementDescendRecursively(statement)) + { + yield return innerItem; + } + } + } + + /// + /// Recursively descends through the tree structure, enumerating all Expression nodes encountered during the traversal. + /// + /// The syntax node to recursively. + /// Enumerated ExpressionSyntax. + public static IEnumerable ExpressionDescendRecursively(this SyntaxNode syntaxNode) + { + foreach (var node in syntaxNode.ChildNodes()) + { + if (node is StatementSyntax statementSyntax) + { + foreach (var expression in ExpressionDescendRecursively(statementSyntax)) + { + yield return expression; + } + } + else if (node is ExpressionSyntax expressionSyntax) + { + yield return expressionSyntax; + + foreach (var expression in ExpressionDescendRecursively(expressionSyntax)) + { + yield return expression; + } + } + } + } + + /// + /// Recursively descends through the tree structure, enumerating all Expression nodes encountered during the traversal. + /// + /// The expression syntax to recursively. + /// Enumerated ExpressionSyntax. + public static IEnumerable ExpressionDescendRecursively(this ExpressionSyntax expressionSyntax) + { + foreach (var inner in expressionSyntax.ChildNodes().OfType()) + { + yield return inner; + + foreach (var innerItem in ExpressionDescendRecursively(inner)) + { + yield return innerItem; + } + } + } + internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictionary cache) { if (tree == null) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1313ParameterNamesMustBeginWithLowerCaseLetter.cs b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1313ParameterNamesMustBeginWithLowerCaseLetter.cs index 869d5a2ae..310221f97 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1313ParameterNamesMustBeginWithLowerCaseLetter.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1313ParameterNamesMustBeginWithLowerCaseLetter.cs @@ -7,6 +7,7 @@ namespace StyleCop.Analyzers.NamingRules { using System; using System.Collections.Immutable; + using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -86,9 +87,19 @@ private static void HandleParameter(SyntaxNodeAnalysisContext context) return; } - if ((name == "_" || name == "__") && IsInLambda(syntax)) + var nameChars = name.ToCharArray(); + if (nameChars[0] == '_') { - return; + var isAllUnderscore = nameChars.All(c => c == '_'); + if (IsUnused(syntax, isAllUnderscore ? name.Length : null)) + { + return; + } + + if (isAllUnderscore && IsInLambda(syntax, name.Length)) + { + return; + } } if (NameMatchesAbstraction(syntax, context.SemanticModel)) @@ -100,25 +111,97 @@ private static void HandleParameter(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(Diagnostic.Create(Descriptor, identifier.GetLocation(), name)); } - private static bool IsInLambda(ParameterSyntax syntax) + private static bool IsUnused(ParameterSyntax syntax, int? underscoreCount) { - if (syntax.Parent.IsKind(SyntaxKind.SimpleLambdaExpression)) + var parent = syntax.Parent.Parent; + if (parent.IsKind(SyntaxKind.MethodDeclaration)) { - return true; + var methodSyntax = (MethodDeclarationSyntax)parent; + return !IsParameterUsed(methodSyntax.Body) + && (!underscoreCount.HasValue + || IsIncrementalName(syntax, underscoreCount.Value, methodSyntax.ParameterList)); } + else + { + try + { + var methodSyntax = (LocalFunctionStatementSyntaxWrapper)parent; - if (syntax.Parent.Parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression) - || syntax.Parent.Parent.IsKind(SyntaxKind.AnonymousMethodExpression)) + return !IsParameterUsed(methodSyntax.Body) + && (!underscoreCount.HasValue + || IsIncrementalName(syntax, underscoreCount.Value, methodSyntax.ParameterList)); + } + catch + { + } + } + + return false; + + bool IsParameterUsed(BlockSyntax blockSyntax) + { + var valueName = syntax.Identifier.ValueText; + return blockSyntax.ExpressionDescendRecursively() + .OfType() + .Any(x => x.Identifier.ValueText == valueName); + } + } + + private static bool IsInLambda(ParameterSyntax syntax, int underscoreCount) + { + var parent = syntax.Parent; + if (parent.IsKind(SyntaxKind.SimpleLambdaExpression)) { - return true; + return underscoreCount == 1; + } + + parent = parent.Parent; + if (parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression)) + { + return IsIncrementalName(syntax, underscoreCount, ((ParenthesizedLambdaExpressionSyntax)parent).ParameterList); + } + else if (parent.IsKind(SyntaxKind.AnonymousMethodExpression)) + { + return IsIncrementalName(syntax, underscoreCount, ((AnonymousMethodExpressionSyntax)parent).ParameterList); } return false; } + private static bool IsIncrementalName(ParameterSyntax syntax, int underscoreCount, ParameterListSyntax parameterList) + { + bool isSingleUnderscore = underscoreCount == 1; + int lastUnderscoreCount = 0; + foreach (var parameter in parameterList.Parameters) + { + if (parameter == syntax) + { + break; + } + + var name = parameter.Identifier.ValueText; + if (string.IsNullOrEmpty(name) + || name.ToCharArray().Any(c => c != '_')) + { + continue; + } + + if (isSingleUnderscore + && name.Length != 1) + { + isSingleUnderscore = false; + } + + lastUnderscoreCount = name.Length; + } + + return isSingleUnderscore + || lastUnderscoreCount == (underscoreCount - 1); + } + private static bool NameMatchesAbstraction(ParameterSyntax syntax, SemanticModel semanticModel) { - if (!(syntax.Parent is ParameterListSyntax parameterList)) + if (syntax.Parent is not ParameterListSyntax parameterList) { // This occurs for simple lambda expressions (without parentheses) return false; diff --git a/documentation/SA1313.md b/documentation/SA1313.md index ff11fb3c5..fdcee3621 100644 --- a/documentation/SA1313.md +++ b/documentation/SA1313.md @@ -25,8 +25,12 @@ The name of a parameter in C# does not begin with a lower-case letter. A violation of this rule occurs when the name of a parameter does not begin with a lower-case letter. -An exception to this rule is made for lambda parameters named `_` and `__`. These parameters are often used to designate a -placeholder parameter which is not actually used in the body of the lambda expression. +### Exceptions + +1. An exception to this rule is made for lambda parameters that have names consisting only of '_', such as '_', '__', or '___'. + These parameters are often used to designate a placeholder parameter which is not actually used in the body of the lambda expression. +2. An exception to this rule is made for method parameters whose names start with '_'. + These parameters are often used to indicate parameters that are not actually used in the body of the method. If the parameter name is intended to match the name of an item associated with Win32 or COM, and thus needs to begin with an upper-case letter, place the parameter within a special `NativeMethods` class. A `NativeMethods` class is any From 5ca9aeb4d32229cb06c9e65a96a210c0c8fb2c3f Mon Sep 17 00:00:00 2001 From: Azarasi Date: Sun, 22 Sep 2024 21:13:51 +0900 Subject: [PATCH 2/2] Fix coverage Remove unused method --- .../HelperTests/SyntaxTreeHelpersTests.cs | 21 ++++++++++ .../NamingRules/SA1313UnitTests.cs | 41 ++++++++++++++++++- .../Helpers/SyntaxTreeHelpers.cs | 18 -------- 3 files changed, 60 insertions(+), 20 deletions(-) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers.Test/HelperTests/SyntaxTreeHelpersTests.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/HelperTests/SyntaxTreeHelpersTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/HelperTests/SyntaxTreeHelpersTests.cs new file mode 100644 index 000000000..164c9ef3e --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/HelperTests/SyntaxTreeHelpersTests.cs @@ -0,0 +1,21 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#nullable disable + +namespace StyleCop.Analyzers.Test.HelperTests +{ + using Microsoft.CodeAnalysis; + using StyleCop.Analyzers.Helpers; + using Xunit; + + public class SyntaxTreeHelpersTests + { + [Fact] + public void TestContainsUsingAliasArgumentIsNull() + { + SyntaxTree tree = null; + Assert.False(tree.ContainsUsingAlias(null)); + } + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs index d9d253779..31e2fc120 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1313UnitTests.cs @@ -594,12 +594,49 @@ public async Task TestMethodParameterNamedDoubleUnderscoreAsync() { var testCode = @"public class TypeName { - public void MethodName(int __) + public void MethodName(int __, int _) { } }"; - DiagnosticResult expected = Diagnostic().WithArguments("__").WithLocation(3, 32); + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("__").WithLocation(3, 32), + Diagnostic().WithArguments("_").WithLocation(3, 40), + }; + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestMethodParameterNamedIncrementUnderscoreAsync() + { + var testCode = @"public class TypeName +{ + public void MethodName(int _, int __, int ___) + { + } +}"; + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2974, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2974")] + public async Task TestMethodParameterNamedIrregularUnderscoreAsync() + { + var testCode = @"public class TypeName +{ + public void MethodName1(int __, int _) { } + public void MethodName2(int _, int ___, int __) { } +}"; + + DiagnosticResult[] expected = + { + Diagnostic().WithArguments("__").WithLocation(3, 33), + Diagnostic().WithArguments("_").WithLocation(3, 41), + Diagnostic().WithArguments("___").WithLocation(4, 40), + Diagnostic().WithArguments("__").WithLocation(4, 49), + }; await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs index 6c90a1733..70ca30828 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs @@ -73,24 +73,6 @@ public static bool IsWhitespaceOnly(this SyntaxTree tree, CancellationToken canc && TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1; } - /// - /// Recursively descends through the tree structure, enumerating all Statement nodes encountered during the traversal. - /// - /// The syntax node to recursively. - /// Enumerated StatementSyntax. - public static IEnumerable StatementDescendRecursively(this SyntaxNode syntaxNode) - { - foreach (var statement in syntaxNode.ChildNodes().OfType()) - { - yield return statement; - - foreach (var innerItem in StatementDescendRecursively(statement)) - { - yield return innerItem; - } - } - } - /// /// Recursively descends through the tree structure, enumerating all Expression nodes encountered during the traversal. ///