|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Testing;
using Roslyn.Test.Utilities;
using Xunit;
using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier<
Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderDiagnosticAnalyzer,
Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderCodeFixProvider>;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.FileHeaders;
public class FileHeaderTests
{
private const string TestSettings = """
[*.cs]
file_header_template = Copyright (c) SomeCorp. All rights reserved.\nLicensed under the ??? license. See LICENSE file in the project root for full license information.
""";
private const string TestSettingsWithEmptyLines = """
[*.cs]
file_header_template = \nCopyright (c) SomeCorp. All rights reserved.\n\nLicensed under the ??? license. See LICENSE file in the project root for full license information.\n
""";
/// <summary>
/// Verifies that the analyzer will not report a diagnostic when the file header is not configured.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Theory]
[InlineData("")]
[InlineData("file_header_template =")]
[InlineData("file_header_template = unset")]
public async Task TestFileHeaderNotConfiguredAsync(string fileHeaderTemplate)
{
var testCode = """
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
EditorConfig = $@"
[*]
{fileHeaderTemplate}
",
}.RunAsync();
}
/// <summary>
/// Verifies that the analyzer will report a diagnostic when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Theory]
[InlineData("\n")]
[InlineData("\r\n")]
[WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1414432")]
public async Task TestNoFileHeaderAsync(string lineEnding)
{
var testCode = """
[||]namespace N
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode.ReplaceLineEndings(lineEnding),
FixedCode = fixedCode.ReplaceLineEndings(lineEnding),
EditorConfig = TestSettings,
Options =
{
{ FormattingOptions2.NewLine, lineEnding },
},
}.RunAsync();
}
/// <summary>
/// Verifies that the analyzer will report a diagnostic when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestNoFileHeaderWithUsingDirectiveAsync()
{
var testCode = """
[||]using System;
namespace N
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that the analyzer will report a diagnostic when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestNoFileHeaderWithBlankLineAndUsingDirectiveAsync()
{
var testCode = """
[||]
using System;
namespace N
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that the analyzer will report a diagnostic when the file is completely missing a header.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestNoFileHeaderWithWhitespaceLineAsync()
{
var testCode = "[||] " + """
using System;
namespace N
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
using System;
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that the built-in variable <c>fileName</c> works as expected.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestFileNameBuiltInVariableAsync()
{
var editorConfig = """
[*.cs]
file_header_template = {fileName} Copyright (c) SomeCorp. All rights reserved.\nLicensed under the ??? license. See LICENSE file in the project root for full license information.
""";
var testCode = """
[||]namespace N
{
}
""";
var fixedCode = """
// Test0.cs Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace N
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = editorConfig,
}.RunAsync();
}
/// <summary>
/// Verifies that a valid file header built using single line comments will not produce a diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestValidFileHeaderWithSingleLineCommentsAsync()
{
var testCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that a valid file header built using multi-line comments will not produce a diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestValidFileHeaderWithMultiLineComments1Async()
{
var testCode = """
/* Copyright (c) SomeCorp. All rights reserved.
* Licensed under the ??? license. See LICENSE file in the project root for full license information.
*/
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that a valid file header built using multi-line comments will not produce a diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestValidFileHeaderWithMultiLineComments2Async()
{
var testCode = """
/* Copyright (c) SomeCorp. All rights reserved.
Licensed under the ??? license. See LICENSE file in the project root for full license information. */
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that a valid file header built using unterminated multi-line comments will not produce a diagnostic
/// message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestValidFileHeaderWithMultiLineComments3Async()
{
var testCode = """
/* Copyright (c) SomeCorp. All rights reserved.
Licensed under the ??? license. See LICENSE file in the project root for full license information.
""";
await new VerifyCS.Test
{
TestCode = testCode,
ExpectedDiagnostics =
{
// /0/Test0.cs(1,1): error CS1035: End-of-file found, '*/' expected
DiagnosticResult.CompilerError("CS1035").WithSpan(1, 1, 1, 1),
},
FixedCode = testCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that a file header without text / only whitespace will produce the expected diagnostic message.
/// </summary>
/// <param name="comment">The comment text.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Theory]
[InlineData("[|//|]")]
[InlineData("[|//|] ")]
public async Task TestInvalidFileHeaderWithoutTextAsync(string comment)
{
var testCode = $@"{comment}
namespace Bar
{{
}}";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestInvalidFileHeaderWithWrongTextAsync()
{
var testCode = """
[|//|] Copyright (c) OtherCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestInvalidFileHeaderWithWrongText2Async()
{
var testCode = """
[|/*|] Copyright (c) OtherCorp. All rights reserved.
* Licensed under the ??? license. See LICENSE file in the project root for full license information.
*/
namespace Bar
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
/* Copyright (c) OtherCorp. All rights reserved.
* Licensed under the ??? license. See LICENSE file in the project root for full license information.
*/
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
[Theory]
[InlineData("", "")]
[InlineData(" Header", "")]
[InlineData(" Header", " Header")]
public async Task TestValidFileHeaderInRegionAsync(string startLabel, string endLabel)
{
var testCode = $@"#region{startLabel}
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
#endregion{endLabel}
namespace Bar
{{
}}
";
await new VerifyCS.Test
{
TestCode = testCode,
EditorConfig = TestSettings,
}.RunAsync();
}
[Theory]
[InlineData("", "")]
[InlineData(" Header", "")]
[InlineData(" Header", " Header")]
public async Task TestInvalidFileHeaderWithWrongTextInRegionAsync(string startLabel, string endLabel)
{
var testCode = $@"#region{startLabel}
[|//|] Copyright (c) OtherCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
#endregion{endLabel}
namespace Bar
{{
}}
";
var fixedCode = $@"// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
#region{startLabel}
// Copyright (c) OtherCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
#endregion{endLabel}
namespace Bar
{{
}}
";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestInvalidFileHeaderWithWrongTextInUnterminatedMultiLineComment1Async()
{
var testCode = """
{|CS1035:|}[|/*|] Copyright (c) OtherCorp. All rights reserved.
* Licensed under the ??? license. See LICENSE file in the project root for full license information.
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
{|CS1035:|}/* Copyright (c) OtherCorp. All rights reserved.
* Licensed under the ??? license. See LICENSE file in the project root for full license information.
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestInvalidFileHeaderWithWrongTextInUnterminatedMultiLineComment2Async()
{
var testCode = """
{|CS1035:|}[|/*|]/
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
{|CS1035:|}/*/
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Theory]
[InlineData("")]
[InlineData(" ")]
public async Task TestInvalidFileHeaderWithWrongTextAfterBlankLineAsync(string firstLine)
{
var testCode = $@"{firstLine}
[|//|] Copyright (c) OtherCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{{
}}";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
/// <summary>
/// Verifies that an invalid file header built using single line comments will produce the expected diagnostic message.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Fact]
public async Task TestInvalidFileHeaderWithWrongTextFollowedByCommentAsync()
{
var testCode = """
[|//|] Copyright (c) OtherCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
//using System;
namespace Bar
{
}
""";
var fixedCode = """
// Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
//using System;
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettings,
}.RunAsync();
}
[Fact]
public async Task TestHeaderMissingRequiredNewLinesAsync()
{
var testCode = """
[|//|] Copyright (c) SomeCorp. All rights reserved.
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
namespace Bar
{
}
""";
var fixedCode = """
//
// Copyright (c) SomeCorp. All rights reserved.
//
// Licensed under the ??? license. See LICENSE file in the project root for full license information.
//
namespace Bar
{
}
""";
await new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode,
EditorConfig = TestSettingsWithEmptyLines,
}.RunAsync();
}
}
|