Skip to content

Commit d37cf22

Browse files
committed
Fix handling of tuple types in using alias directives
Fixes #2690
1 parent 50a8501 commit d37cf22

5 files changed

Lines changed: 77 additions & 3 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,19 @@ public async Task TestFullyQualifiedAliasWithUnresolvedTypeParameterAsync()
228228
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
229229
}
230230

231+
[Fact]
232+
[WorkItem(2690, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2690")]
233+
public async Task TestFullyQualifiedAliasInsideNamespaceAsync()
234+
{
235+
var testCode = @"
236+
namespace Test {
237+
using Example = System.ValueTuple<System.Collections.IList, int>;
238+
}
239+
";
240+
241+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
242+
}
243+
231244
protected override CodeFixProvider GetCSharpCodeFixProvider()
232245
{
233246
return new SA1135CodeFixProvider();

StyleCop.Analyzers/StyleCop.Analyzers/Lightup/CSharp7.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@
6565
* [ ] `Microsoft.CodeAnalysis.IMethodSymbol.ReturnsByRef.get -> bool`
6666
* [ ] `Microsoft.CodeAnalysis.INamedTypeSymbol.GetTypeArgumentCustomModifiers(int ordinal) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CustomModifier>`
6767
* [ ] `Microsoft.CodeAnalysis.INamedTypeSymbol.IsComImport.get -> bool`
68-
* [ ] `Microsoft.CodeAnalysis.INamedTypeSymbol.TupleElements.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IFieldSymbol>`
69-
* [ ] `Microsoft.CodeAnalysis.INamedTypeSymbol.TupleUnderlyingType.get -> Microsoft.CodeAnalysis.INamedTypeSymbol`
68+
* [x] `Microsoft.CodeAnalysis.INamedTypeSymbol.TupleElements.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IFieldSymbol>`
69+
* [x] `Microsoft.CodeAnalysis.INamedTypeSymbol.TupleUnderlyingType.get -> Microsoft.CodeAnalysis.INamedTypeSymbol`
7070
* [ ] `Microsoft.CodeAnalysis.IParameterSymbol.RefCustomModifiers.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CustomModifier>`
7171
* [ ] `Microsoft.CodeAnalysis.IPropertySymbol.RefCustomModifiers.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CustomModifier>`
7272
* [ ] `Microsoft.CodeAnalysis.IPropertySymbol.ReturnsByRef.get -> bool`
73-
* [ ] `Microsoft.CodeAnalysis.ITypeSymbol.IsTupleType.get -> bool`
73+
* [x] `Microsoft.CodeAnalysis.ITypeSymbol.IsTupleType.get -> bool`
7474
* [x] `Microsoft.CodeAnalysis.MethodKind.LocalFunction = 17 -> Microsoft.CodeAnalysis.MethodKind`
7575
* [ ] `Microsoft.CodeAnalysis.PortableExecutableReference.GetMetadataId() -> Microsoft.CodeAnalysis.MetadataId`
7676
* [ ] `Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveGenericsOptions(Microsoft.CodeAnalysis.SymbolDisplayGenericsOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat`
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace StyleCop.Analyzers.Lightup
5+
{
6+
using System;
7+
using System.Collections.Immutable;
8+
using Microsoft.CodeAnalysis;
9+
10+
internal static class INamedTypeSymbolExtensions
11+
{
12+
private static readonly Func<INamedTypeSymbol, INamedTypeSymbol> TupleUnderlyingTypeAccessor;
13+
private static readonly Func<INamedTypeSymbol, ImmutableArray<IFieldSymbol>> TupleElementsAccessor;
14+
15+
static INamedTypeSymbolExtensions()
16+
{
17+
TupleUnderlyingTypeAccessor = LightupHelpers.CreateSyntaxPropertyAccessor<INamedTypeSymbol, INamedTypeSymbol>(typeof(INamedTypeSymbol), nameof(TupleUnderlyingType));
18+
TupleElementsAccessor = LightupHelpers.CreateSyntaxPropertyAccessor<INamedTypeSymbol, ImmutableArray<IFieldSymbol>>(typeof(INamedTypeSymbol), nameof(TupleElements));
19+
}
20+
21+
public static INamedTypeSymbol TupleUnderlyingType(this INamedTypeSymbol symbol)
22+
{
23+
return TupleUnderlyingTypeAccessor(symbol);
24+
}
25+
26+
public static ImmutableArray<IFieldSymbol> TupleElements(this INamedTypeSymbol symbol)
27+
{
28+
return TupleElementsAccessor(symbol);
29+
}
30+
}
31+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace StyleCop.Analyzers.Lightup
5+
{
6+
using System;
7+
using Microsoft.CodeAnalysis;
8+
9+
internal static class ITypeSymbolExtensions
10+
{
11+
private static readonly Func<ITypeSymbol, bool> IsTupleTypeAccessor;
12+
13+
static ITypeSymbolExtensions()
14+
{
15+
IsTupleTypeAccessor = LightupHelpers.CreateSyntaxPropertyAccessor<ITypeSymbol, bool>(typeof(ITypeSymbol), nameof(IsTupleType));
16+
}
17+
18+
public static bool IsTupleType(this ITypeSymbol symbol)
19+
{
20+
return IsTupleTypeAccessor(symbol);
21+
}
22+
}
23+
}

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace StyleCop.Analyzers.ReadabilityRules
1010
using Microsoft.CodeAnalysis.Diagnostics;
1111

1212
using StyleCop.Analyzers.Helpers;
13+
using StyleCop.Analyzers.Lightup;
1314

1415
/// <summary>
1516
/// A using directive is not qualified.
@@ -89,6 +90,12 @@ private static void CheckUsingDeclaration(SyntaxNodeAnalysisContext context, Usi
8990
return;
9091
}
9192

93+
if (symbol is INamedTypeSymbol typeSymbol
94+
&& typeSymbol.IsTupleType())
95+
{
96+
symbol = typeSymbol.TupleUnderlyingType();
97+
}
98+
9299
string symbolString = symbol.ToString();
93100
string usingString = usingDirective.Name.ToString();
94101
if ((symbolString != usingString) && !usingDirective.StartsWithAlias(context.SemanticModel, context.CancellationToken))

0 commit comments

Comments
 (0)