Search code examples
c#roslynroslyn-code-analysis

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


Suppose I created two Compilation objects, initialized both with the same SyntaxTree, obtained two SemanticModel objects and used each to obtain a symbol to the same declaration.

Here is the complete unit test.

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);
        }
    }
}

Notice the two symbols are not equal, but we can get to their respective declarations and because both symbols are associated with the same SyntaxTree object we can figure out they are equivalent.

How can one figure out that these symbols are equivalent, if the syntax trees are different, but the code is the same?

EDIT 1

I have slightly modified the question - I am looking for the way to establish equivalence if the syntax trees are different, but the source code is the exactly the same for both trees.

EDIT 2

I have just realised that if the source code is the same, then instead of comparing the nodes we can:

  1. Compare the spans of the respective SyntaxNode objects associated with the symbols.
  2. If equal, compare the two SourceText objects associated with the syntax trees

I wonder if there is a better way.


Solution

  • The IsEquivalentTo(...) method can be used to compare the equality of two trees, nodes, tokens or trivias. For example

    var syntaxTree1 = CSharpSyntaxTree.ParseText(CODE);
    var syntaxTree2 = CSharpSyntaxTree.ParseText(CODE);
    
    Assert.IsTrue(syntaxTree1.IsEquivalentTo(syntaxTree2));