-
Notifications
You must be signed in to change notification settings - Fork 510
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
Implemented SA1117 diagnostic + unit tests #1480
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
namespace StyleCop.Analyzers.Test.ReadabilityRules | ||
{ | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using StyleCop.Analyzers.ReadabilityRules; | ||
using TestHelper; | ||
using Xunit; | ||
|
||
public class SA1117UnitTests : DiagnosticVerifier | ||
{ | ||
public static IEnumerable<object[]> GetTestDeclarations(string delimiter) | ||
{ | ||
yield return new object[] { $"public Foo(int a, int b,{delimiter} string s) {{ }}" }; | ||
yield return new object[] { $"public object Bar(int a, int b,{delimiter} string s) => null;" }; | ||
yield return new object[] { $"public object this[int a, int b,{delimiter} string s] => null;" }; | ||
yield return new object[] { $"public delegate void Bar(int a, int b,{delimiter} string s);" }; | ||
} | ||
|
||
public static IEnumerable<object[]> GetTestConstructorInitializers(string delimiter) | ||
{ | ||
yield return new object[] { $"this(42, 43, {delimiter} \"hello\")" }; | ||
yield return new object[] { $"base(42, 43, {delimiter} \"hello\")" }; | ||
} | ||
|
||
public static IEnumerable<object[]> GetTestExpressions(string delimiter) | ||
{ | ||
yield return new object[] { $"Bar(1, 2, {delimiter} 2)", 13 }; | ||
yield return new object[] { $"System.Action<int, int, int> func = (int x, int y, {delimiter} int z) => Bar(x, y, z)", 41 }; | ||
yield return new object[] { $"System.Action<int, int, int> func = delegate(int x, int y, {delimiter} int z) {{ Bar(x, y, z); }}", 49 }; | ||
yield return new object[] { $"new System.DateTime(2015, 9, {delimiter} 14)", 20 }; | ||
yield return new object[] { $"var arr = new string[2, 2, {delimiter} 2];", 30 }; | ||
yield return new object[] { $"char cc = (new char[3, 3, 3])[2, 2,{delimiter} 2];", 36 }; | ||
yield return new object[] { $"char? c = (new char[3, 3, 3])?[2, 2,{delimiter} 2];", 37 }; | ||
yield return new object[] { $"long ll = this[2, 2,{delimiter} 2];", 24 }; | ||
} | ||
|
||
public static IEnumerable<object[]> ValidTestExpressions() | ||
{ | ||
yield return new object[] { $"System.Action func = () => Bar(0, 2, 3)", 0 }; | ||
yield return new object[] { $"System.Action<int> func = x => Bar(x, 2, 3)", 0 }; | ||
yield return new object[] { $"System.Action func = delegate {{ Bar(0, 0, 0); }}", 0 }; | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestDeclarations), "")] | ||
public async Task TestValidDeclarationAsync(string declaration) | ||
{ | ||
var testCode = $@" | ||
class Foo | ||
{{ | ||
{declaration} | ||
}}"; | ||
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestDeclarations), "\r\n")] | ||
public async Task TestInvalidDeclarationAsync(string declaration) | ||
{ | ||
var testCode = $@" | ||
class Foo | ||
{{ | ||
{declaration} | ||
}}"; | ||
|
||
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(5, 2); | ||
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestConstructorInitializers), "")] | ||
public async Task TestValidConstructorInitializerAsync(string initializer) | ||
{ | ||
var testCode = $@" | ||
class Base | ||
{{ | ||
public Base(int a, int b, string s) | ||
{{ | ||
}} | ||
}} | ||
|
||
class Derived : Base | ||
{{ | ||
public Derived() | ||
: {initializer} | ||
{{ | ||
}} | ||
|
||
public Derived(int i, int j, string z) | ||
: base(i, j, z) | ||
{{ | ||
}} | ||
}}"; | ||
|
||
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestConstructorInitializers), "\r\n")] | ||
public async Task TestInvalidConstructorInitializerAsync(string initializer) | ||
{ | ||
var testCode = $@" | ||
class Base | ||
{{ | ||
public Base(int a, int b, string s) | ||
{{ | ||
}} | ||
}} | ||
|
||
class Derived : Base | ||
{{ | ||
public Derived() | ||
: {initializer} | ||
{{ | ||
}} | ||
|
||
public Derived(int i, int j, string z) | ||
: base(i, j, z) | ||
{{ | ||
}} | ||
}}"; | ||
|
||
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(13, 2); | ||
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestExpressions), "")] | ||
[MemberData(nameof(ValidTestExpressions))] | ||
public async Task TestValidExpressionAsync(string expression, int column) | ||
{ | ||
var testCode = $@" | ||
class Foo | ||
{{ | ||
public void Bar(int i, int j, int k) | ||
{{ | ||
}} | ||
|
||
public void Baz() | ||
{{ | ||
{expression}; | ||
}} | ||
|
||
public long this[int a, int b, int s] => a + b + s; | ||
}}"; | ||
|
||
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(GetTestExpressions), "\r\n")] | ||
public async Task TestInvalidExpressionAsync(string expression, int column) | ||
{ | ||
var testCode = $@" | ||
class Foo | ||
{{ | ||
public void Bar(int i, int j, int k) | ||
{{ | ||
}} | ||
|
||
public void Baz() | ||
{{ | ||
{expression}; | ||
}} | ||
|
||
public long this[int a, int b, int s] => a + b + s; | ||
}}"; | ||
|
||
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(11, 2); | ||
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Fact] | ||
public async Task TestValidAttributeAsync() | ||
{ | ||
var testCode = @" | ||
[System.AttributeUsage(System.AttributeTargets.Class)] | ||
public class MyAttribute : System.Attribute | ||
{ | ||
public MyAttribute(int a, int b, int c) | ||
{ | ||
} | ||
} | ||
|
||
[MyAttribute(1, 2, 3)] | ||
class Foo | ||
{ | ||
} | ||
|
||
// This is a regression test for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1211 | ||
[System.Obsolete] | ||
class ObsoleteType | ||
{ | ||
}"; | ||
|
||
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
[Fact] | ||
public async Task TestInvalidAttributeAsync() | ||
{ | ||
var testCode = @" | ||
[System.AttributeUsage(System.AttributeTargets.Class)] | ||
public class MyAttribute : System.Attribute | ||
{ | ||
public MyAttribute(int a, int b, int c) | ||
{ | ||
} | ||
} | ||
|
||
[MyAttribute( | ||
1, | ||
2, 3)] | ||
class Foo | ||
{ | ||
}"; | ||
|
||
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(12, 8); | ||
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers() | ||
{ | ||
yield return new SA1117ParametersMustBeOnSameLineOrSeparateLines(); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -301,7 +301,7 @@ | |
<value>The parameters to a C# method or indexer call or declaration are not all on the same line or each on a separate line.</value> | ||
</data> | ||
<data name="SA1117MessageFormat" xml:space="preserve"> | ||
<value /> | ||
<value>The parameters must all be placed on the same line or alternatively, each parameter must be placed on its own line.</value> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I think it reads better without "alternativelty" at all, since "each" is repeated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
</data> | ||
<data name="SA1117Title" xml:space="preserve"> | ||
<value>Parameters must be on same line or separate lines</value> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might add an expression that will handle multiple rank-specifiers. For example: