visual-studioroslynvisual-studio-extensionsvsixvssdk

How to get information about word under mouse position in code editor in visual studio extension


I'm trying to learn how to create visual studio extensions by playing around a little bit.
I would like to get all information about word under the mouse in code editor(c#) but I can't figure out how to do it. I don't want to analyze code by myself, because there has to be mechanism for this, because all those information are for example in tooltips(maybe it will be enough to capture tooltip data).
To make this clearer:
-If you hover over variable I would like to know that this word is a variable also I would like the name of this variable and type. The same for any other type, interface etc.
-If you hover over 'var' keyword I would like to know that this word is 'var' keyword and I would like to know type of it.
-If You hover over class inside generic like 'List[Domain.Example.TestClass]' I would like to get type which will be equal to 'TestClass'
Basically the same what is in tooltips.

I was trying to use 'IQuickInfoSource' and it allow me to get word under cursor, however I don't know how to get any additional data.
I also tried 'IMouseProcessorProvider' and I ended up with the same result, I was able to get current word but any other info.

Could You tell me how to achieve this? Or at least point me in the right direction, because it is quite difficult to find any proper documentation about visual studio extensions. If You need any more info please ask.

Thanks in advance.


Solution

  • after many hours I was able to achieve what I wanted. If someone will be trying to do the same then you can find steps below.

    I'm using 'Roslyn' to get those information, so I needed to download nuget packages like 'Microsoft.CodeAnalysis' etc.

    I also used IMouseProcessorProvider to be able to react for mouse events:

    [Export(typeof(IMouseProcessorProvider))]
    [Order]
    [ContentType("CSharp")]
    [Name("MouseNavigation")]
    [TextViewRole(PredefinedTextViewRoles.Interactive)]
    internal class MouseNavigationProvider : IMouseProcessorProvider
    

    After that using following code, I was able to get type information

    SnapshotPoint caretPosition = _textView.Caret.Position.BufferPosition;
    Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
    SemanticModel semanticModel = document.GetSemanticModelAsync().Result;
    if (semanticModel == null)
       return null;
    
    TypeInfo typeInfo;
    SyntaxNode expressionNode = document.GetSyntaxRootAsync().Result.FindToken(caretPosition).Parent;
    if (expressionNode is VariableDeclaratorSyntax)
    {
        SyntaxNode childNode = expressionNode.ChildNodes()?.FirstOrDefault()
             ?.ChildNodes()?.FirstOrDefault();
        typeInfo = semanticModel.GetTypeInfo(childNode);
    }
    else if (expressionNode is ClassDeclarationSyntax)
    {
        throw new NotImplementedException();
    }
    else
    {
       // NOTE: This probably should be changed for specific type of syntax, but right now it is only for testing purposes
       typeInfo = semanticModel.GetTypeInfo(expressionNode);
       if (typeInfo.Type == null)
       {
            expressionNode = expressionNode.Parent;
            typeInfo = semanticModel.GetTypeInfo(expressionNode);
       }
    }