How to enable compiler warnings for only a region? - c#

I enabled XML documentation generation for my project.
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
This generates a lot of warnings for my project because I don't compulsively add or update the XML doc comments for each and every type or member in my project. I turned the warnings back off with another tactically placed MSBuild instruction.
<PropertyGroup>
<NoWarn>$(NoWarn);1591</NoWarn> <!-- CS1591: Missing XML comment for publicly visible type or member -->
<NoWarn>$(NoWarn);1573</NoWarn> <!-- CS1573: Parameter '' has no matching param tag in the XML comment -->
</PropertyGroup>
Now the question becomes, how do I restore the warnings for the files where I do want to have clean documentation or a warning?
What I tried, didn't work.
#pragma warning restore CS1591,CS1573
public class Undocumented
{
public void AlsoUndocumented(bool undocumented = true) { }
}

Related

CA1062 doesn't trigger in vs2019 net5

I'm hoping to see CA1062, Validate Argument of public methods. But I'm not. It seems Code analysis is running because I see CA1822 for some items.
Here's an example of code I'm hoping would trigger CA1062.
public class FooController : BaseController<IFooProxy>
{
[HttpPost]
[Route("bar")]
public async Task<bool> Bar(string baz)
{
bool hasXyz = baz.Contains("xyz");
Console.WriteLine(hasXyz);
This is the csproj settings:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>preview</AnalysisLevel>
<AnalysisMode>All</AnalysisMode>
</PropertyGroup>
It's actually just a desperate attempt to turn everything on... I find myself missing the previous method, with a property page in the project to select rule set.
StyleCop is long gone, if the above doesn't work somehow, is there any open source way to run the rules?
If you want to enable all rules in .net 5, you should use:
<AnalysisLevel>5.0</AnalysisLevel>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
BTW in .net 6, it's:
<AnalysisMode>All</AnalysisMode>
https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysismode

EditorConfig control File-scoped namespace declaration

I'm using C# 10 new feature File-scoped namespace declaration.
I have old code like this
namespace SampleCode
{
public class MyClass
{
}
}
I'm moving this code to
namespace SampleCode;
public class MyClass
{
}
But I have a bunch of warnings : IDE0160: Convert to block scoped namespace
How do I make sure people will have warnings only with old syntax ?
To control the code style in editorconfig use this line :
To enforce this style
namespace SampleCode
{
public class MyClass
{
}
}
Add this line in .editorconfig
# IDE0160: Convert to block-scoped namespace
csharp_style_namespace_declarations = block_scoped:warning
To enforce this style
namespace SampleCode;
public class MyClass
{
}
Add this line in .editorconfig
# IDE0160: Convert to file-scoped namespace
csharp_style_namespace_declarations = file_scoped:warning
Update 2022-01-27 (all scenarios setup)
JetBrains Rider does support the dotnet_diagnostic.IDE* syntax starting from version 2021.3.2.This simplifies the setup for all possible scenarios into this:
EditorConfig
csharp_style_namespace_declarations = file_scoped
dotnet_diagnostic.IDE0161.severity = error
CSProj
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
This will cover all the scenarios. Original answer below. Still worth to read it.
There are several different settings which you should control based on your desired state, used IDEs and workflow.
They are described in this article which I strongly recommend to read before you start building .editorconfig for your project.
Here is a summary for File-scoped, Block-scoped usings, respectively.
EditorConfig/CSproj setup for File-scoped usings
Visual Studio (error on violation)
EditorConfig
csharp_style_namespace_declarations = file_scoped
dotnet_diagnostic.IDE0161.severity = error
Note
Syntax option = rule:severity will be deprecated, sooner or later.
JetBrains Rider (error on violation)
EditorConfig
csharp_style_namespace_declarations = file_scoped:error
Note
Rider doesn't support dotnet_diagnostic.IDE* syntax.
CLI build e.g., CI/CD pipeline
EditorConfig
csharp_style_namespace_declarations = file_scoped
dotnet_diagnostic.IDE0161.severity = error
CSProj
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
Recommended setup
EditorConfig
csharp_style_namespace_declarations = file_scoped:error
dotnet_diagnostic.IDE0161.severity = error
CSProj
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
Note
Is the current .NET EditorConfig syntax a mess? Definitely.
EditorConfig/CSproj setup for Block-scoped usings
Visual Studio (error on violation)
EditorConfig
csharp_style_namespace_declarations = block_scoped
dotnet_diagnostic.IDE0160.severity = error
Note
Syntax option = rule:severity will be deprecated, sooner or later.
JetBrains Rider (error on violation)
EditorConfig
csharp_style_namespace_declarations = block_scoped:error
Note
Rider doesn't support dotnet_diagnostic.IDE* syntax.
CLI build e.g., CI/CD pipeline
EditorConfig
csharp_style_namespace_declarations = block_scoped
dotnet_diagnostic.IDE0160.severity = error
CSProj
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
Recommended setup
EditorConfig
csharp_style_namespace_declarations = block_scoped:error
dotnet_diagnostic.IDE0160.severity = error
CSProj
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>

Why do I keep getting 'Predefined type IsExternalInit it not defined' even after upgrading to .net 5?

I removed my IsExternalInit definition, as we are now using .net 5.0:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>
However I still get this error
CS0518 Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported
In files like this
public sealed record TestDTO
{
public string SomePropert{ get; private init; } = default!; // error occurs here
}
I can see this is expected behaviour when targeting older frameworks, but shouldn't it work in my case? What am I doing wrong?
I think this is happening because one of the projects I reference has a dependency on some library using .net standard
To avoid adding IsExternalInit.cs to every project, I just added one to the solution root folder and also added a file called Directory.Build.Props with these contents
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)IsExternalInit.cs" Visible="false" />
</ItemGroup>
</Project>

Can I get project path or properties from Roslyn analyzer analysis context?

I'm implementing a Roslyn analyzer and I want to take different action based on how some properties are set within the csproj.
Currently I'm accomplishing this by setting "AdditionalFiles" node in a props file imported with the analyzer. This points to the .csproj and then I manually xml-parse the project file looking for the properties I care about.
<ItemGroup>
<AdditionalFiles Include="$(ProjectPath)" />
</ItemGroup>
private void AnalyzeAdditionalFiles(CompilationStartAnalysisContext context)
{
ICompilationStartAnalysisContextWrapper wrappedContext = this.compilationStartAnalysisContextWrapperFactory.Create(context);
if (wrappedContext.GetAdditionalTexts()
.Any(addtionalFile => <xml parse and validate csproj>))
{
context.RegisterSyntaxNodeAction(this.AnalyzeSyntaxNode, PossibleSyntaxKinds);
}
}
I've been told there may be a first-class supported way to do one or both of these actions without requiring what feels like hacky versions of:
Find the path to the csproj
Fetch properties from the csproj
Is this possible? Ideally I'd be looking for the moral equivalent of
AnalysisContext.Project.Properties["MyCustomProp"]
It's now possible to retrieve some project properties, starting with VS 16.7 preview3. It's based around the new csproj tag CompilerVisibleProperty.
You can find more information on the source generator cookbook, but here's a quick example.
First, in your csproj file, you declare your property, and allow the analyzer to access it:
<!-- declare the property you want to access in your analyzer -->
<PropertyGroup>
<MyCustomProp>Value from csproj</MyCustomProp>
</PropertyGroup>
<!-- explicitly allow the analyzer to access that variable -->
<ItemGroup>
<CompilerVisibleProperty Include="MyCustomProp" />
</ItemGroup>
You can then access this variable from any analyzer context, via the AnalyzerConfigOptionsProvider.GlobalOptions. For example:
private static void CompilationStart(CompilationStartAnalysisContext context)
{
// retrieve the global analyzer options
var globalOptions = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions;
// retrieve the actual build property
// -> wanted property name prefixed with "build_property."
string myCustomProp = null;
if (!globalOptions.TryGetValue("build_property.MyCustomProp", out myCustomProp))
myCustomProp = "Default";
}
Nuget packages used for this example:
Microsoft.CodeAnalysis.Analyzers 3.3.3
Microsoft.CodeAnalysis.CSharp 4.0.1

Change the application target framework when changing build configurations in Visual Studio

I have these build configurations:
These platform configurations:
And these compiler conditionals:
NET40
NET45
My solution is a huge API that consists in 20 solutions, some of those solutions consumes Async keywords and other beneffits that are available only from .NetFx 4.5.
That part of the code I have it in a conditional in this way:
#If NET45 then
Sub Async
...
End Sub
#Else
Sub
...
End Sub
#End If
Then, what I'm trying to do is clear, the .NetFx 4.5 build configurations should compile the block of the NET45 conditional, and the .NetFx 4.0 build configurations should compile the block of the #Else part.
The problem I found is that if I change the application target framework in the project settings, the change persist in all the other build configurations, and I would like to avoid that persistance.
So how I can do this?.
Note:
I marked this question with the C# tag because is a general Visual Studio environment question, but I will clarify that my solutions are written in Vb.Net, because I know there are some big differences between the C# project settings and also their compiler params so maybe a C# advanced answer could not help me.
My suggestion is to get rid of conditional statements in code by moving platform/target/etc sencitive code in partial files. Then I would go to project file and would make the icluded files sensitive on particular condition using all the fuctionality ms-build provides
Example:
Create brand new VB Console App in Visual Studio
add three class files ClassDotNetFeatures40.vb, ClassDotNetFeatures45.vb, GenericClass.vb
Add the following code
in GenericClass.vb
Partial Public Class GenericClass
Public Sub Hello()
Console.Write("Hello ")
End Sub
End Class
in ClassDotNetFeatures40.vb
Partial Public Class GenericClass
Public Sub Word()
Console.Write("4.0 Word!")
End Sub
End Class
in
ClassDotNetFeatures45.vb
Public Class GenericClass
Public Sub Word()
Console.Write("4.5 Word!")
End Sub
End Class
Put the following code in Module1.vb
Sub Main()
Dim o = New GenericClass()
o.Hello()
o.Word()
End Sub
Save all
Right click on your solution and press Unload Project
Right click on the project file and press Edit Project
Find the following lines:
<Compile Include="ClassDotNetFeatures40.vb" />
<Compile Include="ClassDotNetFeatures45.vb" />
and replace them with
<Compile Condition="'$(Configuration)' == 'Debug'" Include="ClassDotNetFeatures40.vb" />
<Compile Condition="'$(Configuration)' == 'Release'" Include="ClassDotNetFeatures45.vb" />
press save
right click on project file and press Reload
now when you run the project undo debug you will get:
Hello 4.0 Word!
undo release you willl get:
Hello 4.5 Word!
You will need to change project files manually (I've played with csproj - hopefully vbproj works in the same way).
All project configurations properties described in the sections like this one:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
Please notice Condition statement - that describes that this particular property set specified for Debug, AnyCPU configuration.
What you need to do is to move TargetFrameworkVersion property from general top level to configuration-specific levels, something like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<!-- general properties here - removing framework related... -->
<!--<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>-->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<!-- Use 4.0 for Debug -->
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<!-- other properties here... -->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<!-- Use 4.5 for Release -->
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<!-- other properties here... -->
</PropertyGroup>
Please notice that VS.Net GUI does NOT support this, and will not display correct values in the project Properties window; though it will use these values for build.
Depending on complexity of your solution, you might found some other artifacts, as VS.Net will not reload project properly, but at least that should work with build from console.
Additionally, you might need to use similar conditional "hacks" to reference correct libraries.

Categories

Resources