提交 ace2887f 编写于 作者: M Marcin Wachulski

Fix implicit type use analyzer.

Fixes edge cases where variable identifier name is reused in the initializer as first part of member access qualification.
Example: SomeEnum SomeEnum = SomeEnum.EnumVal1

Fixes dotnet/roslyn#26894
上级 a1cc790a
......@@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.TypeStyle;
......@@ -371,6 +372,150 @@ void M()
}", new TestParameters(options: ImplicitTypeEverywhere()));
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
[WorkItem(26894, "https://github.com/dotnet/roslyn/issues/26894")]
public async Task NotOnVariablesOfEnumTypeNamedAsEnumTypeUsedInInitalizerExpressionAtFirstPosition()
{
await TestMissingInRegularAndScriptAsync(
@"using System;
enum A { X, Y }
class C
{
void M()
{
[|A|] A = A.X;
}
}", new TestParameters(options: ImplicitTypeEverywhere()));
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
[WorkItem(26894, "https://github.com/dotnet/roslyn/issues/26894")]
public async Task NotOnVariablesNamedAsTypeUsedInInitalizerExpressionContainingTypeNameAtFirstPositionOfMemberAccess()
{
await TestMissingInRegularAndScriptAsync(
@"using System;
class A
{
public static A Instance;
}
class C
{
void M()
{
[|A|] A = A.Instance;
}
}", new TestParameters(options: ImplicitTypeEverywhere()));
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
[WorkItem(26894, "https://github.com/dotnet/roslyn/issues/26894")]
public async Task SuggestOnVariablesUsedInInitalizerExpressionAsInnerPartsOfQualifiedNameStartedWithGlobal()
{
await TestAsync(
@"enum A { X, Y }
class C
{
void M()
{
[|A|] A = global::A.X;
}
}",
@"enum A { X, Y }
class C
{
void M()
{
var A = global::A.X;
}
}", CSharpParseOptions.Default, options: ImplicitTypeEverywhere());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
[WorkItem(26894, "https://github.com/dotnet/roslyn/issues/26894")]
public async Task SuggestOnVariablesUsedInInitalizerExpressionAsInnerPartsOfQualifiedName()
{
await TestInRegularAndScriptAsync(
@"using System;
namespace N
{
class A
{
public static A Instance;
}
}
class C
{
void M()
{
[|N.A|] A = N.A.Instance;
}
}",
@"using System;
namespace N
{
class A
{
public static A Instance;
}
}
class C
{
void M()
{
var A = N.A.Instance;
}
}", options: ImplicitTypeEverywhere());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
[WorkItem(26894, "https://github.com/dotnet/roslyn/issues/26894")]
public async Task SuggestOnVariablesUsedInInitalizerExpressionAsLastPartOfQualifiedName()
{
await TestInRegularAndScriptAsync(
@"using System;
class A {}
class X
{
public static A A;
}
class C
{
void M()
{
[|A|] A = X.A;
}
}",
@"using System;
class A {}
class X
{
public static A A;
}
class C
{
void M()
{
var A = X.A;
}
}", options: ImplicitTypeEverywhere());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
public async Task NotOnAssignmentToInterfaceType()
{
......
......@@ -261,8 +261,25 @@ protected override bool ShouldAnalyzeForEachStatement(ForEachStatementSyntax for
// variables declared using var cannot be used further in the same initialization expression.
if (initializer.DescendantNodesAndSelf()
.Where(n => (n as IdentifierNameSyntax)?.Identifier.ValueText.Equals(identifier.ValueText) == true)
.Any(n => semanticModel.GetSymbolInfo(n, cancellationToken).Symbol?.IsKind(SymbolKind.Local) == true))
.Where(n => n is IdentifierNameSyntax id && id.Identifier.ValueText.Equals(identifier.ValueText))
.Any(n =>
{
// case of variable direct use: int x = x * 2;
if (semanticModel.GetSymbolInfo(n, cancellationToken).Symbol.IsKind(SymbolKind.Local) == true)
{
return true;
}
// case of qualification starting with the variable name: SomeEnum SomeEnum = SomeEnum.EnumVal1;
// note that: SomeEnum SomeEnum = global::SomeEnum.EnumVal1; // is ok and 'var' can be offered
// https://github.com/dotnet/roslyn/issues/26894
if (n.Parent is MemberAccessExpressionSyntax memberAccessParent && memberAccessParent.Expression == n)
{
return true;
}
return false;
}))
{
return false;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册