c# - 确定两个 SyntaxToken 是否相同

标签 c# roslyn roslyn-code-analysis

以下面一段代码为例:

public class Thing
{
    public int Item { get; }

    public Thing(int item)
    {
        Item = Item; // note incorrect assignment: rhs should be item, the passed-in arg, hence analyzer should warn
    }

    public Thing(Thing other)
    {
      Item = other.Item; // correct assignment, should NOT trigger analyzer
    }
}

我正在编写一个 Roslyn 分析器来检测和报告这些可能错误的 self 分配情况,相关部分如下:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(MistakenSelfAssignment, SyntaxKind.SimpleAssignmentExpression);
}

private static void MistakenSelfAssignment(SyntaxNodeAnalysisContext context)
{
    var assignment = context.Node as AssignmentExpressionSyntax;
    if (assignment == null)
    {
        return;
    }

    var leftToken = GetIdentifierToken(assignment.Left);
    var rightToken = GetIdentifierToken(assignment.Right);

    if (leftToken != null && leftToken.IsEquivalentTo(rightToken)) // this never works
    {
        var diagnostic = Diagnostic.Create(Rule, assignment.GetLocation());
        context.ReportDiagnostic(diagnostic);
    }
}

private static SyntaxToken GetIdentifierToken(ExpressionSyntax syntax)
{
    var identifierName = syntax as IdentifierNameSyntax;
    if (identifierName != null)
    {
        return identifierName.Identifier;
    }

    var identifierAccess = syntax as MemberAccessExpressionSyntax;
    if (identifierAccess != null)
    {
        return identifierAccess.Name.Identifier;
    }

    return default(SyntaxToken);
}

但我不知道如何确定赋值的 LHS 和 RHS 是否是同一个标记 - SyntaxToken.IsEquivalentTo 似乎是我想要的方法,但它总是返回 false, SyntaxToken.Equals== 也是如此。

确定 token 是否引用自身的正确方法是什么?

最佳答案

我认为您不能在 SyntaxToken 级别上执行此操作。起初,我认为语义模型在这里可以帮到你,但在这两种情况下,符号指的是同一个东西,所以你不能用它来区分。

但是,您可以做的只是调查 SimpleAssignmentExpression,检查两个操作数是否都是标识符,并通过相同的 SyntaxFactory.AreEquivalent() 检查它们的等价性马库斯提到。我做到了这一点(有关完整的 LINQPad 查询,请参阅 this gist):

假设您编写了这个方法:

private static bool IsAssignmentBad(AssignmentExpressionSyntax assignmentNode)
{
    if (!assignmentNode.IsKind(SyntaxKind.SimpleAssignmentExpression))
    {
        return false;
    }

    var lhs = assignmentNode.Left;
    if (!lhs.IsKind(SyntaxKind.IdentifierName))
    {
        return false;
    }

    var rhs = assignmentNode.Right;
    if (!rhs.IsKind(SyntaxKind.IdentifierName))
    {
        return false;
    }

    return SyntaxFactory.AreEquivalent(lhs, rhs);
}

然后用这个运行它会得到你想要的,我想:

var tree = CSharpSyntaxTree.ParseText(
@"public class Thing
{
    public int Item { get; }

    public Thing(int item)
    {
        Item = Item; // note incorrect assignment: rhs should be item, the passed-in arg, hence analyzer should warn
    }

    public Thing(Thing other)
    {
        Item = other.Item; // correct assignment, should NOT trigger analyzer
    }
}");

var root = tree.GetRoot();

var incorrectAssignment = root.DescendantNodes().OfType<AssignmentExpressionSyntax>().First();
var correctAssignment = root.DescendantNodes().OfType<AssignmentExpressionSyntax>().Last();

var b1 = IsAssignmentBad(correctAssignment); // doesn't consider the assignment bad
var b2 = IsAssignmentBad(incorrectAssignment); // this one does

关于c# - 确定两个 SyntaxToken 是否相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39741244/

相关文章:

c# - 在 Roslyn 中使用泛型生成有效类型名称的技术

c# - 使用 Roslyn 编译

c# - 如何知道 Roslyn 的 ScripEngine 中的输入是否仅部分完成

c# - Roslyn - 抛出构建错误

c# - 可靠地将类型符号 (ITypeSymbol) 与 Roslyn 进行比较

c# - 什么是 UMThunkStubAMD64?为什么它看起来是一个瓶颈?

C# 怎么可能 false == true ?见图片

c# - 调用需要对象数组的方法

c# - MassTransit 3,其中 AzureServiceBus 在队列名称前添加斜杠

c# - Roslyn 向现有类添加新方法