在罗斯林如何弄清楚两个符号是等价的?
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
我刚刚意识到,如果源代码相同,那么我们可以不用比较节点:
- 比较与符号关联的各个
SyntaxNode
对象的跨度。
- 如果相等,比较与语法树关联的两个
SourceText
对象
不知道有没有更好的办法
IsEquivalentTo(...)方法可以用来比较两个trees
、nodes
、tokens
或trivias
是否相等。例如
var syntaxTree1 = CSharpSyntaxTree.ParseText(CODE);
var syntaxTree2 = CSharpSyntaxTree.ParseText(CODE);
Assert.IsTrue(syntaxTree1.IsEquivalentTo(syntaxTree2));
假设我创建了两个 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
对象
不知道有没有更好的办法
IsEquivalentTo(...)方法可以用来比较两个trees
、nodes
、tokens
或trivias
是否相等。例如
var syntaxTree1 = CSharpSyntaxTree.ParseText(CODE);
var syntaxTree2 = CSharpSyntaxTree.ParseText(CODE);
Assert.IsTrue(syntaxTree1.IsEquivalentTo(syntaxTree2));