0

I'm writing a DiagnosticAnalyzer, and register a SyntaxNode action for SyntaxKind.Attribute. The attribute names some other file in the project.

For example, the code being analyzed may include

[RelatedFile("otherFileName.foo")] interface Whatever {...}

In my analysis callback, I want to be able to access the contents of the related file, from the perspective of the project being analyzed. So, I need to:

  1. Extract the file name from the SyntaxNode. I can do this.
  2. Get an object describing the document containing the code being analyzed. I don't know how to do this.
  3. Get an object describing the project containing the code being analyzed. I don't know how to do this.
  4. Find out if the project contains a document by the specified name. I can do this.
  5. Open and parse or update the contents of that file. I think I can do this.

I get stuck on steps (2) and (3). (Yes, I may not strictly need to do step 2, but I'd still like to know how.)

From the SyntaxNodeAnalysisContext parameter, I can get the Workspace object, and from that the Solution object, and from that a collection of Project objects. But I don't see a way to relate the particular SyntaxNode back to the Project or Document from which it came.

Any ideas about how to do this would be appreciated.

Jim Lyon
  • 21
  • 4

1 Answers1

0

I have found it:

Workspace workspace = ...;
SyntaxNode node = ...;
Document document = workspace.Solution.GetDocument(node.SyntaxTree);
Project project = document.Project;

I don't know why I didn't see that earlier. Edit: I now know why I didn't see it earlier. Getting ahold of the Workspace requires using a non-public property of AnalyzerOptions.

You can get the Workspace from a SyntaxNodeAnalysisContext via...

SyntaxNodeAnalysisContext context = ...;
AnalyzerOptions options = context.Options;
Workspace workspace = (Workspace)
    (options.GetType().GetRuntimeProperty("Workspace").GetValue(options));

It's not pretty, but it works. I wish there were a better way.

Jim Lyon
  • 21
  • 4
  • Jim, could you explain how you get the Workspace from the SyntaxNodeAnalysisContext? – Phil Jollans May 29 '20 at 21:03
  • Thanks Jim. I don't know if it is a better way, but you can also get the workspace [as described by Josh Varty](https://joshvarty.com/2014/09/12/learn-roslyn-now-part-6-working-with-workspaces/). If you are not in a VSPackage, you can call GetService using the ServiceProvider.GlobalProvider in Microsoft.VisualStudio.Shell. This might require references which you strictly should not use in a code analysis. In a code fix (but not a code analysis) you can import the workspace as an MEF component. – Phil Jollans May 31 '20 at 08:01