diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/LayoutRules/SA1500CSharp7UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/LayoutRules/SA1500CSharp7UnitTests.cs index d505ebfaf..d5d6eb9c0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/LayoutRules/SA1500CSharp7UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/LayoutRules/SA1500CSharp7UnitTests.cs @@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Test.CSharp7.LayoutRules { using System.Threading; using System.Threading.Tasks; + using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; using StyleCop.Analyzers.Test.LayoutRules; using TestHelper; @@ -167,5 +168,173 @@ void LocalFunction6() await VerifyCSharpFixAsync(testCode, expectedDiagnostics, fixedTestCode, CancellationToken.None).ConfigureAwait(false); } + + /// + /// Verifies that no diagnostics are reported for the valid stackalloc array initializers defined in this test. + /// + /// + /// These are valid for SA1500 only, some will report other diagnostics. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestStackAllocArrayInitializersValidAsync() + { + var testCode = @"using System; + +public class TestClass +{ + public unsafe void TestMethod() + { + var array1 = stackalloc int[0] { }; + var array2 = stackalloc[] { 0, 1 }; + var array3 = stackalloc int[] { 0, 1 }; + var array4 = stackalloc int[] + { + }; + var array5 = stackalloc int[2] + { + 0, + 1, + }; + } +}"; + await VerifyCSharpDiagnosticAsync(LanguageVersion.CSharp7_3, testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Verifies that diagnostics will be reported for all invalid implicit stackalloc array initializer definitions. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestImplicitStackAllocArrayInitializersInvalidAsync() + { + var testCode = @" +public class TestClass +{ + public unsafe void TestMethod() + { + var invalidArray1 = stackalloc[] + { 0, 1 + }; + + var invalidArray2 = stackalloc[] + { + 0, 1 }; + + var invalidArray3 = stackalloc[] + { 0, 1 }; + + var invalidArray4 = stackalloc[] + { 0, 1 + }; + + var invalidArray5 = stackalloc[] + { + 0, 1 }; + } +}"; + + var fixedTestCode = @" +public class TestClass +{ + public unsafe void TestMethod() + { + var invalidArray1 = stackalloc[] + { + 0, 1 + }; + + var invalidArray2 = stackalloc[] + { + 0, 1 + }; + + var invalidArray3 = stackalloc[] + { + 0, 1 + }; + + var invalidArray4 = stackalloc[] + { + 0, 1 + }; + + var invalidArray5 = stackalloc[] + { + 0, 1 + }; + } +}"; + + DiagnosticResult[] expectedDiagnostics = + { + Diagnostic().WithLocation(7, 13), + Diagnostic().WithLocation(12, 22), + Diagnostic().WithLocation(15, 13), + Diagnostic().WithLocation(15, 20), + Diagnostic().WithLocation(18, 13), + Diagnostic().WithLocation(23, 22), + }; + + await VerifyCSharpFixAsync(LanguageVersion.CSharp7_3, testCode, expectedDiagnostics, fixedTestCode, CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Verifies that diagnostics will be reported for all invalid stackalloc array initializer definitions. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestStackAllocArrayInitializersInvalidAsync() + { + var testCode = @" +public class TestClass +{ + public unsafe void TestMethod() + { + var invalidArray1 = stackalloc int[] + { 0, 1 }; + + var invalidArray2 = stackalloc int[] + { 0, 1 + }; + + var invalidArray3 = stackalloc int[] + { + 0, 1 }; + } +}"; + + var fixedTestCode = @" +public class TestClass +{ + public unsafe void TestMethod() + { + var invalidArray1 = stackalloc int[] + { + 0, 1 + }; + + var invalidArray2 = stackalloc int[] + { + 0, 1 + }; + + var invalidArray3 = stackalloc int[] + { + 0, 1 + }; + } +}"; + + DiagnosticResult[] expectedDiagnostics = + { + Diagnostic().WithLocation(7, 13), + Diagnostic().WithLocation(7, 20), + Diagnostic().WithLocation(10, 13), + Diagnostic().WithLocation(15, 22), + }; + + await VerifyCSharpFixAsync(LanguageVersion.CSharp7_3, testCode, expectedDiagnostics, fixedTestCode, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1500BracesForMultiLineStatementsMustNotShareLine.cs b/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1500BracesForMultiLineStatementsMustNotShareLine.cs index 428eb111d..4d42c29de 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1500BracesForMultiLineStatementsMustNotShareLine.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1500BracesForMultiLineStatementsMustNotShareLine.cs @@ -10,6 +10,7 @@ namespace StyleCop.Analyzers.LayoutRules using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using StyleCop.Analyzers.Helpers; + using StyleCop.Analyzers.Lightup; /// /// The opening or closing brace within a C# statement, element, or expression is not placed on its own line. @@ -172,6 +173,22 @@ private static void CheckBraces(SyntaxNodeAnalysisContext context, SyntaxToken o break; + case SyntaxKind.StackAllocArrayCreationExpression: + if (((StackAllocArrayCreationExpressionSyntax)context.Node.Parent).StackAllocKeyword.GetLine() == openBraceTokenLine) + { + return; + } + + break; + + case SyntaxKindEx.ImplicitStackAllocArrayCreationExpression: + if (((ImplicitStackAllocArrayCreationExpressionSyntaxWrapper)context.Node.Parent).StackAllocKeyword.GetLine() == openBraceTokenLine) + { + return; + } + + break; + case SyntaxKind.ArrayInitializerExpression: if (!InitializerExpressionSharesLine((InitializerExpressionSyntax)context.Node)) {