From 02dba8164661f6fd787269f3e0151620eb24ab87 Mon Sep 17 00:00:00 2001 From: Filip W Date: Fri, 31 Jul 2020 20:24:49 +0200 Subject: [PATCH] added support for EmbeddedLanguageCompletionProvider (#1871) * added support for EmbeddedLanguageCompletionProvider * added datetime completion tests * improved test * added regex test * changelog update * fixed name * removed flaky test --- CHANGELOG.md | 1 + .../Intellisense/CompletionItemExtensions.cs | 28 +++++++++++++++++++ .../Intellisense/IntellisenseService.cs | 15 ++-------- .../IntellisenseFacts.cs | 26 +++++++++++++++++ 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccb08add9e..9d4be60502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All changes to the project will be documented in this file. * Introduced a new `/quickinfo` endpoint to provide a richer set of information compared to `/typeinfo`. Consumers are encouraged to use it as their hover provider ([#1808](https://github.com/OmniSharp/omnisharp-roslyn/issues/1808), PR: [#1860](https://github.com/OmniSharp/omnisharp-roslyn/pull/1860)) * Fixed return type in LSP completion handler ([#1864](https://github.com/OmniSharp/omnisharp-roslyn/issues/1864), PR: [#1869](https://github.com/OmniSharp/omnisharp-roslyn/pull/1869)) * Upgraded to the latest version of the csharp-language-server-protocol [#1815](https://github.com/OmniSharp/omnisharp-roslyn/pull/1815) +* Added support for Roslyn `EmbeddedLanguageCompletionProvider` which enables completions for string literals for `DateTime` and `Regex` ([#1871](https://github.com/OmniSharp/omnisharp-roslyn/pull/1871)) ## [1.35.4] - 2020-07-22 * Update to Roslyn `3.8.0-1.20357.3` (PR: [#1849](https://github.com/OmniSharp/omnisharp-roslyn/pull/1849)) diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs index b9e11a146c..ed42561e01 100644 --- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs +++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Completion; +using OmniSharp.Models.AutoComplete; using OmniSharp.Utilities; namespace OmniSharp.Roslyn.CSharp.Services.Intellisense @@ -82,5 +83,32 @@ public static bool TryGetInsertionText(this CompletionItem completionItem, out s { return completionItem.Properties.TryGetValue(InsertionText, out insertionText); } + + public static AutoCompleteResponse ToAutoCompleteResponse(this CompletionItem item, bool wantKind, bool isSuggestionMode, bool preselect) + { + // for simple use cases we'll just assume that the completion text is the same as the display text + var response = new AutoCompleteResponse() + { + CompletionText = item.DisplayText, + DisplayText = item.DisplayText, + Snippet = item.DisplayText, + Kind = wantKind ? item.Tags.FirstOrDefault() : null, + IsSuggestionMode = isSuggestionMode, + Preselect = preselect + }; + + // if provider name is "Microsoft.CodeAnalysis.CSharp.Completion.Providers.EmbeddedLanguageCompletionProvider" + // we have access to more elaborate description + if (GetProviderName(item) == "Microsoft.CodeAnalysis.CSharp.Completion.Providers.EmbeddedLanguageCompletionProvider") + { + response.DisplayText = item.InlineDescription; + if (item.Properties.TryGetValue("DescriptionKey", out var description)) + { + response.Description = description; + } + } + + return response; + } } } diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs index c2beb1504b..b92bac7857 100644 --- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs +++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs @@ -99,19 +99,8 @@ public async Task> Handle(AutoCompleteRequest continue; } - // for other completions, i.e. keywords, create a simple AutoCompleteResponse - // we'll just assume that the completion text is the same - // as the display text. - var response = new AutoCompleteResponse() - { - CompletionText = item.DisplayText, - DisplayText = item.DisplayText, - Snippet = item.DisplayText, - Kind = request.WantKind ? item.Tags.First() : null, - IsSuggestionMode = isSuggestionMode, - Preselect = preselect - }; - + // for other completions, i.e. keywords or em, create a simple AutoCompleteResponse + var response = item.ToAutoCompleteResponse(request.WantKind, isSuggestionMode, preselect); completions.Add(response); } } diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs index 03e33471c2..d53baa0c6f 100644 --- a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs +++ b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs @@ -449,6 +449,32 @@ void M() Assert.True(completions.All(c => !c.IsSuggestionMode)); } + [Theory] + [InlineData("dummy.cs")] + [InlineData("dummy.csx")] + public async Task Embedded_language_completion_provider_for_datetime_format(string filename) + { + const string source = @" +using System; +class C +{ + void M() + { + var d = DateTime.Now.ToString(""$$"" + } +} +"; + + var completions = await FindCompletionsAsync(filename, source); + + Assert.NotEmpty(completions); + + var gStandardCompletion = completions.FirstOrDefault(x => x.CompletionText == "G"); + Assert.NotNull(gStandardCompletion); + Assert.Equal("general long date/time", gStandardCompletion.DisplayText); + Assert.Contains(@"The ""G"" standard format specifier", gStandardCompletion.Description); + } + [Fact] public async Task Scripting_by_default_returns_completions_for_CSharp7_1() {