5

How can I get information about current Workspace (e.g project path, solution path) in Diagnostic with code fix project?

I am implementing Diagnostic of type ISyntaxNodeAnalyzer

I need to access SymbolFinder.FindImplementationsAsync, but to do so, I need Solution instance

EDIT: I have code like this:

var syntax = (LocalDeclarationStatementSyntax) node;
var type = syntax.Declaration.Type;
var typeSymbol = semanticModel.GetTypeInfo(type).ConvertedType;

I would like to find out all usages / references of typeSymbol. TypeSymbol represents Class located in source code.

To do so, I wanted to use SymbolFinder, but methods of SymbolFinder require instance of Solution... In older version of Roslyn, Document was given as Method Parameter of diagnostics, you could get to project and solution.

andyp
  • 6,229
  • 3
  • 38
  • 55
Michal Adda
  • 113
  • 7

2 Answers2

7

There is no current way to get at workspace or to do multi-project analysis when implementing a diagnostic analyzer, as these need to be able to run against a single compilation using only the command-line compiler. You can, however, do this work in the code fix provider once a diagnostic is determined.

If you just want to find all places where once class implements another, you can make a compilation wide diagnostic analyzer and examine all declarations before deciding on a diagnostic. You can do this by implementing both ICompilationStartedAnalyzer and ICompilationEndedAnalyzer.

Matt Warren
  • 1,956
  • 14
  • 15
  • Can I somehow get to Solution instance from actual Diagnostic? Or Document Instance? Older version of Roslyn had Document as method parameter. – Michal Adda Apr 21 '14 at 19:04
  • Or can I just get path to solution that is currently being diagnosed? – Michal Adda Apr 21 '14 at 19:24
  • You cannot get to those -- at the compiler level there is no guarantee those things even exist. I'd you update your question to explain what you want your diagnostic to do, we can provide better guidance. – Jason Malinowski Apr 22 '14 at 01:21
2

If you really need to do this you can, but it through reflection there is no gaurentee it will work on all enviroments or any future version etc... I've only tested this in windows environment.

public static class RoslynExtensions
{
    public static Solution GetSolution(this SyntaxNodeAnalysisContext context)
    {
        var workspace = context.Options.GetPrivatePropertyValue<object>("Workspace");
        return workspace.GetPrivatePropertyValue<Solution>("CurrentSolution");
    }

    public static T GetPrivatePropertyValue<T>(this object obj, string propName)
    {
        if (obj == null)
        {
            throw new ArgumentNullException(nameof(obj));
        }

        var pi = obj.GetType().GetRuntimeProperty(propName);

        if (pi == null)
        {
            throw new ArgumentOutOfRangeException(nameof(propName), $"Property {propName} was not found in Type {obj.GetType().FullName}");
        }

        return (T)pi.GetValue(obj, null);
    }
}

Called from an analyzer like so:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzeConstDeclaration, SyntaxKind.FieldDeclaration);
}

public static void AnalyzeConstDeclaration(SyntaxNodeAnalysisContext context)
{
     var solution = context.GetSolution();
}
johnny 5
  • 19,893
  • 50
  • 121
  • 195