diff --git a/src/Features/Core/Portable/Completion/CompletionTrigger.cs b/src/Features/Core/Portable/Completion/CompletionTrigger.cs
index 32767786e4f07d1655afb0440607c3847af65a4f..17a7081e979931c8c5f607e601b4c76bcc8d8bcf 100644
--- a/src/Features/Core/Portable/Completion/CompletionTrigger.cs
+++ b/src/Features/Core/Portable/Completion/CompletionTrigger.cs
@@ -6,16 +6,6 @@
namespace Microsoft.CodeAnalysis.Completion
{
- ///
- /// The action that triggered completion to start.
- ///
- ///
- /// NOTE: Roslyn's LSP completion implementation uses this struct. If a new property is added, either:
- /// 1: The property's type must be serializable
- /// OR
- /// 2. LSP will need to be updated to not use CompletionTrigger - see
- /// Features\LanguageServer\Protocol\Handler\Completion\CompletionResolveData.cs
- ///
public readonly struct CompletionTrigger
{
///
diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs
index 38971be338884039ff3eb0db30c3f7ff885ece83..e8532651f709f6022a60a63fc3d04722a2785660 100644
--- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs
+++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs
@@ -10,9 +10,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.DocumentHighlighting;
-using Microsoft.CodeAnalysis.Elfie.Diagnostics;
using Microsoft.CodeAnalysis.Host;
-using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.NavigateTo;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
@@ -20,7 +18,6 @@
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
-using Logger = Microsoft.CodeAnalysis.Internal.Log.Logger;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer
@@ -68,23 +65,6 @@ internal static class ProtocolConversions
{ WellKnownTags.NuGet, LSP.CompletionItemKind.Text }
};
- // TO-DO: More LSP.CompletionTriggerKind mappings are required to properly map to Roslyn CompletionTriggerKinds.
- // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1178726
- public static Completion.CompletionTriggerKind LSPToRoslynCompletionTriggerKind(LSP.CompletionTriggerKind triggerKind)
- {
- switch (triggerKind)
- {
- case LSP.CompletionTriggerKind.Invoked:
- return Completion.CompletionTriggerKind.Invoke;
- case LSP.CompletionTriggerKind.TriggerCharacter:
- return Completion.CompletionTriggerKind.Insertion;
- default:
- // LSP added a TriggerKind that we need to support.
- Logger.Log(FunctionId.LSPCompletion_MissingLSPCompletionTriggerKind);
- return Completion.CompletionTriggerKind.Invoke;
- }
- }
-
public static Uri GetUriFromFilePath(string? filePath)
{
if (filePath is null)
diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs
index 394c24b5fb2cdadba6701cbbd06217f82dd0ae3c..69d24aaf6bb4751486dae27a1fdadae883b9ea85 100644
--- a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs
@@ -5,19 +5,16 @@
#nullable enable
using System;
-using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
-using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Host.Mef;
-using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.VisualStudio.Text.Adornments;
-using Roslyn.Utilities;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
@@ -27,40 +24,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
///
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentCompletionName)]
- internal class CompletionHandler : AbstractRequestHandler
+ internal class CompletionHandler : AbstractRequestHandler
{
- private readonly ImmutableHashSet _csTriggerCharacters;
- private readonly ImmutableHashSet _vbTriggerCharacters;
-
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
- public CompletionHandler(
- ILspSolutionProvider solutionProvider,
- [ImportMany] IEnumerable> completionProviders)
- : base(solutionProvider)
+ public CompletionHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
- _csTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.CSharp).SelectMany(
- lz => GetTriggerCharacters(lz.Value)).Select(c => c.ToString()).ToImmutableHashSet();
- _vbTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.VisualBasic).SelectMany(
- lz => GetTriggerCharacters(lz.Value)).Select(c => c.ToString()).ToImmutableHashSet();
}
- public override async Task HandleRequestAsync(LSP.CompletionParams request, RequestContext context, CancellationToken cancellationToken)
+ public override async Task HandleRequestAsync(LSP.CompletionParams request, RequestContext context, CancellationToken cancellationToken)
{
var document = SolutionProvider.GetDocument(request.TextDocument, context.ClientName);
if (document == null)
{
- return Array.Empty();
- }
-
- // C# and VB share the same LSP language server, and thus share the same default trigger characters.
- // We need to ensure the trigger character is valid in the document's language. For example, the '{'
- // character, while a trigger character in VB, is not a trigger character in C#.
- var triggerCharacter = char.Parse(request.Context.TriggerCharacter);
- if (request.Context.TriggerKind == LSP.CompletionTriggerKind.TriggerCharacter && !char.IsLetterOrDigit(triggerCharacter) &&
- !IsValidTriggerCharacterForDocument(document, request.Context.TriggerCharacter))
- {
- return Array.Empty();
+ return null;
}
var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);
@@ -81,124 +58,48 @@ public override async Task HandleRequestAsync(LSP.Completi
.WithChangedOption(CompletionServiceOptions.DisallowAddingImports, true);
var completionService = document.Project.LanguageServices.GetRequiredService();
-
- // TO-DO: More LSP.CompletionTriggerKind mappings are required to properly map to Roslyn CompletionTriggerKinds.
- // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1178726
- var triggerKind = ProtocolConversions.LSPToRoslynCompletionTriggerKind(request.Context.TriggerKind);
- var completionTrigger = new CompletionTrigger(triggerKind, triggerCharacter);
-
- var list = await completionService.GetCompletionsAsync(document, position, completionTrigger, options: completionOptions, cancellationToken: cancellationToken).ConfigureAwait(false);
+ var list = await completionService.GetCompletionsAsync(document, position, options: completionOptions, cancellationToken: cancellationToken).ConfigureAwait(false);
if (list == null)
{
- return Array.Empty();
+ return null;
}
var lspVSClientCapability = context.ClientCapabilities?.HasVisualStudioLspCapability() == true;
- return list.Items.Select(item => CreateLSPCompletionItem(request, item, lspVSClientCapability, completionTrigger)).ToArray();
-
- // Local functions
- bool IsValidTriggerCharacterForDocument(Document document, string triggerCharacter)
+ return new LSP.VSCompletionList
{
- if (document.Project.Language == LanguageNames.CSharp)
- {
- return _csTriggerCharacters.Contains(triggerCharacter);
- }
- else if (document.Project.Language == LanguageNames.VisualBasic)
- {
- return _vbTriggerCharacters.Contains(triggerCharacter);
- }
-
- return true;
- }
+ Items = list.Items.Select(item => CreateLSPCompletionItem(request, item, lspVSClientCapability)).ToArray(),
+ SuggesstionMode = list.SuggestionModeItem != null,
+ };
- static LSP.CompletionItem CreateLSPCompletionItem(
- LSP.CompletionParams request,
- CompletionItem item,
- bool useVSCompletionItem,
- CompletionTrigger completionTrigger)
+ // local functions
+ static LSP.CompletionItem CreateLSPCompletionItem(LSP.CompletionParams request, CompletionItem item, bool useVSCompletionItem)
{
if (useVSCompletionItem)
{
- var vsCompletionItem = CreateCompletionItem(request, item, completionTrigger);
+ var vsCompletionItem = CreateCompletionItem(request, item);
vsCompletionItem.Icon = new ImageElement(item.Tags.GetFirstGlyph().GetImageId());
return vsCompletionItem;
}
else
{
- var roslynCompletionItem = CreateCompletionItem(request, item, completionTrigger);
+ var roslynCompletionItem = CreateCompletionItem(request, item);
+ roslynCompletionItem.Tags = item.Tags.ToArray();
return roslynCompletionItem;
}
}
- static TCompletionItem CreateCompletionItem(
- LSP.CompletionParams request,
- CompletionItem item,
- CompletionTrigger completionTrigger) where TCompletionItem : LSP.CompletionItem, new()
- {
- var completeDisplayText = item.DisplayTextPrefix + item.DisplayText + item.DisplayTextSuffix;
- var completionItem = new TCompletionItem
+ static TCompletionItem CreateCompletionItem(LSP.CompletionParams request, CompletionItem item) where TCompletionItem : LSP.CompletionItem, new()
+ => new TCompletionItem
{
- Label = completeDisplayText,
- InsertText = item.Properties.ContainsKey("InsertionText") ? item.Properties["InsertionText"] : completeDisplayText,
+ Label = item.DisplayTextPrefix + item.DisplayText + item.DisplayTextSuffix,
+ InsertText = item.Properties.ContainsKey("InsertionText") ? item.Properties["InsertionText"] : item.DisplayText,
SortText = item.SortText,
FilterText = item.FilterText,
Kind = GetCompletionKind(item.Tags),
- Data = new CompletionResolveData
- {
- TextDocument = request.TextDocument,
- Position = request.Position,
- DisplayText = item.DisplayText,
- CompletionTrigger = completionTrigger,
- },
+ Data = new CompletionResolveData { TextDocument = request.TextDocument, Position = request.Position, DisplayText = item.DisplayText },
Preselect = item.Rules.SelectionBehavior == CompletionItemSelectionBehavior.HardSelection,
- CommitCharacters = GetCommitCharacters(item)
};
-
- return completionItem;
- }
-
- static string[]? GetCommitCharacters(CompletionItem item)
- {
- var commitCharacterRules = item.Rules.CommitCharacterRules;
-
- // If the item doesn't have any special rules, just use the default commit characters.
- if (commitCharacterRules.IsEmpty)
- {
- return null;
- }
-
- using var _ = PooledHashSet.GetInstance(out var commitCharacters);
- commitCharacters.AddAll(CompletionRules.Default.DefaultCommitCharacters);
- foreach (var rule in commitCharacterRules)
- {
- switch (rule.Kind)
- {
- case CharacterSetModificationKind.Add:
- commitCharacters.UnionWith(rule.Characters);
- continue;
- case CharacterSetModificationKind.Remove:
- commitCharacters.ExceptWith(rule.Characters);
- continue;
- case CharacterSetModificationKind.Replace:
- commitCharacters.Clear();
- commitCharacters.AddRange(rule.Characters);
- break;
- }
- }
-
- return commitCharacters.Select(c => c.ToString()).ToArray();
- }
- }
-
- internal static ImmutableHashSet GetTriggerCharacters(CompletionProvider provider)
- {
- if (provider is LSPCompletionProvider lspProvider)
- {
- return lspProvider.TriggerCharacters;
- }
-
- return ImmutableHashSet.Empty;
}
private static LSP.CompletionItemKind GetCompletionKind(ImmutableArray tags)
diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveData.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveData.cs
index a79180caee0a36166a855fa46a14b25ab4231e08..7997711abfe27eb9e397e9f4bc9a5f5e7baf853b 100644
--- a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveData.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveData.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.CodeAnalysis.Completion;
using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
@@ -14,7 +13,5 @@ internal class CompletionResolveData
public Position Position { get; set; }
public string DisplayText { get; set; }
-
- public CompletionTrigger CompletionTrigger { get; set; }
}
}
diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveHandler.cs
index bc8a082d41e0c65d8a45eef2929eda426f28def7..ebcdb9b4e95bad4d0f934471fae830883cd3428f 100644
--- a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveHandler.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionResolveHandler.cs
@@ -52,7 +52,7 @@ public override async Task HandleRequestAsync(LSP.Completion
var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(data.Position), cancellationToken).ConfigureAwait(false);
var completionService = document.Project.LanguageServices.GetRequiredService();
- var list = await completionService.GetCompletionsAsync(document, position, data.CompletionTrigger, cancellationToken: cancellationToken).ConfigureAwait(false);
+ var list = await completionService.GetCompletionsAsync(document, position, cancellationToken: cancellationToken).ConfigureAwait(false);
if (list == null)
{
return completionItem;
diff --git a/src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs
index d1691859ac8bf56b2d67d4d89abf21892a6c3a03..3378e965e058e0ae6eed3631af5d0e44a7ea6372 100644
--- a/src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs
@@ -36,9 +36,7 @@ public InitializeHandler([ImportMany] IEnumerable HandleRequestAsync(LSP.InitializeParams request, RequestContext context, CancellationToken cancellationToken)
{
- var commitCharacters = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray();
- var triggerCharacters = _completionProviders.SelectMany(
- lz => CompletionHandler.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray();
+ var triggerCharacters = _completionProviders.SelectMany(lz => GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray();
return Task.FromResult(new LSP.InitializeResult
{
@@ -49,12 +47,7 @@ public Task HandleRequestAsync(LSP.InitializeParams reques
ImplementationProvider = true,
CodeActionProvider = new LSP.CodeActionOptions { CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor } },
CodeActionsResolveProvider = true,
- CompletionProvider = new LSP.CompletionOptions
- {
- ResolveProvider = true,
- AllCommitCharacters = commitCharacters,
- TriggerCharacters = triggerCharacters
- },
+ CompletionProvider = new LSP.CompletionOptions { ResolveProvider = true, TriggerCharacters = triggerCharacters },
SignatureHelpProvider = new LSP.SignatureHelpOptions { TriggerCharacters = new[] { "(", "," } },
DocumentSymbolProvider = true,
WorkspaceSymbolProvider = true,
@@ -73,5 +66,15 @@ public Task HandleRequestAsync(LSP.InitializeParams reques
}
});
}
+
+ private static ImmutableHashSet GetTriggerCharacters(CompletionProvider provider)
+ {
+ if (provider is LSPCompletionProvider lspProvider)
+ {
+ return lspProvider.TriggerCharacters;
+ }
+
+ return ImmutableHashSet.Empty;
+ }
}
}
diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs
index a496790da34f6879dc555462ce8d4dc475f28700..8ef1086ef53b1ec36b42f6e4d0d617e44e0c6c9d 100644
--- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs
+++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs
@@ -28,19 +28,13 @@ void M()
using var workspace = CreateTestWorkspace(markup, out var locations);
var tags = new string[] { "Class", "Internal" };
var completionParams = CreateCompletionParams(locations["caret"].Single(), "\0", LSP.CompletionTriggerKind.Invoked);
- var commitCharacters = new string[]
- {
- " ", "{", "}", "[", "]", "(", ")", ".", ",", ":",
- ";", "+", "-", "*", "/", "%", "&", "|", "^", "!",
- "~", "=", "<", ">", "?", "@", "#", "'", "\"", "\\"
- };
var completionItem = CreateCompletionItem
- ("A", LSP.CompletionItemKind.Class, tags, completionParams, commitCharacters: commitCharacters);
+ ("A", LSP.CompletionItemKind.Class, tags, completionParams);
var description = new ClassifiedTextElement(CreateClassifiedTextRunForClass("A"));
var clientCapabilities = new LSP.VSClientCapabilities { SupportsVisualStudioExtensions = true };
var expected = CreateResolvedCompletionItem(
- "A", LSP.CompletionItemKind.Class, null, completionParams, description, "class A", null, commitCharacters);
+ "A", LSP.CompletionItemKind.Class, null, completionParams, description, "class A", null);
var results = (LSP.VSCompletionItem)await RunResolveCompletionItemAsync(workspace.CurrentSolution, completionItem, clientCapabilities);
AssertJsonEquals(expected, results);
diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
index c22ffe877d25fa1792fc1fdf085f2462b55946f9..c4d6fea23df89cbf289bfbd3b8c5598f5993e23f 100644
--- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
+++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs
@@ -28,16 +28,10 @@ void M()
using var workspace = CreateTestWorkspace(markup, out var locations);
var completionParams = CreateCompletionParams(
locations["caret"].Single(), triggerCharacter: "\0", triggerKind: LSP.CompletionTriggerKind.Invoked);
- var expected = CreateCompletionItem("A", LSP.CompletionItemKind.Class, new string[] { "Class", "Internal" },
- completionParams, commitCharacters: new string[]
- {
- " ", "{", "}", "[", "]", "(", ")", ".", ",", ":",
- ";", "+", "-", "*", "/", "%", "&", "|", "^", "!",
- "~", "=", "<", ">", "?", "@", "#", "'", "\"", "\\"
- });
+ var expected = CreateCompletionItem("A", LSP.CompletionItemKind.Class, new string[] { "Class", "Internal" }, completionParams);
var results = await RunGetCompletionsAsync(workspace.CurrentSolution, completionParams).ConfigureAwait(false);
- AssertJsonEquals(expected, results.First());
+ AssertJsonEquals(expected, results.Items.First());
}
[Fact]
@@ -62,7 +56,7 @@ void M()
var completionParams = CreateCompletionParams(locations["caret"].Single(), triggerCharacter: "\0", LSP.CompletionTriggerKind.Invoked);
var results = await RunGetCompletionsAsync(solution, completionParams);
- Assert.False(results.Any(item => "Console" == item.Label));
+ Assert.False(results.Items.Any(item => "Console" == item.Label));
}
[Fact]
@@ -81,7 +75,7 @@ public async Task TestGetCompletionsDoesNotIncludeSnippetsAsync()
var completionParams = CreateCompletionParams(locations["caret"].Single(), "\0", LSP.CompletionTriggerKind.Invoked);
var results = await RunGetCompletionsAsync(solution, completionParams);
- Assert.False(results.Any(item => "ctor" == item.Label));
+ Assert.False(results.Items.Any(item => "ctor" == item.Label));
}
[Fact]
@@ -98,16 +92,43 @@ void M()
using var workspace = CreateTestWorkspace(markup, out var locations);
var completionParams = CreateCompletionParams(locations["caret"].Single(), triggerCharacter: "\0", LSP.CompletionTriggerKind.Invoked);
var expected = CreateCompletionItem("A", LSP.CompletionItemKind.Class, new string[] { "Class", "Internal" },
- completionParams, preselect: true, commitCharacters: new string[] { "", "(", "[", "{" });
+ completionParams, preselect: true);
var results = await RunGetCompletionsAsync(workspace.CurrentSolution, completionParams).ConfigureAwait(false);
- AssertJsonEquals(expected, results.First());
+ AssertJsonEquals(expected, results.Items.First());
+ }
+
+ [Fact]
+ public async Task TestGetCompletionsIsInSuggestionMode()
+ {
+ var markup =
+@"
+using System.Collections.Generic;
+using System.Linq;
+namespace M
+{
+ class Item
+ {
+ void M()
+ {
+ var items = new List- ();
+ items.Count(i{|caret:|}
+ }
+ }
+}";
+ using var workspace = CreateTestWorkspace(markup, out var locations);
+ var completionParams = CreateCompletionParams(
+ locations["caret"].Single(), triggerCharacter: "i", triggerKind: LSP.CompletionTriggerKind.TriggerCharacter);
+
+ var results = (LSP.VSCompletionList)await RunGetCompletionsAsync(workspace.CurrentSolution, completionParams).ConfigureAwait(false);
+ Assert.True(results.Items.Any());
+ Assert.True(results.SuggesstionMode);
}
- private static async Task RunGetCompletionsAsync(Solution solution, LSP.CompletionParams completionParams)
+ private static async Task RunGetCompletionsAsync(Solution solution, LSP.CompletionParams completionParams)
{
var clientCapabilities = new LSP.VSClientCapabilities { SupportsVisualStudioExtensions = true };
- return await GetLanguageServer(solution).ExecuteRequestAsync(LSP.Methods.TextDocumentCompletionName,
+ return await GetLanguageServer(solution).ExecuteRequestAsync(LSP.Methods.TextDocumentCompletionName,
completionParams, clientCapabilities, null, CancellationToken.None);
}
}
diff --git a/src/VisualStudio/LiveShare/Impl/Shims/TypeScriptHandlerShims.cs b/src/VisualStudio/LiveShare/Impl/Shims/TypeScriptHandlerShims.cs
index 0dbfe59f08da61f4a5099ddee909aaa5cd27fbc8..2052cd3692e375183a8f9a6493323b2e87286584 100644
--- a/src/VisualStudio/LiveShare/Impl/Shims/TypeScriptHandlerShims.cs
+++ b/src/VisualStudio/LiveShare/Impl/Shims/TypeScriptHandlerShims.cs
@@ -30,7 +30,7 @@
namespace Microsoft.VisualStudio.LanguageServices.LiveShare
{
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.TextDocumentCompletionName)]
- internal class TypeScriptCompletionHandlerShim : CompletionHandler, ILspRequestHandler