diff --git a/src/OmniSharp.Abstractions/Models/v1/AutoComplete/AutoCompleteRequest.cs b/src/OmniSharp.Abstractions/Models/v1/AutoComplete/AutoCompleteRequest.cs index 607d3ced79..a63830d9b6 100644 --- a/src/OmniSharp.Abstractions/Models/v1/AutoComplete/AutoCompleteRequest.cs +++ b/src/OmniSharp.Abstractions/Models/v1/AutoComplete/AutoCompleteRequest.cs @@ -51,5 +51,7 @@ public string WordToComplete /// Returns the kind (i.e Method, Property, Field) /// public bool WantKind { get; set; } + + public string TriggerCharacter { get; set; } } } diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs index bddfe62cf3..8067cbf2a2 100644 --- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs +++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs @@ -14,6 +14,7 @@ internal static class CompletionItemExtensions { private const string GetSymbolsAsync = nameof(GetSymbolsAsync); private const string InsertionText = nameof(InsertionText); + private const string ObjectCreationCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.ObjectCreationCompletionProvider"; private const string NamedParameterCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.NamedParameterCompletionProvider"; private const string OverrideCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.OverrideCompletionProvider"; private const string ParitalMethodCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.PartialMethodCompletionProvider"; @@ -32,6 +33,12 @@ static CompletionItemExtensions() _getSymbolsAsync = symbolCompletionItemType.GetMethod(GetSymbolsAsync, BindingFlags.Public | BindingFlags.Static); } + public static bool IsObjectCreationCompletionItem(this CompletionItem item) + { + var properties = item.Properties; + return properties.TryGetValue(Provider, out var provider) && provider == ObjectCreationCompletionProvider; + } + public static async Task> GetCompletionSymbolsAsync(this CompletionItem completionItem, IEnumerable recommendedSymbols, Document document) { var properties = completionItem.Properties; diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs index aeb6ef5475..2214c8172e 100644 --- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs +++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs @@ -43,7 +43,13 @@ public async Task> Handle(AutoCompleteRequest if (completionList != null) { - // get recommened symbols to match them up later with SymbolCompletionProvider + // Only trigger on space if Roslyn has object creation items + if (request.TriggerCharacter == " " && !completionList.Items.Any(i => i.IsObjectCreationCompletionItem())) + { + return completions; + } + + // get recommended symbols to match them up later with SymbolCompletionProvider var semanticModel = await document.GetSemanticModelAsync(); var recommendedSymbols = await Recommender.GetRecommendedSymbolsAtPositionAsync(semanticModel, position, _workspace); diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/AbstractAutoCompleteTestFixture.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/AbstractAutoCompleteTestFixture.cs index 16b59c9afc..62dfc5baf9 100644 --- a/tests/OmniSharp.Roslyn.CSharp.Tests/AbstractAutoCompleteTestFixture.cs +++ b/tests/OmniSharp.Roslyn.CSharp.Tests/AbstractAutoCompleteTestFixture.cs @@ -16,7 +16,7 @@ protected AbstractAutoCompleteTestFixture(ITestOutputHelper output) protected override string EndpointName => OmniSharpEndpoints.AutoComplete; - protected async Task> FindCompletionsAsync(string filename, string source, bool wantSnippet = false) + protected async Task> FindCompletionsAsync(string filename, string source, bool wantSnippet = false, string triggerChar = null) { var testFile = new TestFile(filename, source); using (var host = CreateOmniSharpHost(testFile)) @@ -32,7 +32,8 @@ protected async Task> FindCompletionsAsync(str WordToComplete = GetPartialWord(testFile.Content), WantMethodHeader = true, WantSnippet = wantSnippet, - WantReturnType = true + WantReturnType = true, + TriggerCharacter = triggerChar }; var requestHandler = GetRequestHandler(host); diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs index 0919402e57..13271dfb9f 100644 --- a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs +++ b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs @@ -454,5 +454,39 @@ private void ContainsCompletions(IEnumerable completions, params string[ Assert.Equal(expected, completions.ToArray()); } + + [Theory] + [InlineData("dummy.cs")] + [InlineData("dummy.csx")] + public async Task TriggeredOnSpaceForObjectCreation(string filename) + { + const string input = +@"public class Class1 { + public M() + { + Class1 c = new $$ + } +}"; + + var completions = await FindCompletionsAsync(filename, input, wantSnippet: true, triggerChar: " "); + Assert.NotEmpty(completions); + } + + [Theory] + [InlineData("dummy.cs")] + [InlineData("dummy.csx")] + public async Task NotTriggeredOnSpaceWithoutObjectCreation(string filename) + { + const string input = +@"public class Class1 { + public M() + { + $$ + } +}"; + + var completions = await FindCompletionsAsync(filename, input, wantSnippet: true, triggerChar: " "); + Assert.Empty(completions); + } } }