diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/DocumentationRules/SA1649CSharp10UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/DocumentationRules/SA1649CSharp10UnitTests.cs
index 3ae105437..e63b2cd68 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/DocumentationRules/SA1649CSharp10UnitTests.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/DocumentationRules/SA1649CSharp10UnitTests.cs
@@ -3,9 +3,47 @@
namespace StyleCop.Analyzers.Test.CSharp10.DocumentationRules
{
+ using System.Threading;
+ using System.Threading.Tasks;
using StyleCop.Analyzers.Test.CSharp9.DocumentationRules;
+ using StyleCop.Analyzers.Test.Helpers;
+ using Xunit;
+ using static StyleCop.Analyzers.Test.Verifiers.CustomDiagnosticVerifier<
+ StyleCop.Analyzers.DocumentationRules.SA1649FileNameMustMatchTypeName>;
public class SA1649CSharp10UnitTests : SA1649CSharp9UnitTests
{
+ ///
+ /// Verifies that the file name is based on the first type.
+ ///
+ /// The type keyword to use during the test.
+ /// A representing the asynchronous unit test.
+ [Theory]
+ [MemberData(nameof(CommonMemberData.TypeDeclarationKeywords), MemberType = typeof(CommonMemberData))]
+ [WorkItem(3435, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3435")]
+ public async Task VerifyFirstTypeIsUsedWithFileScopedNamespacesAsync(string typeKeyword)
+ {
+ var testCode = $@"namespace TestNamespace;
+
+public enum IgnoredEnum {{ }}
+public delegate void IgnoredDelegate();
+
+{GetTypeDeclaration(typeKeyword, "TestType", diagnosticKey: 0)}
+
+{GetTypeDeclaration(typeKeyword, "TestType2")}
+";
+ var fixedCode = $@"namespace TestNamespace;
+
+public enum IgnoredEnum {{ }}
+public delegate void IgnoredDelegate();
+
+{GetTypeDeclaration(typeKeyword, "TestType")}
+
+{GetTypeDeclaration(typeKeyword, "TestType2")}
+";
+
+ var expectedDiagnostic = Diagnostic().WithLocation(0);
+ await VerifyCSharpFixAsync("TestType2.cs", testCode, StyleCopSettings, expectedDiagnostic, "TestType.cs", fixedCode, CancellationToken.None).ConfigureAwait(false);
+ }
}
}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/MaintainabilityRules/SA1402CSharp10ForClassUnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/MaintainabilityRules/SA1402CSharp10ForClassUnitTests.cs
index cfade8dbc..41e3c74a8 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/MaintainabilityRules/SA1402CSharp10ForClassUnitTests.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/MaintainabilityRules/SA1402CSharp10ForClassUnitTests.cs
@@ -3,9 +3,41 @@
namespace StyleCop.Analyzers.Test.CSharp10.MaintainabilityRules
{
+ using System.Threading;
+ using System.Threading.Tasks;
using StyleCop.Analyzers.Test.CSharp9.MaintainabilityRules;
+ using Xunit;
public class SA1402CSharp10ForClassUnitTests : SA1402CSharp9ForClassUnitTests
{
+ [Fact]
+ [WorkItem(3435, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3435")]
+ public async Task VerifyTwoClassesWithFileScopedNamespacesAsync()
+ {
+ var testCode = $@"namespace TestNamespace;
+
+public class TestClass1 {{ }}
+public class {{|#0:TestClass2|}} {{ }}
+";
+ var fixedCode1 = $@"namespace TestNamespace;
+
+public class TestClass1 {{ }}
+";
+ var fixedCode2 = $@"namespace TestNamespace;
+public class TestClass2 {{ }}
+";
+
+ var expectedDiagnostic = this.Diagnostic().WithLocation(0);
+ await this.VerifyCSharpFixAsync(
+ testCode,
+ this.GetSettings(),
+ expectedDiagnostic,
+ new[]
+ {
+ ("/0/Test0.cs", fixedCode1),
+ ("TestClass2.cs", fixedCode2),
+ },
+ CancellationToken.None).ConfigureAwait(false);
+ }
}
}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1649UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1649UnitTests.cs
index ccb105e31..5f2bf72bb 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1649UnitTests.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/DocumentationRules/SA1649UnitTests.cs
@@ -17,7 +17,7 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
///
public class SA1649UnitTests
{
- private const string MetadataSettings = @"
+ protected const string MetadataSettings = @"
{
""settings"": {
""documentationRules"": {
@@ -27,7 +27,7 @@ public class SA1649UnitTests
}
";
- private const string StyleCopSettings = @"
+ protected const string StyleCopSettings = @"
{
""settings"": {
""documentationRules"": {
@@ -331,7 +331,7 @@ public class Class2
await VerifyCSharpDiagnosticAsync("Class1.cs", testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}
- private static string GetTypeDeclaration(string typeKind, string typeName, int? diagnosticKey = null)
+ protected static string GetTypeDeclaration(string typeKind, string typeName, int? diagnosticKey = null)
{
if (diagnosticKey is not null)
{
@@ -345,7 +345,7 @@ private static string GetTypeDeclaration(string typeKind, string typeName, int?
};
}
- private static Task VerifyCSharpDiagnosticAsync(string fileName, string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
+ protected static Task VerifyCSharpDiagnosticAsync(string fileName, string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
{
var test = new StyleCopCodeFixVerifier.CSharpTest()
{
@@ -356,10 +356,10 @@ private static Task VerifyCSharpDiagnosticAsync(string fileName, string source,
return test.RunAsync(cancellationToken);
}
- private static Task VerifyCSharpFixAsync(string oldFileName, string source, string testSettings, DiagnosticResult expected, string newFileName, string fixedSource, CancellationToken cancellationToken)
+ protected static Task VerifyCSharpFixAsync(string oldFileName, string source, string testSettings, DiagnosticResult expected, string newFileName, string fixedSource, CancellationToken cancellationToken)
=> VerifyCSharpFixAsync(oldFileName, source, testSettings, new[] { expected }, newFileName, fixedSource, cancellationToken);
- private static Task VerifyCSharpFixAsync(string oldFileName, string source, string testSettings, DiagnosticResult[] expected, string newFileName, string fixedSource, CancellationToken cancellationToken)
+ protected static Task VerifyCSharpFixAsync(string oldFileName, string source, string testSettings, DiagnosticResult[] expected, string newFileName, string fixedSource, CancellationToken cancellationToken)
{
var test = new StyleCopCodeFixVerifier.CSharpTest()
{
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1649FileNameMustMatchTypeName.cs b/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1649FileNameMustMatchTypeName.cs
index 125fc6e4d..b087bb726 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1649FileNameMustMatchTypeName.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1649FileNameMustMatchTypeName.cs
@@ -11,6 +11,7 @@ namespace StyleCop.Analyzers.DocumentationRules
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using StyleCop.Analyzers.Helpers;
+ using StyleCop.Analyzers.Lightup;
using StyleCop.Analyzers.Settings.ObjectModel;
///
@@ -97,13 +98,13 @@ public static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopS
private static MemberDeclarationSyntax GetFirstTypeDeclaration(SyntaxNode root)
{
// Prefer to find the first type which is a true TypeDeclarationSyntax
- MemberDeclarationSyntax firstTypeDeclaration = root.DescendantNodes(descendIntoChildren: node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration))
+ MemberDeclarationSyntax firstTypeDeclaration = root.DescendantNodes(descendIntoChildren: node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration))
.OfType()
.FirstOrDefault();
// If no TypeDeclarationSyntax is found, expand the search to any type declaration as long as only one
// is present
- var expandedTypeDeclarations = root.DescendantNodes(descendIntoChildren: node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration))
+ var expandedTypeDeclarations = root.DescendantNodes(descendIntoChildren: node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration))
.OfType()
.Where(node => node is BaseTypeDeclarationSyntax || node.IsKind(SyntaxKind.DelegateDeclaration))
.ToList();
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleType.cs b/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleType.cs
index 35e153783..18194e065 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleType.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleType.cs
@@ -12,6 +12,7 @@ namespace StyleCop.Analyzers.MaintainabilityRules
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using StyleCop.Analyzers.Helpers;
+ using StyleCop.Analyzers.Lightup;
using StyleCop.Analyzers.Settings.ObjectModel;
///
@@ -99,7 +100,7 @@ private static IEnumerable GetTopLevelTypeDeclarations(
private static bool ContainsTopLevelTypeDeclarations(SyntaxNode node)
{
- return node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration);
+ return node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration);
}
private static bool IsRelevantType(SyntaxNode node, StyleCopSettings settings)