public static string ToContentType(this LanguageServerKind languageServerKind) { return(languageServerKind switch { LanguageServerKind.CSharp => RazorLSPConstants.CSharpContentTypeName, LanguageServerKind.Html => RazorLSPConstants.HtmlLSPContentTypeName, _ => RazorLSPConstants.RazorLSPContentTypeName, });
public static string ToLanguageServerName(this LanguageServerKind languageServerKind) { return(languageServerKind switch { LanguageServerKind.CSharp => RazorLSPConstants.RazorCSharpLanguageServerName, LanguageServerKind.Html => RazorLSPConstants.HtmlLanguageServerName, LanguageServerKind.Razor => RazorLSPConstants.RazorLanguageServerName, _ => throw new System.NotImplementedException(), });
public static string ToContentType(this LanguageServerKind languageServerKind) { switch (languageServerKind) { case LanguageServerKind.CSharp: return(RazorLSPConstants.CSharpContentTypeName); case LanguageServerKind.Html: return(RazorLSPConstants.HtmlLSPContentTypeName); default: return(RazorLSPConstants.RazorLSPContentTypeName); } }
private static void AssociateRequest(LanguageServerKind requestKind, CompletionItem item, CompletionRequestContextCache cache, object originalData = null) { var documentUri = new Uri("C:/path/to/file.razor"); var projectedUri = new Uri("C:/path/to/file.razor.g.xyz"); var requestContext = new CompletionRequestContext(documentUri, projectedUri, requestKind); var resultId = cache.Set(requestContext); var data = new CompletionResolveData() { ResultId = resultId, OriginalData = originalData, }; item.Data = data; }
public abstract Task <TOut> CustomRequestServerAsync <TIn, TOut>( string method, LanguageServerKind serverKind, TIn parameters, CancellationToken cancellationToken);
private async Task <TOut> RequestServerCoreAsync <TIn, TOut>(MethodInfo lspPlatformMethod, string method, LanguageServerKind serverKind, TIn parameters, CancellationToken cancellationToken) { if (lspPlatformMethod is null) { throw new ArgumentNullException(nameof(lspPlatformMethod)); } if (string.IsNullOrEmpty(method)) { throw new ArgumentException("message", nameof(method)); } var contentType = RazorLSPConstants.RazorLSPContentTypeName; if (serverKind == LanguageServerKind.CSharp) { contentType = RazorLSPConstants.CSharpLSPContentTypeName; } else if (serverKind == LanguageServerKind.Html) { contentType = RazorLSPConstants.HtmlLSPContentTypeName; } var serializedParams = JToken.FromObject(parameters); var task = (Task <(ILanguageClient, JToken)>)lspPlatformMethod.Invoke( _languageServiceBroker, new object[] { new[] { contentType }, (Func <JToken, bool>)(token => true), method, serializedParams, cancellationToken }); var(_, resultToken) = await task.ConfigureAwait(false); var result = resultToken != null?resultToken.ToObject <TOut>(_serializer) : default; return(result); }
public override Task <TOut> ReinvokeRequestOnServerAsync <TIn, TOut>(string method, LanguageServerKind serverKind, TIn parameters, CancellationToken cancellationToken) { return(RequestServerCoreAsync <TIn, TOut>(_requestAsyncMethod, method, serverKind, parameters, cancellationToken)); }
public async override Task <TOut> RequestServerAsync <TIn, TOut>(string method, LanguageServerKind serverKind, TIn parameters, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(method)) { throw new ArgumentException("message", nameof(method)); } var contentType = RazorLSPContentTypeDefinition.Name; if (serverKind == LanguageServerKind.CSharp) { contentType = CSharpVirtualDocumentFactory.CSharpLSPContentTypeName; } else if (serverKind == LanguageServerKind.Html) { contentType = HtmlVirtualDocumentFactory.HtmlLSPContentTypeName; } var serializedParams = JToken.FromObject(parameters); var task = (Task <(ILanguageClient, JToken)>)_requestAsyncMethod.Invoke( _languageClientBroker, new object[] { new[] { contentType }, (Func <JToken, bool>)(token => true), method, serializedParams, cancellationToken }); var(_, resultToken) = await task.ConfigureAwait(false); var result = resultToken != null?resultToken.ToObject <TOut>() : default; return(result); }
// Internal for testing internal SumType <CompletionItem[], CompletionList>?SetResolveData(SumType <CompletionItem[], CompletionList> completionResult, LanguageServerKind kind) { var result = completionResult.Match <SumType <CompletionItem[], CompletionList>?>( items => { var newItems = items.Select(item => SetData(item)).ToArray(); return(newItems); }, list => { var newItems = list.Items.Select(item => SetData(item)).ToArray(); if (list is VSCompletionList vsList) { return(new VSCompletionList() { Items = newItems, IsIncomplete = vsList.IsIncomplete, SuggesstionMode = vsList.SuggesstionMode, ContinueCharacters = vsList.ContinueCharacters }); } return(new CompletionList() { Items = newItems, IsIncomplete = list.IsIncomplete, }); }, () => null); return(result); CompletionItem SetData(CompletionItem item) { var data = new CompletionResolveData() { LanguageServerKind = kind, OriginalData = item.Data }; item.Data = data; return(item); } }
// C# keywords were previously provided by snippets, but as of now C# LSP doesn't provide snippets. // We're providing these for now to improve the user experience (not having to ESC out of completions to finish), // but once C# starts providing them their completion will be offered instead, at which point we should be able to remove this step. private SumType <CompletionItem[], CompletionList>?IncludeCSharpKeywords(SumType <CompletionItem[], CompletionList> completionResult, LanguageServerKind kind) { var result = completionResult.Match <SumType <CompletionItem[], CompletionList>?>( items => { var newList = items.Union(KeywordCompletionItems, CompletionItemComparer.Instance); return(newList.ToArray()); }, list => { var newList = list.Items.Union(KeywordCompletionItems, CompletionItemComparer.Instance); list.Items = newList.ToArray(); return(list); }); return(result); }
private bool IsSimpleImplicitExpression(LSPDocumentSnapshot documentSnapshot, CompletionParams request, LanguageServerKind serverKind) { if (serverKind != LanguageServerKind.CSharp) { return(false); } if (string.Equals(request.Context.TriggerCharacter, "@", StringComparison.Ordinal)) { // Completion was triggered with `@` this is always a simple implicit expression return(true); } var snapshot = documentSnapshot.Snapshot; var navigator = _textStructureNavigator.GetTextStructureNavigator(snapshot.TextBuffer); var line = snapshot.GetLineFromLineNumber(request.Position.Line); var absoluteIndex = line.Start + request.Position.Character; if (absoluteIndex > snapshot.Length) { Debug.Fail("This should never happen when resolving C# polyfills given we're operating on snapshots."); return(false); } // Lets walk backwards to the character that caused completion (if one triggered it) to ensure that the "GetExtentOfWord" returns // the word we care about and not whitespace following it. For instance: // // @Date|\r\n // // Will return the \r\n as the "word" which is incorrect; however, this is actually fixed in newer VS CoreEditor builds but is behind // the "Use word pattern in LSP completion" preview feature. Once this preview feature flag is the default we can remove this -1. var completionCharacterIndex = Math.Max(0, absoluteIndex - 1); var completionSnapshotPoint = new SnapshotPoint(documentSnapshot.Snapshot, completionCharacterIndex); var wordExtent = navigator.GetExtentOfWord(completionSnapshotPoint); if (!wordExtent.IsSignificant) { // Word is only whitespace, definitely not an implicit expresison return(false); } // We need to look at the item before the word because `@` at the beginning of a word is not encapsulated in that word. var leadingWordCharacterIndex = Math.Max(0, wordExtent.Span.Start.Position - 1); var leadingWordCharacter = snapshot[leadingWordCharacterIndex]; if (leadingWordCharacter == '@') { // This means that completion was requested at something like @for|e and the word was "fore" with the previous character index being "@" return(true); } return(false); }