I have added the StyleCop.Analyzers NuGet package to my project (latest stable version, 1.1.118). This contains some analysis rules around ensuring that file headers are present and correct. My project also has the following stylecop.json file, with the Build Action property set to "C# analyzer additional file".
{
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"settings": {
"documentationRules": {
"companyName": "Me"
}
}
}
If I add the following class to the project, it raises a warning "SA1636: The file header copyright text should match the copyright text from the settings".
// <copyright file="MyClass.cs" company="Me">
// Copyright (c) Me. All rights reserved. Some extra text to intentionally cause SA1636.
// </copyright>
namespace StackOverflowSA1636
{
/// <summary>
/// A class that I wrote.
/// </summary>
public class MyClass
{
}
}
If I remove Some extra text to intentionally cause SA1636. from the file header then the warning goes away. All good so far.
But what if I want to use a class written by someone else, either as-is or with any changes I've made? I want to credit them correctly for their code. The following class raises warning SA1636 and also "SA1641: The file header company name should match the company name from the settings".
// <copyright file="SomeoneElsesClass.cs" company="Me, Someone Else">
// Copyright (c) Me, Someone Else. All rights reserved.
// </copyright>
namespace StackOverflowSA1636
{
/// <summary>
/// A class written by someone else which I've adapted for my needs.
/// </summary>
public class SomeoneElsesClass
{
}
}
Visual Studio 2019 helpfully suggests that I can suppress these warnings in a GlobalSuppressions.cs file with attributes like this:
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1636:File header copyright text should match",
Justification = "Someone else wrote the original version of this class",
Scope = "namespace",
Target = "~N:StackOverflowSA1636")]
[assembly: SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1641:File header company name text should match",
Justification = "Someone else wrote the original version of this class",
Scope = "namespace",
Target = "~N:StackOverflowSA1636")]
And this does suppress the warnings, but for the whole namespace, which isn't what I want. I want to suppress them just for the one class. I tried changing them to this:
[assembly: SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1636:File header copyright text should match",
Justification = "Someone else wrote the original version of this class",
Scope = "type",
Target = "~T:StackOverflowSA1636.SomeoneElsesClass")]
[assembly: SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1641:File header company name text should match",
Justification = "Someone else wrote the original version of this class",
Scope = "type",
Target = "~T:StackOverflowSA1636.SomeoneElsesClass")]
While I was making this edit, Visual Studio greyed out the attribute because the Scope and Target didn't resolve to anything, but when I'd finished editing, the attributes were no longer greyed out, which makes me think that I've specified the Scope and Target correctly. However, this doesn't result in the warnings being suppressed.
Visual Studio also suggests that I can suppress SA1636 like this:
#pragma warning disable SA1636 // File header copyright text should match
// <copyright file="SomeoneElsesClass.cs" company="Me, Someone Else">
// Copyright (c) Me, Someone Else. All rights reserved.
// </copyright>
namespace StackOverflowSA1636
#pragma warning restore SA1636 // File header copyright text should match
{
/// <summary>
/// A class written by someone else which I've adapted for my needs.
/// </summary>
public class SomeoneElsesClass
{
}
}
And this does indeed suppress the warnings, but raises three new warnings:
"SA1633: The file header is missing or not located at the top of the file" (because the first line of the file is a #pragma rather than the file header)
"SA1512: Single-line comments should not be followed by blank line" (presumably because the file header is no longer be recognised as part of the file header, because it's not at the top of the file, so it's being treated as a regular comment)
"SA1515: Single-line comment should be preceded by blank line" (same reason as SA1512)
There is a solution which doesn't involve suppressing anything, to simply keep the file header the way StyleCop wants it, and then follow it with a comment crediting the original author or containing any copyright / licensing statement from the original code. This feels misleading, because the file header is effectively claiming that I'm the sole author when I'm not, but is there any better way to both satisfy StyleCop and correctly credit the original author?
Is there anything I can do to the stylecop.json file to change how the file header is validated?
Have I stumbled across a bug in StyleCop.Analyzers?
Update 9th Jan
Following some further thought, I suspect the reason I was unable to suppress the warnings using SuppressMessage is because the warnings are raised against the file rather than the class, and the Target I specified points to the class rather than the file.
Experimenting a bit with different values of the Target parameter seems to show that Visual Studio only greys out the attribute if the Target points to something that doesn't exist, but not when there's no such warning at the target to suppress. I suspect it may not be possible to target a file rather than a class, however I've had no joy finding any guidance on how to construct the Target.
This GitHub issue seems to cover my use case so I haven't created a new one: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2733