首页 > 解决方案 > 在 Roslyn 如何找出两个符号是等价的?

问题描述

假设我创建了两个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与语法树关联的两个对象

我想知道是否有更好的方法。

标签: c#roslynroslyn-code-analysis

解决方案


IsEquivalentTo (...)方法可用于比较两个 trees、或nodes的相等性。例如tokenstrivias

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

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

推荐阅读