在罗斯林如何弄清楚两个符号是等价的?

In Roslyn how to figure out that two symbols are equivalent?

假设我创建了两个 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对象

不知道有没有更好的办法

IsEquivalentTo(...)方法可以用来比较两个treesnodestokenstrivias是否相等。例如

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

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