Skip to content

Commit aa6c944

Browse files
Merge pull request #8 from bjornhellander/feature/sa1402-file-modifier
Update SA1402FileMayOnlyContainASingleType to treat types with the file accessibility modifier as not relevant
2 parents 64d88c5 + b486c12 commit aa6c944

File tree

10 files changed

+162
-4
lines changed

10 files changed

+162
-4
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForClassCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForClassCSharp11UnitTests : SA1402ForClassCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file class TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForDelegateCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForDelegateCSharp11UnitTests : SA1402ForDelegateCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file delegate void TestType2();
21+
";
22+
23+
await VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForEnumCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForEnumCSharp11UnitTests : SA1402ForEnumCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file enum TestType2 {{ }}
21+
";
22+
23+
await VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForInterfaceCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForInterfaceCSharp11UnitTests : SA1402ForInterfaceCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file interface TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForRecordCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForRecordCSharp11UnitTests : SA1402ForRecordCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file record TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForRecordClassCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForRecordClassCSharp11UnitTests : SA1402ForRecordClassCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file record class TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForRecordStructCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForRecordStructCSharp11UnitTests : SA1402ForRecordStructCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file record struct TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/MaintainabilityRules/SA1402ForStructCSharp11UnitTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp11.MaintainabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules;
10+
using Xunit;
711

812
public partial class SA1402ForStructCSharp11UnitTests : SA1402ForStructCSharp10UnitTests
913
{
14+
[Fact]
15+
[WorkItem(3803, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3803")]
16+
public async Task TestFileModifierAsync()
17+
{
18+
var testCode = $@"
19+
public class TestType1 {{ }}
20+
file struct TestType2 {{ }}
21+
";
22+
23+
await this.VerifyCSharpDiagnosticAsync(
24+
testCode,
25+
this.GetSettings(),
26+
DiagnosticResult.EmptyDiagnosticResults,
27+
CancellationToken.None).ConfigureAwait(false);
28+
}
1029
}
1130
}

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleType.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Contributors to the New StyleCop Analyzers project.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4-
#nullable disable
5-
64
namespace StyleCop.Analyzers.MaintainabilityRules
75
{
86
using System;
@@ -111,30 +109,36 @@ private static bool ContainsTopLevelTypeDeclarations(SyntaxNode node)
111109
private static bool IsRelevantType(SyntaxNode node, StyleCopSettings settings)
112110
{
113111
var topLevelTypes = settings.MaintainabilityRules.TopLevelTypes;
114-
var isRelevant = false;
115112

113+
var isRelevant = false;
114+
SyntaxTokenList modifiers = default;
116115
switch (node.Kind())
117116
{
118117
case SyntaxKind.ClassDeclaration:
119118
case SyntaxKindEx.RecordDeclaration:
120119
isRelevant = topLevelTypes.Contains(TopLevelType.Class);
120+
modifiers = ((BaseTypeDeclarationSyntax)node).Modifiers;
121121
break;
122122
case SyntaxKind.InterfaceDeclaration:
123123
isRelevant = topLevelTypes.Contains(TopLevelType.Interface);
124+
modifiers = ((BaseTypeDeclarationSyntax)node).Modifiers;
124125
break;
125126
case SyntaxKind.StructDeclaration:
126127
case SyntaxKindEx.RecordStructDeclaration:
127128
isRelevant = topLevelTypes.Contains(TopLevelType.Struct);
129+
modifiers = ((BaseTypeDeclarationSyntax)node).Modifiers;
128130
break;
129131
case SyntaxKind.EnumDeclaration:
130132
isRelevant = topLevelTypes.Contains(TopLevelType.Enum);
133+
modifiers = ((BaseTypeDeclarationSyntax)node).Modifiers;
131134
break;
132135
case SyntaxKind.DelegateDeclaration:
133136
isRelevant = topLevelTypes.Contains(TopLevelType.Delegate);
137+
modifiers = ((DelegateDeclarationSyntax)node).Modifiers;
134138
break;
135139
}
136140

137-
return isRelevant;
141+
return isRelevant && !modifiers.Any(x => x.IsKind(SyntaxKindEx.FileKeyword));
138142
}
139143
}
140144
}

documentation/SA1402.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ It is possible to configure which kind of types this rule should affect. By defa
2727

2828
It is also possible to place multiple parts of the same partial type within the same file.
2929

30+
Types with the `file` access modifier are not taken into account.
31+
3032
## How to fix violations
3133

3234
To fix an instance of this violation, move each type into its own file.

0 commit comments

Comments
 (0)