7

I'm trying to write some code to find all method invocations of any given method as I am looking to create an open source UML Sequence Diagramming tool. I'm having trouble, however, getting past the first few lines of code :/

The API appears to have changed drastically and I can't seem to infer proper usage by looking at the code.

When I do:

    var workspace = new CustomWorkspace();
    string solutionPath = @"C:\Workspace\RoslynTest\RoslynTest.sln";
    var solution = workspace.CurrentSolution;

I find that workspace.CurrentSolution has 0 Projects. I figured this would be the equivalent to what was previously Workspace.LoadSolution( string solutionFile ) which would then supposedly contain any Projects in the Solution, but I am not finding any success with this path.

I am terribly confused 0.o

If someone could offer some additional guidance as to how I can use the FindReferences API to identify all invocations of a particular method, it would be very much appreciated!

Alternatively, would I be better off taking a static-analysis approach? I would like to support things like lambdas, iterator methods and async.

====================================================================

Edit -

Here is a full example based on the accepted answer:

using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.FindSymbols;
using System.Diagnostics;

namespace RoslynTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string solutionPath = @"C:\Workspace\RoslynTest\RoslynTest.sln";
            var workspace = MSBuildWorkspace.Create();
            var solution = workspace.OpenSolutionAsync(solutionPath).Result;
            var project = solution.Projects.Where(p => p.Name == "RoslynTest").First();
            var compilation = project.GetCompilationAsync().Result;
            var programClass = compilation.GetTypeByMetadataName("RoslynTest.Program");

            var barMethod = programClass.GetMembers("Bar").First();
            var fooMethod = programClass.GetMembers("Foo").First();

            var barResult = SymbolFinder.FindReferencesAsync(barMethod, solution).Result.ToList();
            var fooResult = SymbolFinder.FindReferencesAsync(fooMethod, solution).Result.ToList();

            Debug.Assert(barResult.First().Locations.Count() == 1);
            Debug.Assert(fooResult.First().Locations.Count() == 0);
        }

        public bool Foo()
        {
            return "Bar" == Bar();
        }

        public string Bar()
        {
            return "Bar";
        }
    }
}
Jordan
  • 5,085
  • 7
  • 34
  • 50
  • I tried your solution and I stumble upon this property "CanOpenDocuments" assigned at false when in Solution-> Workspace->CanOpenDocuments What did I do wrong ? – Kevin Avignon Apr 14 '15 at 14:26
  • solution could be outdated - feel free to update the thread – Jordan Apr 15 '15 at 23:09

3 Answers3

9

CustomWorkspace is

A workspace that allows manual addition of projects and documents.

Since you're trying to load a solution, you should use the MSBuildWorkspace, which is

A workspace that can be populated by opening MSBuild solution and project files.

You can create a new MSBuildWorkspace and call OpenSolutionAsync with your solutionPath. For the reference finding part, take a look at the SymbolFinder.

David Poeschl
  • 864
  • 4
  • 11
  • @DavirdPoeschl If I don't know the name of the solution while running my analyzer, how could I fetch dynamically ? – Kevin Avignon Apr 14 '15 at 14:17
  • @KevinAvignon If you're in an analyzer, you should only need the information provided by the API (the syntax node or symbol to analyze and some context). What do you need beyond what's provided? If you have a scenario, consider creating a separate question for it. – David Poeschl Apr 21 '15 at 15:49
2

Solutions are an MSBuild concept.

You need to create an MSBuildWorkspace and call OpenSolutionAsync().

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
1
string solutionPath = @"C:\Workspace\RoslynTest\RoslynTest.sln";

creates a local variable. It has no influence on your CustomWorkspace object.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720