Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include keywords and aliases in Roslyn recommended symbols?

I am using Roslyn to create a C# scripting control with IntelliSense.

I am generally very happy with the results I am getting, however, the recommended symbols don't include keywords such as for and if et cetera and also don't contain type aliases such as int, when it includes Int32.

More specifically, I am using Microsoft.CodeAnalysis.Recommendations, that is:

Recommender.GetRecommendedSymbolsAtPositionAsync(mySemanticModel, scriptPosition, myAdhocWorkspace);

My SemanticModel object is obtained from a C# compilation which always has a reference to mscorlib.dll at the very least.

At all positions in my script, the recommended completions are always correct. However, I would argue that they are incomplete if they are missing keywords such as if, else and for etc.

I can see that it would be easy for me to include common type aliases in my IntelliSense manually. That is, if Int32 is a possible completion, then I could manually add int.

However, it is less obvious when an if statement or a for statement or even is/as would be appropriate in the given scope.

Is there a way to include these keywords when getting the recommended symbols this way?

Is there also a way to automatically include type aliases?

like image 499
rbren Avatar asked Oct 16 '22 07:10

rbren


1 Answers

It seems that Recommender.GetRecommendedSymbolsAtPositionAsync provides only symbols completion. That mean, Methods, Types etc (ISymbol implementations).

If you want keywords or snippets completion, you can use Microsoft.CodeAnalysis.Completion.CompletionService

void CompletionExample()
{
    var code = @"using System;

namespace NewConsoleApp
{
class NewClass
{
    void Method()
    {
fo // I want to get 'for' completion for this
    }
}
}";

    var completionIndex = code.LastIndexOf("fo") + 2;
    // Assume you have a method that create a workspace for you
    var workspace = CreateWorkspace("newSln", "newProj", code);
    var doc = workspace.CurrentSolution.Projects.First().Documents.First();

    var service = CompletionService.GetService(doc);
    var completionItems = service.GetCompletionsAsync(doc, completionIndex).Result.Items;

    foreach (var result in completionItems)
    {
        Console.WriteLine(result.DisplayText);
        Console.WriteLine(string.Join(",", result.Tags));
        Console.WriteLine();
    }
}

You can play around to figure it out how to customize it for your needs (rules, filters).

Notice that each result comes from a specific completion provider (item.Properties["Provider"]) and you can create a custom CompletionProvider (at least you should be able).

You can also take a look at C# for VS code (that powered with OmniSharp) to see how they did the work.

like image 71
Dudi Keleti Avatar answered Oct 19 '22 23:10

Dudi Keleti