Support for unimported types in Omnisharp and C# Extension for VS Code

· 581 words · 3 minutes to read

Some time ago I blogged about new Omnisharp features - support for analyzers and support for Editorconfig. Those were at the time two of the most requested features on Github that we had. Today I wanted to let you know that we just shipped another one of those hugely requested functionalities - support for unimported types. In fact, since those previous two have been dealt with, this was the most requested feature that we had.

Some background 🔗

Support for unimported types means that types and extension methods that belong to namespaces that are not imported into the current document, still show up in intellisense, typically with lower sort order to avoid congestion of the autocomplete list. This functionality has been available in Visual Studio for a while - first made popular by Resharper and later on as integral part of VS itself. It is one of the great productivity boosts for many C# developers, as it effectively means that you do not need to worry about namespace importing any more - at all.

The feature has been made possible thanks to Omnisharp finally fully embracing the Roslyn Completion Service - so far it was only partially in use. This allows for a ton of other improvements to be made, which I will describe in separate blog posts.

The new completion service is available in Omnisharp as a new endpoint /completion, so any editor integrating an OmniSharp server interested in using it will have to switch to that model instead of the existing /autcomplete. The main difference between the old and the new endpoints is that there is now an extra request /completion/resolve which is made once a completion item is selected from the completion list. This was not the case for the old /autocomplete feature but is in-line with the LSP approach too. Resolving completion items separately is critical for performance and allows us to expand a single item into a complex multi-line edit. That is actually the case to unimported types, where showing the items in the list is one thing, but once you as a user selects it, you expect the editor to insert not just the completion text, but also the relevant using statement. And it is precisely this extra resolve requests that ends up fetching this document-level changeset.

I started working on this feature long time ago, but ran into some complications that I never managed to resolve. Thankfully, the feature was picked up and entirely implemented by Fred from the Roslyn team, whose did amazing work to make it all happen, including some workarounds we had to make because of the different text edit models between VS and VS Code.

Using it 🔗

The new completion endpoints shipped in OmniSharp 1.37.0 in mid-August, however at that point there was still no support for unimported types - this required additional work that ultimately was released in OmniSharp 1.37.1 on September 1.

On the C# extension for VS Code side, it was integrated in version 1.23.2 which was released to the extension marketplace on September 3.

The feature is disabled by default. You can enable it using OmniSharp configuration model, such as omnisharp.json:

{
"RoslynExtensionsOptions": {
"enableImportCompletion": true
}
}


There is a separate VS Code setting, that you can configure in VS Code directly, if you’d prefer that:

"omnisharp.enableImportCompletion": true


As you can see on the screengrab below, once enabled, completions for unimported namespaces - in this case ClaimsPrincipal from System.Security.Claims - is now offered:

<p>
Enjoy!
</p>