Skip to content

Commit

Permalink
Merge branch 'master' into 2019
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Dec 27, 2019
2 parents 8a983fb + cf56922 commit b83a77f
Show file tree
Hide file tree
Showing 21 changed files with 1,502 additions and 427 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ A collection of 500+ [analyzers](src/Analyzers/README.md), [refactorings](src/Re
* [NuGet Analyzers](#nuget-analyzers)
* [Roslynator API](#roslynator-api)
* [Roslynator Command-Line Interface](#roslynator-command-line-interface)
* [Roslynator for VS Code](#roslynator-for-vs-code)
* [Roslynator for VS Code](#extensions-for-visual-studio-code)
* [Release notes](ChangeLog.md)
* Follow on [Twitter](https://twitter.com/roslynator)

Expand Down
169 changes: 85 additions & 84 deletions docs/HowToConfigureAnalyzers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,122 +2,101 @@

## Content

* [Introduction](#introduction)
* [What Is Rule Set](#what-is-rule-set)
* [How to Configure a Rule Set](#how-to-configure-a-rule-set)
* [How to Suppress a Diagnostic](#how-to-suppress-a-diagnostic)
* [Configure Analyzers in a Ruleset File](#configure-analyzers-in-a-ruleset-file)
* [Configure Analyzers in an EditorConfig File](#configure-analyzers-in-an-editorconfig-file)
* [Change Default Configuration of Analyzers](#change-default-configuration-of-analyzers)
* [Suppress Diagnostics](#suppress-diagnostics)

## Introduction

* It is a common requirement to enable/disable specific analyzer or/and to change its action (from **Warning** to **Info** etc.)
* This can be easily accomplished by using **rule set**.
## Configure Analyzers in a Ruleset File

## What is Rule Set

* Rule set is a group of rules where each rule define "Action" for a specific analyzer.
* Action **None** deactivates analyzer.
* Other actions specifies that analyzer is active but it differs in how it is displayed in the IDE.

Action | Description
--- | ---
**None** | disabled
**Hidden** | not visible
**Info** | visible as **Message**
**Warning** | visible as **Warning**
**Error** | visible as **Error**

Rule set is typically stored in a file with extension **ruleset** and it has following structure:
* Ruleset is a group of rules where each rule define "Action" for a specific analyzer.
* Allowed actions are **None** (disabled), **Hidden** (not visible), **Info**, **Warning** or **Error**.
* Rules are stored in a XML file that has extension **ruleset** and following structure:

```xml
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="My Rules" ToolsVersion="15.0">
<Rules AnalyzerId="Roslynator.CSharp.Analyzers" RuleNamespace="Roslynator.CSharp.Analyzers">
<Rule Id="RCS1001" Action="Warning" />
</Rules>
</RuleSet>
```

## How to Configure a Rule Set
<!-- Specify zero or more paths to other rulesets that should be included. -->
<Include Path="parent.ruleset" Action="Default,None,Hidden,Info,Warning,Error" />

### Configure Rule Set for Old Project Format (.NET Framework)

#### 1) Create Your Own Rule Set File

* Skip this step if you already have one.
* Go to Solution Explorer - Solution - Project - References - Analyzers - Open Active Rule Set.

![Open Active Rule Set](/images/OpenActiveRuleSet.png)

* Modify rule set.
* Save rule set (this will create a new file **ProjectName.ruleset** in your project folder.
* Move rule set file to a solution root folder (or any other location).

![Rule Set Editor](/images/RuleSetEditor.png)
<Rules AnalyzerId="Roslynator.CSharp.Analyzers" RuleNamespace="Roslynator.CSharp.Analyzers">
<Rule Id="RCS...." Action="None,Hidden,Info,Warning,Error" />
</Rules>

#### 2) Modify Rule Set File Manually
<!-- Specify default action that should be applied to all analyzers except those explicitly specified. -->
<IncludeAll Action="None,Hidden,Info,Warning,Error" />

* Open rule set file in text editor.
* Change value of attribute 'Name' (rule set is represented in the IDE by its name).
</RuleSet>
```

![Edit Rule Set File](/images/EditRuleSetFile.png)
To enforce ruleset it is necessary to reference it in a csproj file:

#### 3) Attach Rule Set to Project(s)
```xml
<PropertyGroup>
<CodeAnalysisRuleSet>relative_or_absolute_path_to_ruleset_file</CodeAnalysisRuleSet>
</PropertyGroup>
```

* Go to Main Menu - Analysis - Configure Code Analysis - For Solution
Please see step-by-step tutorial [how to configure ruleset file](HowToConfigureRulesetFile.md).

![Configure Code Analysis for Solution](/images/ConfigureCodeAnalysisForSolution.png)

* Change rule set for each project.
* Change configuration and repeat previous step (optional).
## Configure Analyzers in an EditorConfig File

![Code Analysis Settings](/images/CodeAnalysisSettings.png)
*Note: This option is applicable for Visual Studio 2019 version 16.3 and later.*

Severity of a rule can be changed by adding following line to an EditorConfig file:
```
dotnet_diagnostic.<RULE_ID>.severity = <default|none|silent|info|warning|error>
```

### Configure Rule Set for New Project Format (.NET Core, .NET Standard)
For further information please see how to [set rule severity in an EditorConfig file](https://docs.microsoft.com/en-us/visualstudio/code-quality/use-roslyn-analyzers#set-rule-severity-in-an-editorconfig-file).

#### 1) Add New Rule Set File to Your Solution

* Go to Solution Explorer - Solution - Context Menu - Add - New Item - Code Analysis Rule Set
## Change Default Configuration of Analyzers

#### 2) Modify Rule Set File Manually
*Note: This option is applicable for Roslynator 2019 or later (Visual Studio) and for Roslynator for VS Code.*

* Open rule set file in text editor.
* Change value of attribute 'Name' (rule set is represented in the IDE by its name).
Roslynator ruleset file can be used to:

![Edit Rule Set File](/images/EditNewRuleSetFile.png)
1) Enable/disable analyzer(s) by DEFAULT.
2) Change DEFAULT severity (action) of the analyzer(s).

Default configuration is applied once when analyzers are loaded.
Therefore, it may be neccessary to restart IDE for changes to take effect.

#### 3) Attach Rule Set to Project(s)
### Location of Roslynator Ruleset File

* Open csproj file in text editor or go to Solution Explorer - Project - Context Menu - Edit ProjectName.csproj
* Add following `PropertyGroup` (or add element to the existing `PropertyGroup`):
Roslynator ruleset file must be named **roslynator.ruleset** and must be located in one of the following folders:

```xml
<PropertyGroup>
<CodeAnalysisRuleSet>relative_or_absolute_path_to_ruleset_file</CodeAnalysisRuleSet>
</PropertyGroup>
```
| Folder Path | Scope |
| -------- | ------- |
| `LOCAL_APP_DATA/JosefPihrt/Roslynator` | Visual Studio installations and VS Code installation |
| `LOCAL_APP_DATA/JosefPihrt/Roslynator/VisualStudio` | Visual Studio installations |
| `LOCAL_APP_DATA/JosefPihrt/Roslynator/VisualStudio/2019` | Visual Studio 2019 installations |
| `LOCAL_APP_DATA/JosefPihrt/Roslynator/VisualStudioCode` | VS Code installation |

## How to Change Default Configuration of Analyzers
### Location of LOCAL_APP_DATA Folder

Roslynator 2019 adds capability to:
1) Enable/disable analyzer(s) by DEFAULT.
2) Change DEFAULT severity (action) of the analyzer(s).
| OS | Path |
| -------- | ------- |
| Windows | `C:\Users\USER_NAME\AppData\Local` |
| Linux | `/home/USER_NAME/.local/share` |
| OSX | `/Users/USER_NAME/.local/share` |

Default configuration is stored in `%LOCALAPPDATA%\JosefPihrt\Roslynator\VisualStudio\2019\roslynator.ruleset`.

Before first use, it is necessary to copy `roslynator.ruleset` from the directory where Roslynator 2019 is installed
to the location where the configuration is stored.

IMPORTANT: Default configuration is applied once when analyzers are loaded.
Therefore, it may be necessary to restart Visual Studio for changes to take effect.
## Suppress Diagnostics

## How to Suppress a Diagnostic
Suppression of diagnostics is useful to suppress rare cases that are not or cannot be covered by an analyzer.

> Note: If you want to disable an analyzer completely you have use a rule set.
This approach should not be used as a replacement for configuration of analyzers since analyzers that produce diagnostics still execute even if diagnostics are suppressed.

### Suppress Diagnostic for a Declaration

```csharp
using System.Diagnostics.CodeAnalysis;

class C
{
[SuppressMessage("Readability", "RCS1008", Justification = "<Pending>")]
Expand All @@ -129,6 +108,8 @@ class C
```

```csharp
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Readability", "RCS1008", Justification = "<Pending>", Scope = "member", Target = "~M:C.M")]

class C
Expand All @@ -143,6 +124,8 @@ class C
### Suppress Diagnostic for Selected Lines

```csharp
using System.Diagnostics.CodeAnalysis;

class C
{
void M()
Expand All @@ -154,15 +137,33 @@ class C
}
```

### Suppress Diagnostic Globally (Roslynator 2017 only)
### Suppress Diagnostic for Namespace

```csharp
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Readability", "RCS1008", Justification = "<Pending>", Scope = "NamespaceAndDescendants", Target = "N1.N2")]

namespace N1.N2
{
class C
{
void M()
{
var x = Foo(); // no RCS1008 here
}
}
}
```

### Suppress Diagnostic Globally

*Note: this option is applicable for Roslynator 2017*

Go to Visual Studio Tools > Options > Roslynator > Global Suppressions

![Global Suppressions](/images/GlobalSuppressionsOptions.png)

## See Also

* [How to: Create a Custom Rule Set](https://msdn.microsoft.com/en-us/library/dd264974.aspx)
* [Working in the Code Analysis Rule Set Editor](https://msdn.microsoft.com/en-us/library/dd380626.aspx)
* [How to: Specify Managed Code Rule Sets for Multiple Projects in a Solution](https://msdn.microsoft.com/en-us/library/dd465181.aspx)
* [Rule Set XML Schema](https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/RuleSet/RuleSetSchema.xsd)
* [Use code analyzers](https://docs.microsoft.com/en-us/visualstudio/code-quality/use-roslyn-analyzers)
80 changes: 80 additions & 0 deletions docs/HowToConfigureRulesetFile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# How to: Configure Ruleset File

## New csproj format (.NET Core, .NET Standard)

### 1) Add New Rule Set File to Your Solution

* Go to Solution Explorer - Solution - Context Menu - Add - New Item - Code Analysis Rule Set

### 2) Modify Rule Set File Manually

* Open ruleset file in text editor.
* Change value of attribute 'Name' (ruleset is represented in the IDE by its name).

![Edit Rule Set File](/images/EditNewRuleSetFile.png)

### 3) Attach Rule Set to Project(s)

* Open csproj file in text editor or go to Solution Explorer - Project - Context Menu - Edit ProjectName.csproj
* Add following `PropertyGroup` (or add element to the existing `PropertyGroup`):

```xml
<PropertyGroup>
<CodeAnalysisRuleSet>RELATIVE_OR_ABSOLUTE_PATH_TO_RULESET_FILE</CodeAnalysisRuleSet>
</PropertyGroup>
```

## Old csproj format (.NET Framework)

### 1) Create Your Own Rule Set File

* Skip this step if you already have one.
* Go to Solution Explorer - Solution - Project - References - Analyzers - Open Active Rule Set.

![Open Active Rule Set](/images/OpenActiveRuleSet.png)

* Modify ruleset.
* Save ruleset (this will create a new file **ProjectName.ruleset** in your project folder.
* Move ruleset file to a solution root folder (or any other location).

![Rule Set Editor](/images/RuleSetEditor.png)

### 2) Modify Rule Set File Manually

* Open ruleset file in text editor.
* Change value of attribute 'Name' (ruleset is represented in the IDE by its name).

![Edit Rule Set File](/images/EditRuleSetFile.png)

### 3) Attach Rule Set to Project(s)

* Go to Main Menu - Analysis - Configure Code Analysis - For Solution

![Configure Code Analysis for Solution](/images/ConfigureCodeAnalysisForSolution.png)

* Change ruleset for each project.
* Change configuration and repeat previous step (optional).

![Code Analysis Settings](/images/CodeAnalysisSettings.png)

## Directory.Build.props File

It may be convenient to to specify ruleset in **Directory.Build.props** file.
This file is typically located in a root folder of a solution.

```xml
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)my.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
</Project>
```

## See Also

* [How to: Create a Custom Rule Set](https://msdn.microsoft.com/en-us/library/dd264974.aspx)
* [Working in the Code Analysis Rule Set Editor](https://msdn.microsoft.com/en-us/library/dd380626.aspx)
* [How to: Specify Managed Code Rule Sets for Multiple Projects in a Solution](https://msdn.microsoft.com/en-us/library/dd465181.aspx)
* [Rule Set XML Schema](https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/RuleSet/RuleSetSchema.xsd)
* [Customize your build](https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build)
* [Common MSBuild properties and items with Directory.Build.props](https://thomaslevesque.com/2017/09/18/common-msbuild-properties-and-items-with-directory-build-props/)
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

* [Configure Analyzers](HowToConfigureAnalyzers.md)
* [Configure Refactorings](HowToConfigureRefactorings.md)
* [Configure Ruleset File](HowToConfigureRulesetFile.md)
* [Customize Rules for a Project](HowToCustomizeRulesForProject.md)
* [Fix All Diagnostics in a Solution](HowToFixAllDiagnostics.md)
* [Generate API Documentation](HowToGenerateDocumentation.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand All @@ -27,7 +29,35 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeDeclarationSyntax typeDeclaration))
return;

ModifiersCodeFixRegistrator.RemoveModifier(context, context.Diagnostics[0], typeDeclaration, SyntaxKind.PartialKeyword);
Diagnostic diagnostic = context.Diagnostics[0];
Document document = context.Document;

CodeAction codeAction = CodeAction.Create(
ModifiersCodeFixRegistrator.GetRemoveModifierTitle(SyntaxKind.PartialKeyword),
ct =>
{
TypeDeclarationSyntax newTypeDeclaration = typeDeclaration.ReplaceNodes(
typeDeclaration.Members.OfType<MethodDeclarationSyntax>().Where(f => f.Modifiers.Contains(SyntaxKind.PartialKeyword) && f.BodyOrExpressionBody() != null),
(f, _) => f.RemoveModifier(SyntaxKind.PartialKeyword));
int count = newTypeDeclaration.Members.Count;
for (int i = count - 1; i >= 0; i--)
{
if (newTypeDeclaration.Members[i] is MethodDeclarationSyntax method
&& method.Modifiers.Contains(SyntaxKind.PartialKeyword))
{
newTypeDeclaration = SyntaxRefactorings.RemoveMember(newTypeDeclaration, method);
}
}
newTypeDeclaration = newTypeDeclaration.RemoveModifier(SyntaxKind.PartialKeyword);
return document.ReplaceNodeAsync(typeDeclaration, newTypeDeclaration, ct);
},
GetEquivalenceKey(DiagnosticIdentifiers.RemovePartialModifierFromTypeWithSinglePart));

context.RegisterCodeFix(codeAction, diagnostic);
}
}
}
Loading

0 comments on commit b83a77f

Please sign in to comment.