Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn: Current Workspace in Diagnostic with code fix project

Tags:

c#

roslyn

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.

like image 786
Michal Adda Avatar asked Apr 21 '14 18:04

Michal Adda


Video Answer


2 Answers

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.

like image 158
Matt Warren Avatar answered Nov 15 '22 03:11

Matt Warren


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();
}
like image 21
johnny 5 Avatar answered Nov 15 '22 03:11

johnny 5