3

When you hover over a "simplified" using directive in VS2015, it shows you the fully-qualified name. How would I get this information via a Roslyn plugin? Would it be using a DiagnosticAnalyzer? A CodeFixProvider?

Reading through source.roslyn.codeplex.com, there's tons of information there, including how to add a using statement, and also how to simplify type names (including using statements), but I'm unable to figure out how to go in reverse to get the fully-qualified name.

Jedidja
  • 16,610
  • 17
  • 73
  • 112
  • 3
    I assume you'll have to use the semanticmodel to retrieve the type it refers to and then find out it's fully qualified name using `.ToDisplayString()`. – Jeroen Vannevel Apr 04 '16 at 16:26
  • @JeroenVannevel: you should write that as an answer. ;-) – Jason Malinowski Apr 04 '16 at 17:26
  • @JasonMalinowski I was preoccupied but I've added one now ;-) Perhaps you can clarify what `SymbolDisplayFormat` should be used? I didn't expect `SymbolDisplayFormat.FullyQualifiedFormat` to include the `global::` prefix – Jeroen Vannevel Apr 04 '16 at 17:33

1 Answers1

6

With the semantic model you can retrieve information about the semantics that make up your code (evidently) -- this allows you to get specific information about types and other constructs.

For example:

void Main()
{
    var tree = CSharpSyntaxTree.ParseText(@"
using X = System.Text;
using Y = System;
using System.IO;

namespace ConsoleApplication1
{
}"
);

    var mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location);
    var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { mscorlib });
    var semanticModel = compilation.GetSemanticModel(tree);
    var root = tree.GetRoot();

    // Get usings
    foreach (var usingDirective in root.DescendantNodes().OfType<UsingDirectiveSyntax>())
    {
        var symbol = semanticModel.GetSymbolInfo(usingDirective.Name).Symbol;
        var name = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
        name.Dump();
    }
}

Output:

global::System.Text
global::System
global::System.IO

If you use SymbolDisplayFormat.CSharpErrorMessageFormat instead, you will receive

System.Text
System
System.IO

Your choice what you're interested in but as you can see it works just fine with aliases and without.

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
  • I should have included my sample code; got to the point of `root.DescendantNodes().OfType()` and then couldn't figure out what to do with the node after. I tried `.Name` and casting it to `QualifiedNameSyntax` and then got totally lost. – Jedidja Apr 04 '16 at 18:21
  • The sample `DiagnosticAnalyzer` I was working with didn't include the semantic model, so I had started looking into `CodeFixProvider` instead. – Jedidja Apr 04 '16 at 18:23
  • 2
    I suggest you read through Josh Varty's excellent walkthroughs on these concepts -- they will clarify what is what exactly. https://joshvarty.wordpress.com/learn-roslyn-now/ – Jeroen Vannevel Apr 04 '16 at 18:25