Skip to content

Commit 62850e9

Browse files
authored
Merge pull request #110 from bkoelman/config
Added support for rule configuration settings
2 parents 81a0507 + 25f003a commit 62850e9

File tree

13 files changed

+807
-59
lines changed

13 files changed

+807
-59
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ The latest version requires [Visual Studio 2017 with Update 5](https://www.visua
3030

3131
* Optional: [Reference CSharpGuidelines.Layer.DotSettings in your existing Resharper preferences](/docs/Resharper%20Settings.md)
3232

33+
## Rule configuration
34+
The behavior of a few rules can optionally be customized using a configuration file. See [documentation](docs/Configuration.md) for details.
35+
3336
## Suppressing rules
3437
Rule warnings can be suppressed at various scopes, ranging from per line to at the project or solution level.
3538

docs/Configuration.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Rule configuration
2+
3+
The behavior of rules can be customized by adding a file named `CSharpGuidelinesAnalyzer.config` to your C# project with the following structure:
4+
5+
```xml
6+
<?xml version="1.0" encoding="utf-8"?>
7+
<cSharpGuidelinesAnalyzerSettings>
8+
<setting rule="AV1500" name="MaxStatementCount" value="12" />
9+
<setting rule="AV1561" name="MaxParameterCount" value="5" />
10+
</cSharpGuidelinesAnalyzerSettings>
11+
```
12+
13+
The next step is to change the Build Action (Properties window) of this file to **AdditionalFiles** (or **C# analyzer additional file**, depending on project type). This should result in the following line added to your project file:
14+
15+
```xml
16+
<AdditionalFiles Include="CSharpGuidelinesAnalyzer.config" />
17+
```
18+
19+
For a complete list of the available rules and their configuration settings, see [Overview](/docs/Overview.md).
20+
21+
## Multiple projects
22+
23+
If your solution consists of multiple projects, you can share the configuration by moving `CSharpGuidelinesAnalyzer.config` to the solution folder and updating your project files to use a relative link:
24+
```xml
25+
<AdditionalFiles Include="..\CSharpGuidelinesAnalyzer.config">
26+
<Link>CSharpGuidelinesAnalyzer.config</Link>
27+
</AdditionalFiles>
28+
```

docs/Overview.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ This analyzer reports when a method return type is `IEnumerable` or `IEnumerable
4949
### [AV1500](https://github.com/dennisdoomen/CSharpGuidelines/blob/1a90b74c95225a0f7e4d0e7a341fd027e17c2320/_pages/1500_MaintainabilityGuidelines.md#av1500): Methods should not exceed 7 statements ![](/images/warn.png "severity: warning")
5050
This analyzer reports when a method body (such as a method, property getter or local function) contains more than 7 statements.
5151

52+
**Note:** This rule can be customized using a [configuration file](/docs/Configuration.md) by setting **MaxStatementCount** to a value in range 0-255.
53+
5254
### [AV1502](https://github.com/dennisdoomen/CSharpGuidelines/blob/1a90b74c95225a0f7e4d0e7a341fd027e17c2320/_pages/1500_MaintainabilityGuidelines.md#av1502): Avoid conditions with double negatives ![](/images/warn.png "severity: warning")
5355
This analyzer reports when the logical not operator is applied on an argument that has the word "No" or "Not" in its name.
5456

@@ -100,6 +102,8 @@ This analyzer reports when a method, constructor, local function, indexer or del
100102
- declares a tuple parameter
101103
- returns a tuple with more than 2 elements.
102104

105+
**Note:** This rule can be customized using a [configuration file](/docs/Configuration.md) by setting **MaxParameterCount** to a value in range 0-255.
106+
103107
### [AV1562](https://github.com/dennisdoomen/CSharpGuidelines/blob/1a90b74c95225a0f7e4d0e7a341fd027e17c2320/_pages/1500_MaintainabilityGuidelines.md#av1562): Don't use ref or out parameters ![](/images/warn.png "severity: warning")
104108
This analyzer reports when:
105109
- a parameter is declared as `ref`

src/CSharpGuidelinesAnalyzer/CSharpGuidelinesAnalyzer.Test/Specs/Maintainability/AvoidMemberWithManyStatementsSpecs.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using CSharpGuidelinesAnalyzer.Rules.Maintainability;
77
using CSharpGuidelinesAnalyzer.Test.TestDataBuilders;
8+
using FluentAssertions;
89
using Microsoft.CodeAnalysis.Diagnostics;
910
using Xunit;
1011

@@ -2762,6 +2763,139 @@ class C
27622763
"Method 'C.M(bool)' contains 8 statements, which exceeds the maximum of 7 statements.");
27632764
}
27642765

2766+
#region Non-default configuration
2767+
2768+
[Fact]
2769+
internal void When_method_body_contains_seventeen_statements_it_must_be_reported()
2770+
{
2771+
// Arrange
2772+
ParsedSourceCode source = new TypeSourceCodeBuilder()
2773+
.WithSettings(new AnalyzerSettingsBuilder()
2774+
.Including(DiagnosticId, "MaxStatementCount", "16"))
2775+
.InGlobalScope(@"
2776+
class C
2777+
{
2778+
int [|M|](string s)
2779+
{
2780+
; ; ; ;
2781+
; ; ; ;
2782+
; ; ; ;
2783+
; ; ; ;
2784+
throw null;
2785+
}
2786+
}
2787+
")
2788+
.Build();
2789+
2790+
// Act and assert
2791+
VerifyGuidelineDiagnostic(source,
2792+
"Method 'C.M(string)' contains 17 statements, which exceeds the maximum of 16 statements.");
2793+
}
2794+
2795+
[Fact]
2796+
public void When_settings_are_corrupt_it_must_use_default_value()
2797+
{
2798+
// Arrange
2799+
ParsedSourceCode source = new TypeSourceCodeBuilder()
2800+
.WithSettings("*** BAD XML ***")
2801+
.InGlobalScope(@"
2802+
class C
2803+
{
2804+
int [|M|](string s)
2805+
{
2806+
; ; ; ;
2807+
; ; ;
2808+
throw null;
2809+
}
2810+
}
2811+
")
2812+
.Build();
2813+
2814+
// Act and assert
2815+
VerifyGuidelineDiagnostic(source,
2816+
"Method 'C.M(string)' contains 8 statements, which exceeds the maximum of 7 statements.");
2817+
}
2818+
2819+
[Fact]
2820+
public void When_setting_is_missing_it_must_use_default_value()
2821+
{
2822+
// Arrange
2823+
ParsedSourceCode source = new TypeSourceCodeBuilder()
2824+
.WithSettings(new AnalyzerSettingsBuilder()
2825+
.Including(DiagnosticId, "OtherUnusedSetting", "SomeValue"))
2826+
.InGlobalScope(@"
2827+
class C
2828+
{
2829+
int [|M|](string s)
2830+
{
2831+
; ; ; ;
2832+
; ; ;
2833+
throw null;
2834+
}
2835+
}
2836+
")
2837+
.Build();
2838+
2839+
// Act and assert
2840+
VerifyGuidelineDiagnostic(source,
2841+
"Method 'C.M(string)' contains 8 statements, which exceeds the maximum of 7 statements.");
2842+
}
2843+
2844+
[Fact]
2845+
public void When_setting_value_is_missing_it_must_use_default_value()
2846+
{
2847+
// Arrange
2848+
ParsedSourceCode source = new TypeSourceCodeBuilder()
2849+
.WithSettings(new AnalyzerSettingsBuilder()
2850+
.Including(DiagnosticId, "MaxStatementCount", null))
2851+
.InGlobalScope(@"
2852+
class C
2853+
{
2854+
int [|M|](string s)
2855+
{
2856+
; ; ; ;
2857+
; ; ;
2858+
throw null;
2859+
}
2860+
}
2861+
")
2862+
.Build();
2863+
2864+
// Act and assert
2865+
VerifyGuidelineDiagnostic(source,
2866+
"Method 'C.M(string)' contains 8 statements, which exceeds the maximum of 7 statements.");
2867+
}
2868+
2869+
[Fact]
2870+
public void When_setting_value_is_out_of_range_it_must_fail()
2871+
{
2872+
// Arrange
2873+
ParsedSourceCode source = new TypeSourceCodeBuilder()
2874+
.WithSettings(new AnalyzerSettingsBuilder()
2875+
.Including(DiagnosticId, "MaxStatementCount", "-1"))
2876+
.InGlobalScope(@"
2877+
class C
2878+
{
2879+
int [|M|](string s)
2880+
{
2881+
; ; ; ;
2882+
; ; ;
2883+
throw null;
2884+
}
2885+
}
2886+
")
2887+
.Build();
2888+
2889+
// Act
2890+
Action action = () => VerifyGuidelineDiagnostic(source);
2891+
2892+
// Assert
2893+
action.Should().Throw<Exception>()
2894+
.WithMessage("*Value for AV1500:MaxStatementCount configuration setting must be in range 0-255.*");
2895+
}
2896+
2897+
#endregion
2898+
27652899
protected override DiagnosticAnalyzer CreateAnalyzer()
27662900
{
27672901
return new AvoidMemberWithManyStatementsAnalyzer();

src/CSharpGuidelinesAnalyzer/CSharpGuidelinesAnalyzer.Test/Specs/Maintainability/AvoidSignatureWithManyParametersSpecs.cs

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using CSharpGuidelinesAnalyzer.Rules.Maintainability;
34
using CSharpGuidelinesAnalyzer.Test.TestDataBuilders;
5+
using FluentAssertions;
46
using Microsoft.CodeAnalysis.Diagnostics;
57
using Xunit;
68

@@ -716,6 +718,107 @@ void M()
716718
"Local function 'L' returns a tuple with 3 elements, which exceeds the maximum of 2 elements.");
717719
}
718720

721+
#region Non-default configuration
722+
723+
[Fact]
724+
internal void When_method_contains_nine_parameters_it_must_be_reported()
725+
{
726+
// Arrange
727+
ParsedSourceCode source = new MemberSourceCodeBuilder()
728+
.WithSettings(new AnalyzerSettingsBuilder()
729+
.Including(DiagnosticId, "MaxParameterCount", "8"))
730+
.InDefaultClass(@"
731+
void [|M|](int first, string second, double third, float fourth, byte fifth, char sixth, DateTime seventh, TimeSpan eighth, ushort ninth)
732+
{
733+
}
734+
")
735+
.Build();
736+
737+
// Act and assert
738+
VerifyGuidelineDiagnostic(source,
739+
"Method 'M' contains 9 parameters, which exceeds the maximum of 8 parameters.");
740+
}
741+
742+
[Fact]
743+
internal void When_settings_are_corrupt_it_must_use_default_value()
744+
{
745+
// Arrange
746+
ParsedSourceCode source = new MemberSourceCodeBuilder()
747+
.WithSettings("*** BAD XML ***")
748+
.InDefaultClass(@"
749+
void [|M|](int first, string second, double third, float fourth, byte fifth, char sixth, DateTime seventh, TimeSpan eighth, ushort ninth)
750+
{
751+
}
752+
")
753+
.Build();
754+
755+
// Act and assert
756+
VerifyGuidelineDiagnostic(source,
757+
"Method 'M' contains 9 parameters, which exceeds the maximum of 3 parameters.");
758+
}
759+
760+
[Fact]
761+
internal void When_setting_is_missing_it_must_use_default_value()
762+
{
763+
// Arrange
764+
ParsedSourceCode source = new MemberSourceCodeBuilder()
765+
.WithSettings(new AnalyzerSettingsBuilder()
766+
.Including(DiagnosticId, "OtherUnusedSetting", "SomeValue"))
767+
.InDefaultClass(@"
768+
void [|M|](int first, string second, double third, float fourth, byte fifth, char sixth, DateTime seventh, TimeSpan eighth, ushort ninth)
769+
{
770+
}
771+
")
772+
.Build();
773+
774+
// Act and assert
775+
VerifyGuidelineDiagnostic(source,
776+
"Method 'M' contains 9 parameters, which exceeds the maximum of 3 parameters.");
777+
}
778+
779+
[Fact]
780+
internal void When_setting_value_is_missing_it_must_use_default_value()
781+
{
782+
// Arrange
783+
ParsedSourceCode source = new MemberSourceCodeBuilder()
784+
.WithSettings(new AnalyzerSettingsBuilder()
785+
.Including(DiagnosticId, "MaxParameterCount", null))
786+
.InDefaultClass(@"
787+
void [|M|](int first, string second, double third, float fourth, byte fifth, char sixth, DateTime seventh, TimeSpan eighth, ushort ninth)
788+
{
789+
}
790+
")
791+
.Build();
792+
793+
// Act and assert
794+
VerifyGuidelineDiagnostic(source,
795+
"Method 'M' contains 9 parameters, which exceeds the maximum of 3 parameters.");
796+
}
797+
798+
[Fact]
799+
internal void When_setting_value_is_out_of_range_it_must_fail()
800+
{
801+
// Arrange
802+
ParsedSourceCode source = new MemberSourceCodeBuilder()
803+
.WithSettings(new AnalyzerSettingsBuilder()
804+
.Including(DiagnosticId, "MaxParameterCount", "-1"))
805+
.InDefaultClass(@"
806+
void [|M|](int first, string second, double third, float fourth, byte fifth, char sixth, DateTime seventh, TimeSpan eighth, ushort ninth)
807+
{
808+
}
809+
")
810+
.Build();
811+
812+
// Act
813+
Action action = () => VerifyGuidelineDiagnostic(source);
814+
815+
// Assert
816+
action.Should().Throw<Exception>()
817+
.WithMessage("*Value for AV1561:MaxParameterCount configuration setting must be in range 0-255.*");
818+
}
819+
820+
#endregion
821+
719822
protected override DiagnosticAnalyzer CreateAnalyzer()
720823
{
721824
return new AvoidSignatureWithManyParametersAnalyzer();

0 commit comments

Comments
 (0)