【发布时间】: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
我刚刚意识到,如果源代码相同,那么我们可以不用比较节点:
- 比较与符号关联的各个
SyntaxNode对象的跨度。 - 如果相等,则比较与语法树关联的两个
SourceText对象
不知道有没有更好的办法。
【问题讨论】:
-
"语法树不同,但源代码完全相同" --> 这有点令人困惑。如果源代码相同,编译器前端会生成相同的语法树。
-
什么意思?如果我通过运行
CSharpSyntaxTree.ParseText(CODE)创建两个语法树,生成的语法树将无法通过Assert.AreEqual测试,即使源代码相同。你能详细说明一下吗? -
您可以使用IsEquivalentTo方法比较两个语法树:
syntaxTree1.IsEquivalentTo(syntaxTree2) -
也适用于
SyntaxNode类型的对象,例如node1.IsEquivalentTo(node2). -
我错过了
IsEquivalentTo的存在。您能否安排您的回复作为答案,以便我可以信任您?
标签: c# roslyn roslyn-code-analysis