【问题标题】:In Roslyn how to figure out that two symbols are equivalent?在 Roslyn 如何找出两个符号是等价的?
【发布时间】:2021-12-19 22:38:59
【问题描述】:

假设我创建了两个Compilation 对象,都使用相同的SyntaxTree 进行了初始化,获得了两个SemanticModel 对象并使用每个对象来获得同一个声明的符号。

这是完整的单元测试。

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using NUnit.Framework;
using System.Linq;

namespace CSTool.UnitTests
{
    public class RoslynScratch
    {
        private const string CODE = @"namespace N
{
    public class T
    {
    }
}";
        [Test]
        public void SameSymbols()
        {
            var syntaxTree = CSharpSyntaxTree.ParseText(CODE);
            var node = syntaxTree.GetCompilationUnitRoot().DescendantNodes().OfType<TypeDeclarationSyntax>().FirstOrDefault();
            Assert.IsNotNull(node);
            var s1 = GetDeclSymbol(node);
            var s2 = GetDeclSymbol(node);
            Assert.IsFalse(SymbolEqualityComparer.Default.Equals(s1, s2));
            Assert.IsNotNull(GetDeclNode(s1));
            Assert.AreEqual(GetDeclNode(s1), GetDeclNode(s2));
        }

        private static SyntaxNode GetDeclNode(ISymbol s) => s.DeclaringSyntaxReferences.FirstOrDefault().GetSyntax();

        private static ISymbol GetDeclSymbol(TypeDeclarationSyntax node)
        {
            var compilation = CSharpCompilation.Create("test", new[] { node.SyntaxTree });
            var model = compilation.GetSemanticModel(node.SyntaxTree);
            return model.GetDeclaredSymbol(node);
        }
    }
}

注意这两个符号不相等,但我们可以得到它们各自的声明,因为这两个符号都与同一个 SyntaxTree 对象相关联,所以我们可以确定它们是等价的。

如果语法树不同,但代码相同,如何判断这些符号是等价的?

编辑 1

我稍微修改了这个问题 - 如果语法树不同,我正在寻找建立等效性的方法,但两棵树的源代码完全相同。

编辑 2

我刚刚意识到,如果源代码相同,那么我们可以不用比较节点:

  1. 比较与符号关联的各个 SyntaxNode 对象的跨度。
  2. 如果相等,则比较与语法树关联的两个 SourceText 对象

不知道有没有更好的办法。

【问题讨论】:

  • "语法树不同,但源代码完全相同" --> 这有点令人困惑。如果源代码相同,编译器前端会生成相同的语法树。
  • 什么意思?如果我通过运行CSharpSyntaxTree.ParseText(CODE) 创建两个语法树,生成的语法树将无法通过Assert.AreEqual 测试,即使源代码相同。你能详细说明一下吗?
  • 您可以使用IsEquivalentTo方法比较两个语法树:syntaxTree1.IsEquivalentTo(syntaxTree2)
  • 也适用于 SyntaxNode 类型的对象,例如node1.IsEquivalentTo(node2).
  • 我错过了IsEquivalentTo的存在。您能否安排您的回复作为答案,以便我可以信任您?

标签: c# roslyn roslyn-code-analysis


【解决方案1】:

IsEquivalentTo(...) 方法可用于比较两个treesnodestokenstrivias 的相等性。例如

var syntaxTree1 = CSharpSyntaxTree.ParseText(CODE);
var syntaxTree2 = CSharpSyntaxTree.ParseText(CODE);

Assert.IsTrue(syntaxTree1.IsEquivalentTo(syntaxTree2));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 2021-09-28
    • 2010-12-16
    • 1970-01-01
    • 2011-01-21
    相关资源
    最近更新 更多