Question

I'd like to get started with code completion in Roslyn but could not find any simple examples that show how to do code completion.

What would be a good example to finish this code so that I can obtain all possible completion items (AKA Intellisense or CTRL+Space completion) at the caretIndex?

static void Main(string[] args)
{
    var code = @"
    using System;
    public class Test
    {
        public void TestMethod()
        {
            var now = DateTime.Now;
            now.
        }
    }";
    Console.WriteLine(code);

    var st = SyntaxTree.ParseText(code);
    var caretIndex = code.IndexOf("now.") + 4;

    //how to get possible code completions at caret index? (Intellisense)
}
Was it helpful?

Solution

Roslyn does provide code completion services through the ICompletionService and ICompletionProvider interfaces, but they seem to mostly be internal and meant to be accessed when hosted within Visual Studio. However, it is possible to get a hold of the C# code completion types using a couple of reflection hacks, as illustrated by the ScriptCS Pad project. If you can get this to work, I expect you should get VS-grade code completion.

Alternatively, you can do it "by hand", using the public APIs provided by Roslyn. I am not well-versed in them, but the following should get you started in listing the members of the expression to the left of the member access dot. Note that it ignores extension methods and visibility rules, does no error handling and is probably flawed in many other ways. Doing this reliably probably doesn't qualify as "simple" code completion, though.

var code = @"
    using System;
    public class Test
    {
        public void TestMethod()
        {
            var now = DateTime.Now;
            now.
        }
    }";
Console.WriteLine(code);

var syntaxTree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create("foo")
    .AddReferences(MetadataReference.CreateAssemblyReference(typeof(DateTime).Assembly.FullName))
    .AddSyntaxTrees(syntaxTree);
var semanticModel = compilation.GetSemanticModel(syntaxTree);

var dotTextSpan = new TextSpan(code.IndexOf("now.") + 3, 1);
var memberAccessNode = (MemberAccessExpressionSyntax)syntaxTree.GetRoot().DescendantNodes(dotTextSpan).Last();

var lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;

foreach (var symbol in lhsType.GetMembers())
{
    if (!symbol.CanBeReferencedByName
        || symbol.DeclaredAccessibility != Accessibility.Public
        || symbol.IsStatic)
        continue;

    Console.WriteLine(symbol.Name);
}

EDIT: Note that this answer was probably made obsolete by the new Roslyn bits.

OTHER TIPS

Provided you have a Workspace instance, you can use public recommendation API from Microsoft.CodeAnalysys.Workspaces package:

public static class Recommender
{
     public static IEnumerable<ISymbol> GetRecommendedSymbolsAtPosition(SemanticModel semanticModel, int position, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default(CancellationToken));
}

It returns completion symbols at given offset. It does not return keywords, but as of march 2016 Roslyn guys are working on better public api for completion: https://github.com/dotnet/roslyn/issues/3538

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top