Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SA1313: Adding features and tests. #3892

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> action1 = _ => { };
System.Action<int, int> action2 = (_, _) => { };
System.Action<int, int, int> action3 = (_, _, _) => { };
System.Action<int, int, int, int> action4 = (_, _, _, _) => { };
System.Action<int> action5 = delegate(int _) { };
System.Action<int, int> action6 = delegate(int _, int _) { };
System.Action<int, int, int> action7 = delegate(int _, int _, int _) { };
System.Action<int, int, int, int> action8 = delegate(int _, int _, int _, int _) { };

System.Action<int, int> action9 = (_, a) => { };
System.Action<int, int> action10 = (a, _) => { };
System.Action<int, int, int> action11 = (_, a, _) => { };
System.Action<int, int, int> action12 = (a, _, _) => { };
}
}";
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

/// <summary>
Expand All @@ -457,6 +464,7 @@ public void MethodName()
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
[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
Expand All @@ -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]
Expand All @@ -492,36 +506,137 @@ 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<int> action1 = _ => { };
System.Action<int, int> action2 = (_, __) => { };
System.Action<int, int, int> action3 = (_, __, ___) => { };
System.Action<int, int, int, int> action4 = (_, __, ___, ____) => { };
System.Action<int> action5 = delegate(int _) { };
System.Action<int, int> action6 = delegate(int _, int __) { };
System.Action<int, int, int> action7 = delegate(int _, int __, int ___) { };
System.Action<int, int, int, int> action8 = delegate(int _, int __, int ___, int ____) { };

System.Action<int, int> action9 = (a, _) => { };
System.Action<int, int> action10 = (a, __) => { };
System.Action<int, int, int> action11 = (_, a, __) => { };
System.Action<int, int, int> action12 = (_, __, a) => { };
System.Action<int, int, int> 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 _)
{
++_;
}
}";

DiagnosticResult expected = Diagnostic().WithArguments("_").WithLocation(3, 32);
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()
{
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);
}

Expand Down Expand Up @@ -588,6 +703,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);
}

/// <summary>
/// Verify that an invalid method override will not produce a diagnostic nor crash the analyzer.
/// </summary>
Expand Down
47 changes: 47 additions & 0 deletions StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -72,6 +73,52 @@ public static bool IsWhitespaceOnly(this SyntaxTree tree, CancellationToken canc
&& TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1;
}

/// <summary>
/// Recursively descends through the tree structure, enumerating all Expression nodes encountered during the traversal.
/// </summary>
/// <param name="syntaxNode">The syntax node to recursively.</param>
/// <returns>Enumerated ExpressionSyntax.</returns>
public static IEnumerable<ExpressionSyntax> 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;
}
}
}
}

/// <summary>
/// Recursively descends through the tree structure, enumerating all Expression nodes encountered during the traversal.
/// </summary>
/// <param name="expressionSyntax">The expression syntax to recursively.</param>
/// <returns>Enumerated ExpressionSyntax.</returns>
public static IEnumerable<ExpressionSyntax> ExpressionDescendRecursively(this ExpressionSyntax expressionSyntax)
{
foreach (var inner in expressionSyntax.ChildNodes().OfType<ExpressionSyntax>())
{
yield return inner;

foreach (var innerItem in ExpressionDescendRecursively(inner))
{
yield return innerItem;
}
}
}

internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictionary<SyntaxTree, bool> cache)
{
if (tree == null)
Expand Down
Loading
Loading