Skip to content

Commit

Permalink
Merge pull request #3436 from sharwell/file-namespaces
Browse files Browse the repository at this point in the history
Support file-scoped namespaces in SA1649 and SA1402
  • Loading branch information
sharwell authored Jan 14, 2022
2 parents 88d9d3f + e1f52bf commit a821966
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/// <summary>
/// Verifies that the file name is based on the first type.
/// </summary>
/// <param name="typeKeyword">The type keyword to use during the test.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace StyleCop.Analyzers.Test.DocumentationRules
/// </summary>
public class SA1649UnitTests
{
private const string MetadataSettings = @"
protected const string MetadataSettings = @"
{
""settings"": {
""documentationRules"": {
Expand All @@ -27,7 +27,7 @@ public class SA1649UnitTests
}
";

private const string StyleCopSettings = @"
protected const string StyleCopSettings = @"
{
""settings"": {
""documentationRules"": {
Expand Down Expand Up @@ -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)
{
Expand All @@ -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<SA1649FileNameMustMatchTypeName, SA1649CodeFixProvider>.CSharpTest()
{
Expand All @@ -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<SA1649FileNameMustMatchTypeName, SA1649CodeFixProvider>.CSharpTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand Down Expand Up @@ -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<TypeDeclarationSyntax>()
.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<MemberDeclarationSyntax>()
.Where(node => node is BaseTypeDeclarationSyntax || node.IsKind(SyntaxKind.DelegateDeclaration))
.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand Down Expand Up @@ -99,7 +100,7 @@ private static IEnumerable<MemberDeclarationSyntax> 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)
Expand Down

0 comments on commit a821966

Please sign in to comment.