#nullable disable - only for specific namespace? - c#

In my asp.net core project I turned on nullable warnings with:
<Nullable>enable</Nullable>
Everything works just fine. But after adding scaffolded items from Identity (like Login.cshtml, Register.cshtml) many of these warning showed up. I don't want to touch that (somebody else's) code (but I need it for some reason).
I can use #nullable disable in every file, but I was thinking that maybe better solution exists? Restricting #nullable disable only to specific namespace??

While you cannot disable nullable checks on a per-namespace basis, you can customize the severity of issues which those checks surface, via your .editorconfig file.
Many projects make their folder structure mirror their namespaces. If this is the case for your project, you can either put an .editorconfig file into the folder at the root of your target namespace, or you can create a file matching pattern in another .editorconfig file further up the folder tree to target items in that folder. For example:
[**/Models/**.cs]
# API models will be serialized and deserialized, so they can have default constructors,
# but we assume the required values aren't null anyway.
dotnet_diagnostic.CS8618.severity = none

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.

Setting individual StyleCop rules as build errors

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'.

CS0436: Type conflicts with the imported type

I am including an instance of the same source files in multiple assemblies using the Add As Link option. I specifically need to include an instance of the same source within these assemblies because it is responsible for licence validation which must occur internally to the assembly. Performing licence calls across module boundaries could introduce a security risk.
Some of the projects in my solution that include the code depend on other modules that also include it, resulting in warning CS0436:
"The type [type] in [licence.cs full path] conflicts with the imported
type [LicenceClass] in [dependency project also including licence.cs].
Using the type defined in [licence.cs full path]".
I have tried declaring a class alias, but the definitions internal to licence.cs cause the same warning. In the alias, there must be a reference to the duplicated class name which causes the same warning.
I know it is bad practice to duplicate source between assemblies, but it is intentional in this case. I would rather keep a central instance that each assembly links to rather than a dedicated instance with renamed classes to avoid the warnings.
The workaround I have is simply to ignore the warning using a #pragma. Is there a more elegant solution?
It is worth noting that another way to get such warnings is by simply setting a project in visual studio to reference itself: References -> Solution -> etc etc (how I figured this gem out is left as an exercise to the reader ...)
Visual Studio will happily comply, only to throw a wall of warnings of the type described by OP during build, which is to be expected (upon reflection) since every single class etc is getting defined twice.
The only time conflicts occur is when two dependent classes include the same class. There are two workarounds:
Disable the warning in classes that cause CS0436:
#pragma warning disable 0436
Have a separate instance of the class, uniquely named in each client project (undesirable from a maintenance point of view).
EDIT: There is also a solution: do what Mark suggests below, and mark duplicate classes internal.
I had a web application I converted from ASP.NET 3.5 to 4.5 when I moved to VS2015. I started seeing this as a warning, but the solution would still compile. There were no circular references, and cleaning the solution and deleting the bin and obj folders didn't help.
It turns out that VS2015 wasn't happy with some of my classes in the App_Code folder. The classes in here had the same namespace as the rest of the web pages in the parent folder. Once I moved these classes out of the App_Code folder and to the top level of the web application, the warnings went away.
In .NET Core you can also disable the warning in project.json:
{
"buildOptions":
{
"nowarn":
[
"CS0436"
]
}
}
I had this error but not with 2 different classes!
Each new class where in conflict with itself, so obviously I had that CS0436 Error.
After some struggling found out that it was about Mirror Asset that I was using in my multiplayer Unity project. Mirror somehow was including every new class that I make (and inherit from NetworkBehavior).
My external editor was VSCode (visual studio code, solution might also apply to visual studio).
Solution
in
Edit / Preferences / External tools / "Generate .csproj files for:"
I started testing different settings, and this worked for me:
(Not sure if the exact settings work for all, but not having the right files in project, leads to this error. like my case.)
Click Regenerate project files and restart Unity and VSCode after applying these settings (or the setting that suits your project).
I've met such a case when removed some source files temporarily and restored them back later. It happens that IDE (Rider in my case) tries to restore the classes so when they were missing it just added the reference to the resulting exe. Evidently, when I restored the files, they look as duplicate.
The reference IDE inserted looks like this and it's enough to just remove it to fix:
<Reference Include="AppName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>bin\x86\Debug\AppName.exe</HintPath>
</Reference>

How to override VS2010's automatic folder->namespace mapping in new cs files

Projects are often broken down into folders, and those folders are typically expected to map to code namespaces. However, in many of my core projects I have classes that I have merged into existing namespaces - for example I have an MVC reference library that adds additional types into System.Web.Mvc, or System.ComponentModel.DataAnnotations, for example.
In other projects, I might have a suite of interfaces and a suite of default implementations of those interfaces; so I might split the code files into two separate folders (e.g. 'Objects' and 'Interfaces') but I don't want to have Objects and Interfaces sub namespaces.
Equally, I often write extension methods for types in other libraries - e.g. System.String, which I merge into the System namespace so they are already 'there' as soon as you reference the assembly.
So given a project structure like this (in response to the first answer, this project is intended to produce a single assembly with all the namespaces; and could be a dll that might be signed):
Our.Core.Library
|->System
| |->StringExtensions.cs
|->System.Web.Mvc
| |->AnotherModelBinder.cs
|->OurCoreClass.cs
In the above, I want new files added to the root to be in the namespace Our.Core.Library, but I want new files added to the System and System.Web.Mvc folders to be in System and System.Web.Mvc respectively. But VS will give them a default namespace of Our.Core.Library.System.
It's a small gripe, but I'd like to be able to override the default namespace for a specific code folder so I can control it. Any ideas how to achieve this? I've tried an empty default namespace for the project, which might logically make it work for sub-folders, but obviously not for the root; however, the VS Properties page doesn't accept an empty namespace.
Ideally it would be a solution that I can easily replicate across our entire dev team to enable other developers to be able to add code files whilst adhering to the namespace structure set out at the architect/planning stage.
Every C# project settings has a Default namespace option in the application tab that you can change to any other value which will take effect when you add more files to the project. There is only one setting allowed per project
You can break your project into multiple projects and have the default be different for different projects
Basically the only way I'm going to be able to do this is to write my own extension to Visual Studio. It might even require it's own project or item wizard - if I can get anything working I'll post it up here in the future.

Categories