Ejemplo n.º 1
0
        /// <summary>
        /// Retrieve the server's capabilities before additional requests are made to the remote host.
        /// </summary>
        /// <param name="cancellationToken"></param>
        public void InitializeServerCapabilities(CancellationToken cancellationToken)
        {
            if (ActiveLanguageServerClient == null || ServerCapabilities != null)
            {
                return;
            }

            var initializeRequest = new LS.LspRequest <InitializeParams, InitializeResult>(Methods.InitializeName);

            ThreadHelper.JoinableTaskFactory.Run(async() =>
            {
                var intializeResult = await ActiveLanguageServerClient.RequestAsync(initializeRequest, new InitializeParams(), cancellationToken).ConfigureAwait(false);
                ServerCapabilities  = intializeResult?.Capabilities;
            });
        }
Ejemplo n.º 2
0
        private async Task AddRemoteClassificationsAsync(string classificationsType, string filePath, SourceText sourceText, TextSpan textSpan, ArrayBuilder <ClassifiedSpan> result, CancellationToken cancellationToken)
        {
            var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient;

            if (lspClient == null)
            {
                return;
            }

            // TODO - Move to roslyn client initialization once liveshare initialization is fixed.
            // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/964288
            await _roslynLspClientServiceFactory.EnsureInitialized(cancellationToken).ConfigureAwait(false);

            var classificationParams = new ClassificationParams
            {
                TextDocument = new TextDocumentIdentifier {
                    Uri = lspClient.ProtocolConverter.ToProtocolUri(new Uri(filePath))
                },
                Range = ProtocolConversions.TextSpanToRange(textSpan, sourceText)
            };

            var request             = new LS.LspRequest <ClassificationParams, ClassificationSpan[]>(classificationsType);
            var classificationSpans = await lspClient.RequestAsync(request, classificationParams, cancellationToken).ConfigureAwait(false);

            if (classificationSpans == null)
            {
                return;
            }

            foreach (var classificationSpan in classificationSpans)
            {
                // The host may return more classifications than are supported by the guest. As an example, 15.7 added classifications for type members which wouldnt be understood by a 15.6 guest.
                // Check with the classificationTypeMap to see if this is a known classification.
                var classification = classificationSpan.Classification;
                if (_classificationTypeMap.GetClassificationType(classification) == null)
                {
                    classification = ClassificationTypeNames.Identifier;
                }

                var span = ProtocolConversions.RangeToTextSpan(classificationSpan.Range, sourceText);
                if (span.End <= sourceText.Length)
                {
                    result.Add(new ClassifiedSpan(classification, span));
                }
            }
        }
        public async Task AddRemoteClassificationsAsync(string classificationsServiceName, string filePath, SourceText sourceText, TextSpan textSpan, Action <ClassifiedSpan> tagAdder, CancellationToken cancellationToken)
        {
            var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient;

            if (lspClient == null)
            {
                return;
            }

            await EnsureInitializationAsync(cancellationToken).ConfigureAwait(false);

            var classificationParams = new ClassificationParams
            {
                TextDocument = new TextDocumentIdentifier {
                    Uri = lspClient.ProtocolConverter.ToProtocolUri(new Uri(filePath))
                },
                Range = ProtocolConversions.TextSpanToRange(textSpan, sourceText)
            };

            var request             = new LS.LspRequest <ClassificationParams, ClassificationSpan[]>(classificationsServiceName);
            var classificationSpans = await lspClient.RequestAsync(request, classificationParams, cancellationToken).ConfigureAwait(false);

            if (classificationSpans == null)
            {
                return;
            }

            foreach (var classificationSpan in classificationSpans)
            {
                // The host may return more classifications than are supported by the guest. As an example, 15.7 added classifications for type members which wouldnt be understood by a 15.6 guest.
                // Check with the classificationTypeMap to see if this is a known classification.
                var classification = classificationSpan.Classification;
                if (_classificationTypeMap.GetClassificationType(classification) == null)
                {
                    classification = ClassificationTypeNames.Identifier;
                }

                var span = ProtocolConversions.RangeToTextSpan(classificationSpan.Range, sourceText);
                if (span.End <= sourceText.Length)
                {
                    tagAdder(new ClassifiedSpan(classification, span));
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Ensures the client has been fully initialized by making an initialize request
        /// and retrieving the server capabilities.
        /// TODO - This should be called in <see cref="CreateServiceAsync(CollaborationSession, CancellationToken)"/>
        /// and made private once LiveShare fixes the race in client creation.
        /// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/964288
        /// </summary>
        public async Task EnsureInitializedAsync(CancellationToken cancellationToken)
        {
            if (ActiveLanguageServerClient == null)
            {
                return;
            }

            // Only request the server capabilities if we don't already have them.
            if (ServerCapabilities == null)
            {
                var initializeRequest = new LS.LspRequest <InitializeParams, InitializeResult>(Methods.InitializeName);
                var intializeResult   = await ActiveLanguageServerClient.RequestAsync(initializeRequest, new InitializeParams(), cancellationToken).ConfigureAwait(false);

                var serverCapabilities = intializeResult?.Capabilities;
                if (serverCapabilities != null && LanguageServicesUtils.TryParseJson <RoslynExperimentalCapabilities>(serverCapabilities?.Experimental, out var roslynExperimentalCapabilities))
                {
                    serverCapabilities.Experimental = roslynExperimentalCapabilities;
                }

                ServerCapabilities = serverCapabilities;
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieve the server's capabilities before additional requests are made to the remote host.
        /// </summary>
        /// <param name="cancellationToken"></param>
        public void InitializeServerCapabilities(CancellationToken cancellationToken)
        {
            if (ActiveLanguageServerClient == null || ServerCapabilities != null)
            {
                return;
            }

            var initializeRequest = new LS.LspRequest <InitializeParams, InitializeResult>(Methods.InitializeName);

            ThreadHelper.JoinableTaskFactory.Run(async() =>
            {
                var intializeResult = await ActiveLanguageServerClient.RequestAsync(initializeRequest, new InitializeParams(), cancellationToken).ConfigureAwait(false);

                var serverCapabilities = intializeResult?.Capabilities;
                if (serverCapabilities != null && LanguageServicesUtils.TryParseJson <RoslynExperimentalCapabilities>(serverCapabilities?.Experimental, out var roslynExperimentalCapabilities))
                {
                    serverCapabilities.Experimental = roslynExperimentalCapabilities;
                }

                ServerCapabilities = serverCapabilities;
            });
        }
Ejemplo n.º 6
0
        public async Task <TOut> RequestAsync <TIn, TOut>(LS.LspRequest <TIn, TOut> method, TIn param, RequestContext context, CancellationToken cancellationToken)
        {
            // Note that the LSP types TIn and TOut are defined in an assembly
            // (Microsoft.VisualStudio.LanguageServer.Protocol) referenced by
            // LiveShare and that assembly may be from a different version than
            // the one referenced in PTVS. There is no binding redirect since
            // backwards compatibility is not guaranteed in that assembly, so
            // we cannot cast between TIn/TOut and our referenced types.
            // We can convert between our types and the ones passed in TIn and TOut
            // via the intermediate JSON format which is backwards compatible.
            if (method.Name == Methods.Initialize.Name)
            {
                var capabilities = new ServerCapabilities {
                    CompletionProvider = new LSP.CompletionOptions {
                        TriggerCharacters = new[] { "." }
                    },
                    SignatureHelpProvider = new SignatureHelpOptions {
                        TriggerCharacters = new[] { "(", ",", ")" }
                    },
                    HoverProvider      = true,
                    DefinitionProvider = true,
                    ReferencesProvider = true
                };
                var result = new InitializeResult {
                    Capabilities = capabilities
                };

                // Convert between our type and TOut via a JSON object
                try {
                    var resultObj = JObject.FromObject(result);
                    var res       = resultObj.ToObject <TOut>();
                    return(res);
                } catch (JsonException) {
                    return(default(TOut));
                }
            }

            if (method.Name == Methods.TextDocumentCompletion.Name ||
                method.Name == Methods.TextDocumentHover.Name ||
                method.Name == Methods.TextDocumentDefinition.Name ||
                method.Name == Methods.TextDocumentReferences.Name ||
                method.Name == Methods.TextDocumentSignatureHelp.Name
                )
            {
                Uri     uri = null;
                JObject paramObj;

                // Convert to JSON object to get document URI, and pass that
                // object to the analyzer, which accepts any serializable
                // type, including JObject.
                try {
                    paramObj = JObject.FromObject(param);
                    var uriObj = paramObj.SelectToken("textDocument.uri");
                    if (uriObj is JValue uriVal && uriVal.Type == JTokenType.String)
                    {
                        uri = new Uri((string)uriVal.Value);
                    }
                } catch (JsonException) {
                    return(default(TOut));
                }

                if (uri == null)
                {
                    return(default(TOut));
                }

                var analyzer = await FindAnalyzerAsync(uri);

                if (analyzer == null)
                {
                    return(default(TOut));
                }

                if (method.Name == Methods.TextDocumentDefinition.Name)
                {
                    var result = await analyzer.SendLanguageServerRequestAsync <JObject, Location[]>(method.Name, paramObj);

                    // Convert between our type and TOut via a JSON object
                    try {
                        var resultObj = JArray.FromObject(result);
                        var res       = resultObj.ToObject <TOut>();
                        return(res);
                    } catch (JsonException) {
                        return(default(TOut));
                    }
                }

                var entry = analyzer.GetAnalysisEntryFromUri(uri);
                if (entry != null)
                {
                    var buffers = entry.TryGetBufferParser()?.AllBuffers;
                    if (buffers != null)
                    {
                        foreach (var b in buffers)
                        {
                            await entry.EnsureCodeSyncedAsync(b);
                        }
                    }
                }

                return(await analyzer.SendLanguageServerRequestAsync <JObject, TOut>(method.Name, paramObj));
            }

            return(default(TOut));
        }
Ejemplo n.º 7
0
        public async Task <TOut> RequestAsync <TIn, TOut>(LS.LspRequest <TIn, TOut> method, TIn param, RequestContext context, CancellationToken cancellationToken)
        {
            if (method.Name == Methods.Initialize.Name)
            {
                var capabilities = new ServerCapabilities {
                    CompletionProvider = new LSP.CompletionOptions {
                        TriggerCharacters = new[] { "." }
                    },
                    SignatureHelpProvider = new SignatureHelpOptions {
                        TriggerCharacters = new[] { "(", ",", ")" }
                    },
                    HoverProvider      = true,
                    DefinitionProvider = true,
                    ReferencesProvider = true
                };
                object result = new InitializeResult {
                    Capabilities = capabilities
                };
                return((TOut)(result));
            }

            if (method.Name == Methods.TextDocumentCompletion.Name ||
                method.Name == Methods.TextDocumentHover.Name ||
                method.Name == Methods.TextDocumentDefinition.Name ||
                method.Name == Methods.TextDocumentReferences.Name ||
                method.Name == Methods.TextDocumentSignatureHelp.Name
                )
            {
                var doc = (param as TextDocumentPositionParams)?.TextDocument;
                if (doc == null)
                {
                    return(default(TOut));
                }

                var analyzer = await FindAnalyzerAsync(doc);

                if (analyzer == null)
                {
                    return(default(TOut));
                }

                if (method.Name == Methods.TextDocumentDefinition.Name)
                {
                    return((TOut)(object)await analyzer.SendLanguageServerRequestAsync <TIn, Location[]>(method.Name, param));
                }

                var entry = analyzer.GetAnalysisEntryFromUri(doc.Uri);
                if (entry != null)
                {
                    var buffers = entry.TryGetBufferParser()?.AllBuffers;
                    if (buffers != null)
                    {
                        foreach (var b in buffers)
                        {
                            await entry.EnsureCodeSyncedAsync(b);
                        }
                    }
                }

                return(await analyzer.SendLanguageServerRequestAsync <TIn, TOut>(method.Name, param));
            }

            return(default(TOut));
        }