Skip to content

Commit

Permalink
Fix file header insertion before a blank line
Browse files Browse the repository at this point in the history
Fixes #2415
  • Loading branch information
sharwell committed Jun 17, 2017
1 parent 9166e4f commit 87f2fc4
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ private static SyntaxNode ReplaceHeader(Document document, SyntaxNode root, Styl
bool onBlankLine = false;
bool inCopyright = isMalformedHeader;
int? copyrightTriviaIndex = null;
var removalList = new System.Collections.Generic.List<int>();
var removalList = new List<int>();
var leadingSpaces = string.Empty;
string possibleLeadingSpaces = string.Empty;

Expand Down Expand Up @@ -351,7 +351,34 @@ private static SyntaxNode AddHeader(Document document, SyntaxNode root, string n
string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);
var newLineTrivia = SyntaxFactory.EndOfLine(newLineText);
var newTrivia = CreateNewHeader("//", name, settings, newLineText).Add(newLineTrivia).Add(newLineTrivia);
newTrivia = newTrivia.AddRange(root.GetLeadingTrivia());

// Skip blank lines already at the beginning of the document, since we add our own
SyntaxTriviaList leadingTrivia = root.GetLeadingTrivia();
int skipCount = 0;
for (int i = 0; i < leadingTrivia.Count; i++)
{
bool done = false;
switch (leadingTrivia[i].Kind())
{
case SyntaxKind.WhitespaceTrivia:
break;

case SyntaxKind.EndOfLineTrivia:
skipCount = i + 1;
break;

default:
done = true;
break;
}

if (done)
{
break;
}
}

newTrivia = newTrivia.AddRange(leadingTrivia.RemoveRange(0, skipCount));

return root.WithLeadingTrivia(newTrivia);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,101 @@ public virtual async Task TestNoFileHeaderAsync()
var fixedCode = @"// Copyright (c) FooCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Foo
{
}
";

var expectedDiagnostic = this.CSharpDiagnostic(FileHeaderAnalyzers.SA1633DescriptorMissing).WithLocation(1, 1);
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostic, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
}

/// <summary>
/// Verifies that the analyzer will report <see cref="FileHeaderAnalyzers.SA1633DescriptorMissing"/> for
/// projects not using XML headers when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
[WorkItem(2415, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2415")]
public virtual async Task TestNoFileHeaderWithUsingDirectiveAsync()
{
var testCode = @"using System;
namespace Foo
{
}
";
var fixedCode = @"// Copyright (c) FooCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace Foo
{
}
";

var expectedDiagnostic = this.CSharpDiagnostic(FileHeaderAnalyzers.SA1633DescriptorMissing).WithLocation(1, 1);
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostic, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
}

/// <summary>
/// Verifies that the analyzer will report <see cref="FileHeaderAnalyzers.SA1633DescriptorMissing"/> for
/// projects not using XML headers when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
[WorkItem(2415, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2415")]
public virtual async Task TestNoFileHeaderWithBlankLineAndUsingDirectiveAsync()
{
var testCode = @"
using System;
namespace Foo
{
}
";
var fixedCode = @"// Copyright (c) FooCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace Foo
{
}
";

var expectedDiagnostic = this.CSharpDiagnostic(FileHeaderAnalyzers.SA1633DescriptorMissing).WithLocation(1, 1);
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostic, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
}

/// <summary>
/// Verifies that the analyzer will report <see cref="FileHeaderAnalyzers.SA1633DescriptorMissing"/> for
/// projects not using XML headers when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
[WorkItem(2415, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2415")]
public virtual async Task TestNoFileHeaderWithWhitespaceLineAsync()
{
var testCode = " " + @"
using System;
namespace Foo
{
}
";
var fixedCode = @"// Copyright (c) FooCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace Foo
{
}
Expand Down

0 comments on commit 87f2fc4

Please sign in to comment.