Setting individual StyleCop rules as build errors - c#

According to this blog, you can set all/certain projects to treat StyleCop violations as build errors instead of warnings:
By default, StyleCop violations will show up as build warnings. To turn StyleCop violations into build errors, the flag StyleCopTreatErrorsAsWarnings must be set to false. This flag can be set as an environment variable on the machine, or within the build environment command window. Setting the flag this way will cause StyleCop violations to appear as build errors automatically for all projects where StyleCop build integration is enabled.
Alternately, this flag can be set within the project file for a particular project. Open the .csproj file for your project again, and find the first PropertyGroup section within the file. Add a new tag to set the StyleCopTreatErrorsAsWarnings flag to false.
This doc shows where you can turn on/off individual rules, but it doesn't seem to support setting the severity, only completely turning them on/off.
Is it not possible to have more granular control of which rules result in errors vs. warnings?

It's not supposed to, but if you really want it.. why not?
Here is an idea, not a complete solution.
There are two useful lines in StyleCop.Targets file. First one imports StyleCop task:
<UsingTask AssemblyFile=".\StyleCop.dll" TaskName="StyleCopTask"/>
and this one calls it:
<StyleCopTask
ProjectFullPath="$(MSBuildProjectDirectory)"
SourceFiles="#(StyleCopFiles)"
AdditionalAddinPaths="#(StyleCopAdditionalAddinPaths)"
ForceFullAnalysis="$(StyleCopForceFullAnalysis)"
DefineConstants="$(DefineConstants)"
TreatErrorsAsWarnings="$(StyleCopTreatErrorsAsWarnings)"
CacheResults="$(StyleCopCacheResults)"
OverrideSettingsFile="$(StyleCopOverrideSettingsFile)"
OutputFile="$(StyleCopOutputFile)"
MaxViolationCount="$(StyleCopMaxViolationCount)"
/>
So you basically need to call it twice, first one specifying TreatErrorsAsWarnings as false (so that it fails if there are any warnings), and second one with true (resulting in just warning).
Also, you will need to use two separate settings file - first one with stylecop 'errors', second with 'warnings'.

Related

How to disable compiler warnings in only generated code without editing file(s)

I have some generated code that has a bunch of compiler warnings. I want to disable them in the generated file, but keep those warnings in the rest of the project so they can be fixed. I'm using Visual Studio 2019 Community Edition, with the generated files coming from Entity Framework and other NuGet packages.
I want to do this without changing the files, so I won't get the warnings back if they get regenerated. I also don't want to disable the warnings project wide, since they are normally useful warnings. I also don't want to edit the NuGet packages, since that would either require not upgrading them as newer releases are available or possibly having to make changes to the new version.
I've already done plenty of reading, but evidently posting the links is "too much", so I've removed them. Look in the edit history if you want to see them.
The file in question is a Reference.cs for a Connected Service. It has the namespace of Proxy.ProvisioningService and this one file contains a couple of dozen classes. I also have a couple of Entity Framework migration files that have the same problem in a completely different solution.
I have a GlobalSuppressions.cs file that I'd like to add the CS1591 (specifically) to, but my current entry isn't working. Other entries work for other warnings and I've tried variations of the below code to work, including trying to match the format of the other entries, but nothing is working so far. I've changed the "Build" from "Compile", removed the MessageId, changed Scope to be "module", "assembly", and "namespaceanddescendants", and I've tried a couple different ways to set the Target.
[assembly: SuppressMessage("Build", "CS1591:Missing XML comment for publicly visible type or member", Justification = "Generated code", MessageId = "CS1591", Scope = "namespaceanddescendants", Target = "Proxy.ProvisioningService")]
In one of the off-site links, it suggests that I right-click the error, go to Suppress -> In Suppression File, but that's not a listed option. Is that a clue that I can't do it in the GlobalSuppressions.cs file?
I've tried to have Visual Studio 2019 Community Edition automatically suppress the warning by the menu item Analyze -> Build And Suppress Active Issues -> For Project, but that just added a bunch of #pragma directives to the file, which would have to be replaced if the file was regenerated, which I want to avoid.
One of the linked answers suggested writing a script to add the #pragma directives on compile, but that script seems like a hack to me. I'd rather just not edit the generated code at all.
I also don't want to put it in the Project -> Properties -> Build -> Suppress Warnings section, since I want the hand written code to still throw these warnings.
Another SE/SO answer suggests using the GeneratedCodeAttribute attribute to prevent warning from generated files. Unfortunately, my file already has this and it's still throwing the warnings.
Another suggestion was to turn off warnings for these generated files:
To suppress warnings for generated code in a project
Right-click the project in Solution Explorer and then click Properties.
Choose the Code Analysis tab.
Select the Suppress results from generated code check box.
Unfortunately, this option is already selected and not suppressing the CS1591 warning.
So my actual question is:
How can I suppress warnings, specifically CS1591, from generated code files without editing them and without suppressing the warning throughout the whole project?
You said that you consider using a script to update the files to add #pragma a hack, but I can't think of another solution.
I think that you can do this easily with a MSBuild Task by adding something like this to your .csproj file:
<Target Name="DisableWarnings" BeforeTargets="CoreCompile">
<ItemGroup>
<AutoGeneratedFiles Include="**/*.Designer.cs" />
</ItemGroup>
<WriteLinesToFile File="%(AutoGeneratedFiles.FullPath)"
Condition="!$([System.IO.File]::ReadAllText(%(AutoGeneratedFiles.FullPath)).StartsWith("#pragma warning"))"
Lines="$([System.String]::Concat("#pragma warning disable 1591",$([System.IO.File]::ReadAllText(%(AutoGeneratedFiles.FullPath))),"#pragma warning restore 1591"))"
Overwrite="true"
Encoding="Unicode" />
</Target>
The SuppressMessage attribute works only for code analysis warnings. Its summary goes:
Suppresses reporting of a specific code analysis rule violation, allowing multiple suppressions on a single code artifact. Does not apply to compiler diagnostics.
If there is a file name pattern identifying the generated code, compiler warnings can be suppressed in the generated code using EditorConfig. For example, this is how I disabled the warnings for using obsolete code elements in my generated code -- I still need to suppress the warnings in manually written code using #pragma.
[*.generated.cs]
dotnet_diagnostic.CS0612.severity = none
dotnet_diagnostic.CS0618.severity = none
For a WCF connected service, the simplest solution is probably to not have the warning in the first place.
Since the CS1591 warning is about public types, you could use the dotnet-svcutil tool to generate your Reference.cs file and pass the --internal option so that the generated types are internal instead of public, thus getting rid of CS1591 altogether.
For other tools that generate code, look for a similar option to generate internal types instead of public types. For example, you would use the --assemblyVisible option with the xscgen tool.

Visual Studio nullability ref errors show as warnings if defined in Directory.Build.props

This might just be a temporary VS bug, but I wanted to see if anyone had any fixes or if there was perhaps a VS setting I was missing.
If I define nullability errors:
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
And I do so within a .csproj, it works out as one would expect:
However, if the properties are defined in a Directory.Build.props file, which applies to a solution en-masse, they do not show as errors anymore:
It still blocks compilation, and you can still see the error in the raw text output.. but the red squiggle doesn't show (just green) and more importantly, the Error List pane is empty.
Does anyone know why this is, or how to fix it? I would like to have nullability errors defined en-masse via the Directory.Build.props, but it's unusable in its current state.
Actually, automatic msbuild import function has two ways: Directory.Build.props and Directory.Build.targets.
In your side, you should use Directory.Build.targets rather than Directory.Build.props.
As the document said, Directory.Build.props is imported at the top of the csproj file. So it should be used to define global msbuild properties that used on the global environment. And the properties defined on it can be overwritten by the csproj file.
Your situation is that the WarningsAsErrors is overwritten by the system default value none from csproj file. Although the value is not shown on the csproj file, it actually shows as none by default. When you create a new project without any changes, it always shows as a warning.
Solution
Therefore, you should rename the file as Directory.Build.targets and it always is used to overwrite any operation properties like WarningsAsErrors.
Mostly like this similar issue.

How do I disable suppressing a warning for one solution in a TFS build

I'm using TFS 2010 and have a TFS build setup to build our software. Everything is working just fine.
But, we are getting the following warning:
CSC: Assembly generation -- Referenced assembly 'mscorlib.dll' targets a different processor
This is because some of our code is marked as x86 only, and it is being built on an x64 platform. We cannot change the target platform because of third party software we link to.
Also we are targeting the 2.0 framework, which also cannot be changed at this point.
So, I want to simply suppress this error. Seems straight forward enough.
I simply edited the Build template, and added /p:NoWarn=1607. That works.
BUT!
We have ONE solution which is written in VB.net, instead of C#. This causes that one solution to fail with the following error:
vbc: warning number '1607' for the option nowarn is either not configurable or not valid
How do I disable suppressing this warning on that one solution in my TFS build?
I tried to use a <customPropertiesForBuild> tag in my TFSBuild.proj file but I'm probably not using it correctly.
I know I could simply add this to my project files, but we have 37 solutions, each with multiple project files, so I really don't want to do that.
I don't think you can control that suppression from TFS since it is MSbuild complaining during build (and TFS simply calls MSBuild and collects the results).
There's a specific property that tells msbuild to ignore this kind of warning. Simply add the following line to your top Propertygroup in the project file for those projects generating the warning:
<PropertyGroup>
...
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
You should be able to use Properties metadata on the VB solution's SolutionToBuild item to set NoWarn to an empty value just for that solution:
<SolutionToBuild Include="$(BuildProjectFolderPath)/../../MyVbSolution.sln">
<Targets></Targets>
<Properties>NoWarn=;</Properties>
</SolutionToBuild>
Try that and see if your VB solution will compile without errors.
You can provide a NoWarn Property to MSbuild in TFS Build. One idea also is to edit the build definition, in the "Process" Tab, explore the Advanced=>MSBuild Arguments, and then you supply this "/p:NoWarn=1607" without the qoutes. When you also queue a build, in Parameters Tab=>Advanced=>MSBuild Arguments, enter/p:NoWarn=1607.

How to undefine the symbol CONTRACTS_FULL?

Visual Studio defines the CONTRACTS_FULL symbol automatically if
you enable contract checking in the Code Contracts tab of the Project
Properties page.
- C# 5.0 In a Nutshell (page 518)
I'd like to disable/undefine the symbol but it doesn't appear in the Conditional compilation symbols field of the Build tab in the project settings.
(I'm not interested in disabling code-contracts completely! by that I simply mean that setting the contract checking to None is not a solution).
If it matters, the reason I want to do this is because in my release builds I only want to throw on Contract.Requires<TException>, and I don't want to throw ContractException at all.
One "solution" I found is to put #undef CONTRACTS_FULL at the first line of each file, it fixed it but actually doing that would be horrible.
(BTW up until now VS didn't define CONTRACTS_FULL and I had to define it myself, but I guess some setting changed accidentally)
You cannot run the contract tools and undefine the CONTRACTS_FULL symbol. The tools depend on that being defined. Nothing will work if you try to force this. That is why we define the symbol automatically inside the msbuild scripts.
Users of the Code Contract tools should never manually try to define or undefine the CONTRACTS_FULL symbol as it is a tool controlled variable.
I've read that book, and there WAS a contract level that only used Contract.Requires. It was the option before none in there, but it's somewhere in that section in the book, definitely.
However, I can't help you with globally undefing CONTRACTS_FULL. Sorry. I think though that in that contract checking level it's automatically undef'd.
EDIT: Yeah, you need to put it at level one (ReleaseRequired).

Can I set a C# preprocessor directive from a central file?

I need to add some logging to my app, and it needs to be in release mode, and I need to make sure that the logging code isn't running in production. Therefore I'd like to use a #define and #if to make sure the log statements are removed when I move to production.
Trouble is, I need the logging in multiple files, and it's a pain to put a #define at the top of every file. Is there a way to have a centralized #define? That way I can remove the single #define rather than a #define from all files(which means I'll almost assuredly forget one).
On the command line, use the /define switch. In Visual Studio, choose the "Build" tab from the properties page for the project and fill in the "Conditional Compilation Symbols" section.
Consider also instead of using conditional compilation, to instead make your logging methods conditional methods. That's a more pleasant-looking alternative. That's how Debug.Assert works; it is a conditional method, so if the debug preprocessor symbol is not defined, the compiler simply removes all calls to the method before code generation.
See also my article on the subject:
http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/
Are you using Visual Studio? In the project Properties page, on the "Build" tab, there's a "Conditional compilation symbols" text box.
Yes, this is typically done in your build file, or the script you use which creates your build. You specify it as command-line arguments to MSBuild.
To add to Dave's answer, global conditional compilation symbols can also be specified in Visual.
Right-click on your project and go to Properties
Go to the Build tab
You can specify the symbols that you like (DEBUG is already turned on by default for Debug configurations, so this might actually give you what you want already) for the given configuration, or select "All Configurations" at the top to specify certain symbols for all configurations.
Call the logging everywhere you want.
Define the logging api entry methods with
[Conditional ("DEBUG")]
public void WriteDebugMessage(...)
Build your program in debug mode (which, by default, defines 'DEBUG' in VS). These calls will be part of your assembly.
Build your program in release mode (or - remove the DEBUG symbol from the build definition). These calls are now meaningless no-ops and won't run.
Seems like what you want?

Categories