diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs index 58d1ec7b3..99bfc9f53 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs @@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Test.ReadabilityRules { using System.Threading; using System.Threading.Tasks; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing; using StyleCop.Analyzers.ReadabilityRules; using Xunit; @@ -320,6 +321,67 @@ namespace MyNamespace { await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); } + [Fact] + [WorkItem(2879, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2879")] + public async Task TestOmittedTypeInGenericAsync() + { + var testCode = @" +namespace TestNamespace +{ + using Example = System.Collections.Generic.List<>; +} +"; + + var expected = new DiagnosticResult("CS7003", DiagnosticSeverity.Error).WithLocation(4, 48).WithMessage("Unexpected use of an unbound generic name"); + await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2879, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2879")] + public async Task TestNullableTypeInGenericAsync() + { + var testCode = @" +namespace TestNamespace +{ + using Example = System.Collections.Generic.List; +} +"; + + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2879, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2879")] + public async Task TestGlobalQualifiedTypeInGenericAsync() + { + var testCode = @" +namespace TestNamespace +{ + using Example = System.Collections.Generic.List; +} +"; + + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(2879, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2879")] + public async Task TestTypeInGlobalNamespaceAsync() + { + var testCode = @" +namespace TestNamespace +{ + using Example = MyClass; +} + +class MyClass +{ +} +"; + + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + [Fact] [WorkItem(2879, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2879")] public async Task TestAliasTypeNestedInGenericAsync() diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SymbolNameHelpers.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SymbolNameHelpers.cs index ac0683660..0f4c3c488 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SymbolNameHelpers.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SymbolNameHelpers.cs @@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Helpers { using System.Text; using Microsoft.CodeAnalysis; + using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using StyleCop.Analyzers.Lightup; @@ -36,9 +37,10 @@ public static string ToQualifiedString(this ISymbol symbol, NameSyntax name) private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol symbol, TypeSyntax type) { - switch (symbol) + switch (symbol.Kind) { - case IArrayTypeSymbol arraySymbol: + case SymbolKind.ArrayType: + var arraySymbol = (IArrayTypeSymbol)symbol; AppendQualifiedSymbolName(builder, arraySymbol.ElementType, (type as ArrayTypeSyntax)?.ElementType); builder .Append("[") @@ -46,7 +48,8 @@ private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol sym .Append("]"); return true; - case INamespaceSymbol namespaceSymbol: + case SymbolKind.Namespace: + var namespaceSymbol = (INamespaceSymbol)symbol; if (namespaceSymbol.IsGlobalNamespace) { return false; @@ -55,7 +58,8 @@ private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol sym builder.Append(namespaceSymbol.ToDisplayString()); return true; - case INamedTypeSymbol namedTypeSymbol: + case SymbolKind.NamedType: + var namedTypeSymbol = (INamedTypeSymbol)symbol; if (SpecialTypeHelper.TryGetPredefinedType(namedTypeSymbol.SpecialType, out var specialTypeSyntax)) { builder.Append(specialTypeSyntax.ToFullString()); @@ -94,6 +98,12 @@ private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol sym return AppendQualifiedSymbolName(builder, namedTypeSymbol.TupleUnderlyingType(), type); } } + else if (namedTypeSymbol.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) + { + AppendQualifiedSymbolName(builder, namedTypeSymbol.TypeArguments[0], (type as NullableTypeSyntax)?.ElementType); + builder.Append("?"); + return true; + } else { if (AppendQualifiedSymbolName(builder, symbol.ContainingSymbol, (type as QualifiedNameSyntax)?.Left)) @@ -113,14 +123,17 @@ private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol sym for (int i = 0; i < arguments.Length; i++) { var argument = arguments[i]; - var argumentType = argumentTypes.Arguments.Count > i ? argumentTypes.Arguments[i] : null; + var argumentType = argumentTypes != null && argumentTypes.Arguments.Count > i ? argumentTypes.Arguments[i] : null; if (i > 0) { builder.Append(GenericSeparator); } - AppendQualifiedSymbolName(builder, argument, argumentType); + if (!argumentType.IsKind(SyntaxKind.OmittedTypeArgument)) + { + AppendQualifiedSymbolName(builder, argument, argumentType); + } } builder.Append(GenericTypeParametersClose); @@ -130,8 +143,13 @@ private static bool AppendQualifiedSymbolName(StringBuilder builder, ISymbol sym } default: - builder.Append(symbol.Name); - return true; + if (symbol != null) + { + builder.Append(symbol.Name); + return true; + } + + return false; } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs index 130b1cc81..cddfef1ed 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs @@ -3,7 +3,6 @@ namespace StyleCop.Analyzers.ReadabilityRules { - using System; using System.Collections.Immutable; using System.Text; using Microsoft.CodeAnalysis; @@ -215,19 +214,6 @@ private static bool AppendCanonicalString(StringBuilder builder, TypeSyntax type builder.Append(")"); return true; } - else if (RefTypeSyntaxWrapper.IsInstance(type)) - { - var refType = (RefTypeSyntaxWrapper)type; - builder.Append(refType.RefKeyword.Text); - if (refType.ReadOnlyKeyword.IsKind(SyntaxKind.ReadOnlyKeyword)) - { - builder.Append(" ").Append(refType.ReadOnlyKeyword.Text); - } - - builder.Append(" "); - AppendCanonicalString(builder, refType.Type); - return true; - } else { return false;