提交 5db2d642 编写于 作者: C CyrusNajmabadi

Do not simplify to an alias in a nameof if it changes the value of hte nameof.

上级 0a304b01
......@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
......@@ -10,9 +9,7 @@
using Microsoft.CodeAnalysis.CSharp.CodeFixes.SimplifyTypeNames;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -346,6 +343,114 @@ class A
}");
}
[WorkItem(21449, "https://github.com/dotnet/roslyn/issues/21449")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
public async Task DoNotChangeToAliasInNameOfIfItChangesNameOfName()
{
await TestInRegularAndScript1Async(
@"using System;
using Foo = SimplifyInsideNameof.Program;
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof([|SimplifyInsideNameof.Program|]));
}
}
}",
@"using System;
using Foo = SimplifyInsideNameof.Program;
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof(Program));
}
}
}");
}
[WorkItem(21449, "https://github.com/dotnet/roslyn/issues/21449")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
public async Task DoChangeToAliasInNameOfIfItDoesNotAffectName1()
{
await TestInRegularAndScriptAsync(
@"using System;
using Goo = SimplifyInsideNameof.Program;
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof([|SimplifyInsideNameof.Program|].Main));
}
}
}",
@"using System;
using Goo = SimplifyInsideNameof.Program;
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof(Goo.Main));
}
}
}");
}
[WorkItem(21449, "https://github.com/dotnet/roslyn/issues/21449")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
public async Task DoChangeToAliasInNameOfIfItDoesNotAffectName2()
{
await TestInRegularAndScriptAsync(
@"using System;
using Goo = N.Goo;
namespace N {
class Goo { }
}
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof([|N.Goo|]));
}
}
}",
@"using System;
using Goo = N.Goo;
namespace N {
class Goo { }
}
namespace SimplifyInsideNameof
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(nameof(Goo));
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
public async Task TwoAliases()
{
......
......@@ -2497,15 +2497,10 @@ public static bool IsNameOfContext(this SyntaxTree syntaxTree, int position, Sem
// if the nameof expression has a missing close paren, it is parsed as an invocation expression.
if (token.Parent.IsKind(SyntaxKind.ArgumentList) &&
token.Parent.IsParentKind(SyntaxKind.InvocationExpression))
token.Parent.Parent is InvocationExpressionSyntax invocationExpression &&
invocationExpression.IsNameOfInvocation())
{
var invocationExpression = (InvocationExpressionSyntax)token.Parent.Parent;
if (!invocationExpression.IsRightSideOfDotOrArrowOrColonColon() &&
invocationExpression.Expression.IsKind(SyntaxKind.IdentifierName) &&
((IdentifierNameSyntax)invocationExpression.Expression).Identifier.IsKindOrHasMatchingText(SyntaxKind.NameOfKeyword))
{
parentExpression = invocationExpression;
}
parentExpression = invocationExpression;
}
if (parentExpression != null)
......
......@@ -412,9 +412,7 @@ public static bool IsNamedArgumentIdentifier(this ExpressionSyntax expression)
}
public static bool IsInsideNameOf(this ExpressionSyntax expression)
{
return expression.SyntaxTree.IsNameOfContext(expression.SpanStart);
}
=> expression.SyntaxTree.IsNameOfContext(expression.SpanStart);
private static bool CanReplace(ISymbol symbol)
{
......@@ -1114,6 +1112,23 @@ private static bool ValidateAliasForTarget(IAliasSymbol aliasReplacement, Semant
{
var aliasName = aliasReplacement.Name;
// If we're the argument of a nameof(X.Y) call, then we can't simplify to an
// alias unless the alias has the same name as us (i.e. 'Y').
if (node.IsNameOfArgumentExpression())
{
var nameofValueOpt = semanticModel.GetConstantValue(node.Parent.Parent.Parent);
if (!nameofValueOpt.HasValue)
{
return false;
}
if (nameofValueOpt.Value is string existingVal &&
existingVal != aliasName)
{
return false;
}
}
var boundSymbols = semanticModel.LookupNamespacesAndTypes(node.SpanStart, name: aliasName);
if (boundSymbols.Length == 1)
......@@ -1128,6 +1143,20 @@ private static bool ValidateAliasForTarget(IAliasSymbol aliasReplacement, Semant
return false;
}
public static bool IsNameOfArgumentExpression(this ExpressionSyntax expression)
{
return expression.IsParentKind(SyntaxKind.Argument) &&
expression.Parent.IsParentKind(SyntaxKind.ArgumentList) &&
expression.Parent.Parent.Parent is InvocationExpressionSyntax invocation &&
invocation.IsNameOfInvocation();
}
public static bool IsNameOfInvocation(this InvocationExpressionSyntax invocation)
{
return invocation.Expression is IdentifierNameSyntax identifierName &&
identifierName.Identifier.IsKindOrHasMatchingText(SyntaxKind.NameOfKeyword);
}
public static IAliasSymbol GetAliasForSymbol(INamespaceOrTypeSymbol symbol, SyntaxToken token, SemanticModel semanticModel, CancellationToken cancellationToken)
{
var originalSemanticModel = semanticModel.GetOriginalSemanticModel();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册