Making completion API public again?

Topics: APIs
Apr 8, 2014 at 1:00 PM
The new Roslyn version sadly lacks an extensibility feature that had already been included in the previous CTP, namely the ability to extend the Visual Studio completion system (e.g. via the ICompletionProvider interface).

Will you be opening the corresponding namespaces/API again anytime soon? I know that you can extend the completion system via the interfaces that are provided in the VS SDK but Roslyns interfaces are IMHO already much nicer and using them directly would reduce some friction.
Apr 8, 2014 at 2:53 PM
I believe that's in the Visual Studio tooling and not the compiler itself.
Apr 8, 2014 at 5:07 PM
AFAIK: yes and no. This is not part of the compiler-core itself. But like I said the last CTP actually exposed such an API already (which as far as I can tell is an Adapter between Roslyn and the corresponding Visual Studio point of extension) but they decided to move that code into internal assemblies of the Roslyn End-User-Preview. Thus I would like to know if/when we can expect their public reappearance.
Apr 9, 2014 at 6:48 AM
Was it possible with the CTP to consume the ICompletionProvider functionality into a non-Visual Studio IDE?

I ask this because I wanted to integrate the capability into the open source CodeMirror which is a HTML5/Javascript code editor.

At the moment I don't know if this is possible or if I will be forced to look at something like SharpDevelop and NRefactory to provide a suitable auto-completion back end.

My requirements (level of integration) are too complex to simply use the new VS Online.
Apr 9, 2014 at 9:49 AM
Don't know for the CTP. In the current preview the Microsoft.Codeanalysis.Features assembly (which includes ICompletionProvider amongst others) contains no direct references to Visual Sudio as far as I can see. Thus the interfaces provided there seem to be theoretically suitable to implement the features for an Open-Source-IDE. If they would be made public, that is.
Apr 9, 2014 at 10:08 AM
Apr 9, 2014 at 10:36 AM
You're welcome.

I don't think you can use Reflection for this. To register a CompletionProvider it needs to be annotated with the ExportCompletionProviderAttribute which is marked as internal. Since AFAIK attributes are stored in the assembly meta-data you can't add them at runtime. So the only solution would be to modify the compiled assembly which creates a new set of problems. Even if that worked it would not be permissible for usage in a real-world-project.
Apr 9, 2014 at 12:25 PM
I'm very interested in using Roslyn for C# code completion, too. Sadly, I haven't found a way to do it using its current version, either.
Hence, I'd also appreciate the Roslyn team to open up that particular featureset, too. But I'm afraid blocking access to this was probably an active decision by their team as it was possible (using the aforementioned reflection trick) in the 2010 preview version. So dear Roslyn team.. this featureset would be very welcome and would probably convince even more people that currently - still - have to use NRefactory to use Roslyn instead :-)
Apr 9, 2014 at 1:00 PM
Edited Apr 9, 2014 at 1:03 PM
Thanks for pointing out the internal Attribute Christian.

I don't know how much truth there is to this tweet:

http://inagist.com/all/451767013468565504/Next_version_of_NRefactory_will_be_based_on_Roslyn.

The tweeter has been heavily involved in the development of SharpDevelop and now works for Xamarin.

*Update - sounds like it is serious if you dig into the associated tweet conversation.
Apr 9, 2014 at 1:15 PM
A few days ago Kirill Osenkov replied to me in the Jabbr roslyn channel. He stated that he was not 100% sure but thinks that they want to design it right before it is ready for real world usage. This indicates they might be opening it up but of course says nothing about the timeframe.

In principle you can already use Roslyn for augmenting code completion and don't need to use NRefactory. The disadvantages (which would be the same for NRefactory) are:
1) The Roslyn APIs are nicer
2) You have to build a bridge between what's happening in the VS SDK classes (e.g. ITextSnapshot) and the Roslyn classes yourself instead of their implementation handling this.
3) You have the overhead of having two analysis-engines running in parallel, not sharing any information.

An alternative might be using ReSharper and writing a Plug-In for that for now.
Apr 17, 2014 at 11:00 AM
Edited Apr 17, 2014 at 11:33 AM
BogeyLab wrote:
I'm very interested in using Roslyn for C# code completion, too. Sadly, I haven't found a way to do it using its current version, either.
Actually this post is about extending code completion. If you just want to use code completion that should be possible.

The FAQ samples contain entries for completion and there is also Microsoft.CodeAnalysis.Recommendations.Recommender.GetRecommendedSymbolsAtPosition in Microsoft.CodeAnalysis.Workspaces.dll which I found by chance but seems to be helpful for completion purposes, too.
Coordinator
Apr 17, 2014 at 7:14 PM
Edited Apr 17, 2014 at 7:15 PM
There are a few aspects to this:
  1. The existing ICompletionService was too bound to the particular UI methodology that Visual Studio uses for completion, making it difficult to consume. We wanted to introduce an API that was closer to a "pure data" API, and that is the _Microsoft.CodeAnalysis.Recommendations.Recommender.GetRecommendedSymbolsAtPosition that @Zarat mentions above.
  2. The previous CTP had an extensibility mechanism to let people add custom items to completion. We would like to revisit making this public, but possibly with a simplified API. We also need to resolve this with the already existing extensibility mechanisms of the VS editor like ICompletionSourceProvider.
Which of the two scenarios are you most interested in? If it is determine what completion would show, is the API in 1. Sufficient?
Apr 17, 2014 at 8:14 PM
I am most interested in the second scenario: adding and transforming completion items but I see that there is an overlap with the already existing extensibility mechanisms.
Apr 17, 2014 at 11:02 PM
I am interested in both.

The first scenario is good for most situations - ie coding in C# or a scripting language that we create.

The second scenario is important for our MS-Access like RunSQL command and other similar database related queries. For RunSQL we want to source the list of Tables and Fields in a database and have those accessible via an intellisense-like control.

I haven't looked into it deeply enough, but perhaps Linq would turn our second scenario into a first scenario situation. My main concern then is whether our users (MS-Access developers) will be ok with it.
May 27, 2014 at 9:50 PM
Edited May 27, 2014 at 9:50 PM
Pilchie wrote:
Which of the two scenarios are you most interested in? If it is determine what completion would show, is the API in 1. Sufficient?
Having worked with the API a bit, case 1 (the Recommender API) is definitely not sufficient, I can't do much with the returned symbols without knowing which TextSpan the recommendation is meant for. I'd have to basically reimplement (more or less) what the Recommender does to figure out the TextSpan in the current model. I'd suggest to not just return symbols but a "Recommendation struct" which combines the symbol with the TextSpan for which it was recommended. (That TextSpan should then also be enough for anyone to drill into the syntax tree without having to reimplement the Recommender, in case he'd need any more information.)
May 29, 2014 at 10:45 PM
For me first scenario is a good start, however, with two important capabilities:
  • The ability to pass my own string to the recommender as well (or at least TextSpan that would cause it to not consider surrounding characters).
  • The ability to specify the context that the recommender should work in.
My use case would be refactoring providers that can work with incomplete text in the editor. For example, if I am asked for code actions on text t_CK I could check with the recommender if there is anything that would match CK that could go into typeof() construct and if I got single match back, I can offer an action to convert it into typeof(ConsoleKey) or whatever.