Skip to content

Commit 15a4962

Browse files
committed
Support empty lines in header comments
Fixes #2657
1 parent 822c56b commit 15a4962

2 files changed

Lines changed: 60 additions & 4 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/FileHeaderCodeFixProvider.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace StyleCop.Analyzers.DocumentationRules
77
using System.Collections.Generic;
88
using System.Collections.Immutable;
99
using System.Composition;
10+
using System.Linq;
1011
using System.Text;
1112
using System.Threading;
1213
using System.Threading.Tasks;
@@ -139,8 +140,7 @@ private static SyntaxNode ReplaceWellFormedMultiLineCommentHeader(Document docum
139140
triviaStringParts[0] = commentIndentation + interlinePadding + " " + triviaStringParts[0];
140141
StringBuilder sb = StringBuilderPool.Allocate();
141142
string fileName = Path.GetFileName(document.FilePath);
142-
var copyrightText = commentIndentation + interlinePadding + " " +
143-
GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
143+
var copyrightText = GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
144144
var newHeader = WrapInXmlComment(commentIndentation + interlinePadding, copyrightText, document.Name, settings, newLineText);
145145

146146
sb.Append(commentIndentation);
@@ -385,7 +385,7 @@ private static SyntaxNode AddHeader(Document document, SyntaxNode root, string n
385385

386386
private static SyntaxTriviaList CreateNewHeader(string prefixWithLeadingSpaces, string fileName, StyleCopSettings settings, string newLineText)
387387
{
388-
var copyrightText = prefixWithLeadingSpaces + " " + GetCopyrightText(prefixWithLeadingSpaces, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
388+
var copyrightText = GetCopyrightText(prefixWithLeadingSpaces, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
389389
var newHeader = settings.DocumentationRules.XmlHeader
390390
? WrapInXmlComment(prefixWithLeadingSpaces, copyrightText, fileName, settings, newLineText)
391391
: copyrightText;
@@ -417,7 +417,18 @@ private static string WrapInXmlComment(string prefixWithLeadingSpaces, string co
417417
private static string GetCopyrightText(string prefixWithLeadingSpaces, string copyrightText, string newLineText)
418418
{
419419
copyrightText = copyrightText.Replace("\r\n", "\n");
420-
return string.Join(newLineText + prefixWithLeadingSpaces + " ", copyrightText.Split('\n')).Replace(prefixWithLeadingSpaces + " " + newLineText, prefixWithLeadingSpaces + newLineText);
420+
var lines = copyrightText.Split('\n');
421+
return string.Join(newLineText, lines.Select(line =>
422+
{
423+
if (string.IsNullOrEmpty(line))
424+
{
425+
return prefixWithLeadingSpaces;
426+
}
427+
else
428+
{
429+
return prefixWithLeadingSpaces + " " + line;
430+
}
431+
}));
421432
}
422433

423434
private static SyntaxTriviaList RemoveHeaderDecorationLines(SyntaxTriviaList trivia, StyleCopSettings settings)

StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/NoXmlFileHeaderUnitTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ public class NoXmlFileHeaderUnitTests : CodeFixVerifier
3131
}
3232
}
3333
}
34+
";
35+
36+
private const string TestSettingsWithEmptyLines = @"
37+
{
38+
""settings"": {
39+
""documentationRules"": {
40+
""companyName"": ""FooCorp"",
41+
""copyrightText"": ""\nCopyright (c) {companyName}. All rights reserved.\n\nLicensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.\n"",
42+
""variables"": {
43+
""licenseName"": ""???"",
44+
""licenseFile"": ""LICENSE""
45+
},
46+
""xmlHeader"": false
47+
}
48+
}
49+
}
3450
";
3551

3652
private string currentTestSettings = TestSettings;
@@ -368,6 +384,35 @@ namespace Bar
368384
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
369385
}
370386

387+
[Fact]
388+
[WorkItem(2657, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2657")]
389+
public async Task TestHeaderMissingRequiredNewLinesAsync()
390+
{
391+
var testCode = @"// Copyright (c) FooCorp. All rights reserved.
392+
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
393+
394+
namespace Bar
395+
{
396+
}
397+
";
398+
var fixedCode = @"//
399+
// Copyright (c) FooCorp. All rights reserved.
400+
//
401+
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
402+
//
403+
404+
namespace Bar
405+
{
406+
}
407+
";
408+
409+
this.currentTestSettings = TestSettingsWithEmptyLines;
410+
var expected = this.CSharpDiagnostic(FileHeaderAnalyzers.SA1636Descriptor).WithLocation(1, 1);
411+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
412+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
413+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
414+
}
415+
371416
/// <inheritdoc/>
372417
protected override string GetSettings()
373418
{

0 commit comments

Comments
 (0)