diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1500CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1500CodeFixProvider.cs index 2c5e1775e..b5a02ece0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1500CodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1500CodeFixProvider.cs @@ -75,7 +75,6 @@ private static Dictionary GenerateBraceFixes(Document var indentationSteps = DetermineIndentationSteps(indentationSettings, braceToken); var previousToken = braceToken.GetPreviousToken(); - var nextToken = braceToken.GetNextToken(); if (IsAccessorWithSingleLineBlock(previousToken, braceToken)) { @@ -106,9 +105,13 @@ private static Dictionary GenerateBraceFixes(Document braceReplacementToken = braceReplacementToken.WithLeadingTrivia(IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps)); } - // Check if we need to apply a fix after the brace - // if a closing brace is followed by a semi-colon or closing paren, no fix is needed. - if ((LocationHelpers.GetLineSpan(nextToken).StartLinePosition.Line == braceLine) && + // Check if we need to apply a fix after the brace. No fix is needed when: + // - The closing brace is followed by a semi-colon or closing paren + // - The closing brace is the last token in the file + var nextToken = braceToken.GetNextToken(); + var nextTokenLine = nextToken.IsKind(SyntaxKind.None) ? -1 : LocationHelpers.GetLineSpan(nextToken).StartLinePosition.Line; + + if ((nextTokenLine == braceLine) && (!braceToken.IsKind(SyntaxKind.CloseBraceToken) || !IsValidFollowingToken(nextToken))) { var sharedTrivia = nextToken.LeadingTrivia.WithoutTrailingWhitespace(); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/LayoutRules/SA1500/SA1500UnitTests.Namespaces.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/LayoutRules/SA1500/SA1500UnitTests.Namespaces.cs index d6bb8236d..691d9ea4c 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/LayoutRules/SA1500/SA1500UnitTests.Namespaces.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/LayoutRules/SA1500/SA1500UnitTests.Namespaces.cs @@ -129,5 +129,33 @@ namespace InvalidNamespace6 await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false); } + + /// + /// Verifies that an invalid namespace at the end of the source file will be handled correctly. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestNamespaceInvalidAtEndOfFileAsync() + { + var testCode = @" +namespace TestNamespace +{ + using System; }"; + + var fixedTestCode = @" +namespace TestNamespace +{ + using System; +}"; + + DiagnosticResult[] expectedDiagnostics = + { + this.CSharpDiagnostic().WithLocation(4, 17), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false); + } } }