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

Update SA1212 to also trigger for an init accessor before a getter #3661

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,91 @@

namespace StyleCop.Analyzers.Test.CSharp9.OrderingRules
{
using System.Threading;
using System.Threading.Tasks;
sharwell marked this conversation as resolved.
Show resolved Hide resolved
using StyleCop.Analyzers.Test.CSharp8.OrderingRules;
using StyleCop.Analyzers.Test.Verifiers;
sharwell marked this conversation as resolved.
Show resolved Hide resolved
using Xunit;
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
StyleCop.Analyzers.OrderingRules.SA1212PropertyAccessorsMustFollowOrder,
StyleCop.Analyzers.OrderingRules.SA1212SA1213CodeFixProvider>;

public class SA1212CSharp9UnitTests : SA1212CSharp8UnitTests
{
[Fact]
[WorkItem(3652, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3652")]
public async Task TestAutoPropertyDeclarationInitBeforeGetterAsync()
{
var testCode = @"
public class Foo
{
public int Prop { [|init;|] get; }
}";

var fixedCode = @"
public class Foo
{
public int Prop { get; init; }
}";

var test = new CSharpTest
{
TestCode = testCode,
FixedCode = fixedCode,
ReferenceAssemblies = GenericAnalyzerTest.ReferenceAssembliesNet50,
};
await test.RunAsync(CancellationToken.None).ConfigureAwait(false);
sharwell marked this conversation as resolved.
Show resolved Hide resolved
}

[Fact]
[WorkItem(3652, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3652")]
public async Task TestPropertyWithBackingFieldDeclarationInitBeforeGetterAsync()
{
var testCode = @"
public class Foo
{
private int i = 0;

public int Prop
{
[|init
{
i = value;
}|]

get
{
return i;
}
}
}";

var fixedCode = @"
public class Foo
{
private int i = 0;

public int Prop
{
get
{
return i;
}

init
{
i = value;
}
}
}";

var test = new CSharpTest
{
TestCode = testCode,
FixedCode = fixedCode,
ReferenceAssemblies = GenericAnalyzerTest.ReferenceAssembliesNet50,
};
await test.RunAsync(CancellationToken.None).ConfigureAwait(false);
sharwell marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ public int Prop
}

[Fact]
public async Task TestAutoPropertydDeclarationSetterBeforeGetterAsync()
public async Task TestAutoPropertyDeclarationSetterBeforeGetterAsync()
{
var testCode = @"
public class Foo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ internal static class SyntaxKindEx
public const SyntaxKind NullableDirectiveTrivia = (SyntaxKind)9055;
public const SyntaxKind FunctionPointerType = (SyntaxKind)9056;
public const SyntaxKind FunctionPointerParameter = (SyntaxKind)9057;
public const SyntaxKind InitAccessorDeclaration = (SyntaxKind)9060;
public const SyntaxKind WithExpression = (SyntaxKind)9061;
public const SyntaxKind WithInitializerExpression = (SyntaxKind)9062;
public const SyntaxKind RecordDeclaration = (SyntaxKind)9063;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace StyleCop.Analyzers.OrderingRules
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using StyleCop.Analyzers.Lightup;

/// <summary>
/// A get accessor appears after a set accessor within a property or indexer.
Expand Down Expand Up @@ -99,7 +100,7 @@ private static void AnalyzeProperty(SyntaxNodeAnalysisContext context, BasePrope
return;
}

if (accessors[0].Kind() == SyntaxKind.SetAccessorDeclaration &&
if ((accessors[0].Kind() == SyntaxKind.SetAccessorDeclaration || accessors[0].Kind() == SyntaxKindEx.InitAccessorDeclaration) &&
sharwell marked this conversation as resolved.
Show resolved Hide resolved
accessors[1].Kind() == SyntaxKind.GetAccessorDeclaration)
{
context.ReportDiagnostic(Diagnostic.Create(Descriptor, accessors[0].GetLocation()));
Expand Down
4 changes: 2 additions & 2 deletions documentation/SA1212.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@

## Cause

A get accessor appears after a set accessor within a property or indexer.
A get accessor appears after a set or init accessor within a property or indexer.

## Rule description

A violation of this rule occurs when a get accessor is placed after a set accessor within a property or indexer. To comply with this rule, the get accessor should appear before the set accessor.
A violation of this rule occurs when a get accessor is placed after a set or init accessor within a property or indexer. To comply with this rule, the get accessor should appear first.

For example, the following code would raise an instance of this violation:

Expand Down