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(),
     });
Esempio n. 3
0
        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);
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
 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);
        }