9

I am successfully getting dependencies between projects with Roslyn, and now I would like to get dependencies between classes, similar to the Code Map feature in Visual Studio Enterprise.

Here is my code, the "?????" part is where I imagine I could get something. I am very new to the Roslyn API, though, and I don't know how to proceed from there on.

        Solution solution = MSBuildWorkspace.Create()
            .OpenSolutionAsync(Path.Combine(repoRootFolder, "MySolution.sln"))
            .Result;

        ProjectDependencyGraph projdeps = solution.GetProjectDependencyGraph();

        Digraph graph = new Digraph();

        foreach (ProjectId projectId in projdeps.GetTopologicallySortedProjects())
        {
            string projName = solution.GetProject(projectId).Name;
            var projDeps = projdeps.GetProjectsThatThisProjectDirectlyDependsOn(projectId);
            foreach (ProjectId depId in projDeps)
            {
                Project dep = solution.GetProject(depId);

                Compilation compilation = dep.GetCompilationAsync().Result;

                foreach (var syntree in compilation.SyntaxTrees)
                {
                    foreach (var classNode in syntree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
                    {
                        var classesThisClassNodeReferences = ?????????
                    }
                }

                string depName = dep.Name;

                graph.Dependencies.Add(new Dependency
                {
                    Source = projName,
                    Target = depName
                });
            }
        }
heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • Do you mean getting all used types withing that `ClassDeclarationSyntax`? You could get all `SyntaxNode`s, get the corresponding `ISymbol` through the semantic model, check if the symbol is an `INamedTypeSymbol` or not. But I think this will be extremely slow. – Tamas Aug 31 '16 at 14:29
  • @Tamas-SonarSourceTeam I need to generate dependency graphs and output them to PDF, so if it is slow it is not a deal breaker. But I could still not figure out how to perform the operation you propose. Could you perhaps post some code as an answer? It would help me a lot and I would test in my actual scenario as soon as possible. – heltonbiker Aug 31 '16 at 17:01
  • @heltonbiker What library are you using for your Digraph? – farlee2121 Apr 03 '18 at 18:27
  • @farlee2121 I created my own class, it's actually very crude, [here's the gist](https://gist.github.com/heltonbiker/6b38e4ed3c80d1b57e730a119c81aea8) – heltonbiker Apr 03 '18 at 19:06
  • @heltonbiker Thanks! I also found several available on Nuget. The most popular seems to be [graphX](https://www.nuget.org/packages/GraphX/) – farlee2121 Apr 03 '18 at 19:17
  • 1
    @heltonbiker You may also be interested in this open source alternative to CodeMap that I found https://github.com/zebmason/DeepEnds – farlee2121 Apr 03 '18 at 19:54

1 Answers1

7

I'm not sure about your requirements, but you can probably go for checking all descendant SyntaxNodes of the class and get the corresponding symbol, and it's type, and then collect these types. Something like the following:

var semantic = compilation.GetSemanticModel(syntree);
var typesForCurrentClass = classNode.DescendantNodes().Select(n => 
  semantic.GetTypeInfo(n).Type);

Note that there can be multiple typesForCurrentClass for a given class symbol because of partial classes.

Tamas
  • 6,260
  • 19
  • 30
  • It worked, but it is giving me _every_ type the classes uses, even .Net types, ints, strings, etc. CodeMap (the VS Enterprise feature I am trying to replicate) usually puts this kind of thing inside "Externals" group, but I have no current interest in those dependencies. Would you know a way to make `typesForCurrentClass` contain only types defined in the solution? Thanks for the interest! – heltonbiker Aug 31 '16 at 19:19
  • 2
    I'm not sure, you can check `type.ContainingAssembly`, and see if there's anything useful there. – Tamas Sep 01 '16 at 08:47