/// <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; }); }
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)); } } }
/// <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; } }
/// <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; }); }
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)); }
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)); }