Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare type symbols (ITypeSymbol) from different projects in Roslyn?

I have 2 test projects in solution.
First project ("VDoc") declare VDocQuery type.
Second project ("VDocQueryTest" ) calls VDocQuery constructor.
I get 2 VDocQuery's ITypeSymbol's (one from each project), compare it, but get false result.

Steps:
1. Get first ITypeSymbol (from VDoc project with SemanticModel.LookupNamespacesAndTypes() method).
2. Get second ITypeSymbol from VDocQueryTest project (from ObjectCreationExpressionSyntax.GetTypeInfo().Type)
3. Compare it with ITypeSymbol.Equals(ITypeSymbol).

I expected true result, but get false result.

Question: How to correctly compare ITypeSymbols from different projects within one solution?

Code example:

class Program
{
    static void Main(string[] args)
    {
        string solutionPath = @"..\..\..\StaticAnalysis.sln";

        MSBuildWorkspace workspace = MSBuildWorkspace.Create();
        Solution solution = workspace.OpenSolutionAsync(solutionPath).Result;

        var vdocProject = FindProjectByName("VDoc", solution);
        SemanticModel semanticModel = vdocProject.Documents.First().GetSemanticModelAsync().Result;
        var nsVDocQueryFunctionalTest = (INamespaceOrTypeSymbol)semanticModel.LookupNamespacesAndTypes(0, null, "VDocQueryFunctionalTest").First();
        var tVDocQuery = (ITypeSymbol)semanticModel.LookupNamespacesAndTypes(0, nsVDocQueryFunctionalTest, "VDocQuery").First();

        TypeInfo ti = GetFromVDocRef(solution);
        bool result1 = ti.Type.Equals(tVDocQuery); // false, expected = true?

        //these 2 lines added after Jason Malinowski answer
        var sVDocQuerySource = SymbolFinder.FindSourceDefinitionAsync(ti.Type, solution).Result;
        bool result2 = sVDocQuerySource.Equals(tVDocQuery); // false, expected = true?

       //this line solved the problem, thanks to @Tamas
       bool result3 = ti.Type.DeclaringSyntaxReferences.FirstOrDefault()?.Equals(tVDocQuery.DeclaringSyntaxReferences.FirstOrDefault()) ?? false;
    }

    private static TypeInfo GetFromVDocRef(Solution solution)
    {
        var vdocQueryTestProject = FindProjectByName("VDocQueryTest", solution);
        var vdocQueryTestProjectSemanticModel = vdocQueryTestProject.Documents.First().GetSemanticModelAsync().Result;
        var compilationUnit = (CompilationUnitSyntax)vdocQueryTestProject.Documents.First().GetSyntaxRootAsync().Result;
        var ns = (NamespaceDeclarationSyntax)compilationUnit.Members[0];
        var cls = (ClassDeclarationSyntax)ns.Members[0];
        var method = (MethodDeclarationSyntax)cls.Members[0];
        var stat = (ExpressionStatementSyntax)method.Body.Statements[0];
        var newExpr = (ObjectCreationExpressionSyntax)stat.Expression;
        var ti = vdocQueryTestProjectSemanticModel.GetTypeInfo(newExpr);
        return ti;
    }

    static Project FindProjectByName(string projectName, Solution solution)
    {
        var project = solution.Projects.SingleOrDefault(p => p.Name == projectName);
        return project;
    }
}

VDocQuery.cs:

using System.Collections.Generic;

namespace VDocQueryFunctionalTest
{
    public class VDocQuery
    {
        public VDocQuery()
        {
        }

        public void AddFields(string docType, params string[] fields)
        {
        }

        public List<VDoc> Execute()
        {
            return null;
        }
    }
}

VDocQueryUse.cs:

using VDocQueryFunctionalTest;

namespace VDocQueryTest
{
    static class VDocQueryUse
    {
        public static void VDocQueryUseTest()
        {
            new VDocQuery();
        }
    }
}
like image 321
Alex Sedow Avatar asked Sep 26 '22 05:09

Alex Sedow


1 Answers

I could reproduce your problem by using different target frameworks in the two projects. Set the same target framework for both projects and then your original solution will find the matching types.

If you can't change the target frameworks, then you could still compare the ITypeSymbol.DeclaringSyntaxReferences.

like image 158
Tamas Avatar answered Oct 03 '22 13:10

Tamas