protected override async Task <CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken) { var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return(await base.GetDescriptionWorkerAsync(document, item, cancellationToken).ConfigureAwait(false)); } if (!item.Properties.TryGetValue("ResolveData", out var serializedItem)) { return(await base.GetDescriptionWorkerAsync(document, item, cancellationToken).ConfigureAwait(false)); } var completionItem = JToken.Parse(serializedItem).ToObject <RoslynCompletionItem>(); var request = new LspRequest <RoslynCompletionItem, RoslynCompletionItem>(LSP.Methods.TextDocumentCompletionResolveName); var resolvedCompletionItem = await lspClient.RequestAsync(request, completionItem, cancellationToken).ConfigureAwait(false); if (resolvedCompletionItem?.Description == null) { return(await base.GetDescriptionWorkerAsync(document, item, cancellationToken).ConfigureAwait(false)); } var parts = resolvedCompletionItem.Description.Select(tt => tt.ToTaggedText()).AsImmutable(); return(CompletionDescription.Create(parts)); }
protected override async Task <IEnumerable <CodeActionOperation> > ComputePreviewOperationsAsync(CancellationToken cancellationToken) { // If we have a codeaction, then just call the base method which will call ComputeOperationsAsync below. // This creates an ApplyChagesOperation so that Roslyn can show a preview of the changes. if (_codeActionWorkspaceEdit != null) { return(await base.ComputePreviewOperationsAsync(cancellationToken).ConfigureAwait(false)); } // We have a command - this will be executed on the host but the host may have a preview for the current document. var runCodeActionsCommand = ((JToken)_command.Arguments?.Single()).ToObject <LSP.Command>(); var runCodeActionParams = ((JToken)runCodeActionsCommand.Arguments?.Single())?.ToObject <RunCodeActionParams>(); var request = new LspRequest <RunCodeActionParams, LSP.TextEdit[]>(RoslynMethods.CodeActionPreviewName); var textEdits = await _lspClient.RequestAsync(request, runCodeActionParams, cancellationToken).ConfigureAwait(false); if (textEdits == null || textEdits.Length == 0) { return(ImmutableArray <CodeActionOperation> .Empty); } var newDocument = await ApplyEditsAsync(_document, textEdits, cancellationToken).ConfigureAwait(false); return(ImmutableArray.Create(new ApplyChangesOperation(newDocument.Project.Solution))); }
public static Task <TResult> InvokeWithParameterObjectAsync <TArgument, TResult> ( this JsonRpc jsonRpc, LspRequest <TArgument, TResult> request, TArgument argument, CancellationToken cancellationToken = default(CancellationToken)) { return(jsonRpc.InvokeWithParameterObjectAsync <TResult> (request.Name, argument, cancellationToken)); }
public async Task <ImmutableArray <ProjectInfo> > GetRemoteProjectInfosAsync(CancellationToken cancellationToken) { if (!_remoteLanguageServiceWorkspace.IsRemoteSession) { return(ImmutableArray <ProjectInfo> .Empty); } var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return(ImmutableArray <ProjectInfo> .Empty); } CustomProtocol.Project[] projects; try { var request = new LspRequest <object, CustomProtocol.Project[]>(CustomProtocol.RoslynMethods.ProjectsName); projects = await lspClient.RequestAsync(request, new object(), cancellationToken).ConfigureAwait(false); } catch (Exception) { projects = null; } if (projects == null) { return(ImmutableArray <ProjectInfo> .Empty); } var projectInfos = ImmutableArray.CreateBuilder <ProjectInfo>(); foreach (var project in projects) { // We don't want to add cshtml files to the workspace since the Roslyn will add the generated secondary buffer of a cshtml // file to a different project but with the same path. This used to be ok in Dev15 but in Dev16 this confuses Roslyn and causes downstream // issues. There's no need to add the actual cshtml file to the workspace - so filter those out. // This is also the case for files for which TypeScript adds the generated TypeScript buffer to a different project. var filesTasks = project.SourceFiles .Where(f => f.Scheme != SystemUriSchemeExternal) .Where(f => !this._secondaryBufferFileExtensions.Any(ext => f.LocalPath.EndsWith(ext))) .Select(f => lspClient.ProtocolConverter.FromProtocolUriAsync(f, false, cancellationToken)); var files = await Task.WhenAll(filesTasks).ConfigureAwait(false); var projectInfo = CreateProjectInfo(project.Name, project.Language, files.Select(f => f.LocalPath).ToImmutableArray()); projectInfos.Add(projectInfo); } return(projectInfos.ToImmutableArray()); }
private async Task AddRemoteSemanticClassificationsAsync(SourceText text, string filePath, TextSpan textSpan, ArrayBuilder <ClassifiedSpan> result, CancellationToken cancellationToken) { var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return; } var classificationParams = new ClassificationParams { TextDocument = new TextDocumentIdentifier { Uri = lspClient.ProtocolConverter.ToProtocolUri(new Uri(filePath)) }, Range = ProtocolConversions.TextSpanToRange(textSpan, text) }; var request = new LspRequest <ClassificationParams, ClassificationSpan[]>(RoslynMethods.ClassificationsName); 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, text); if (span.End <= text.Length) { result.Add(new ClassifiedSpan(classification, span)); } } }
public async Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(Document document, CancellationToken cancellationToken) { var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return(ImmutableArray <Diagnostic> .Empty); } var textDocumentParams = new TextDocumentParams { TextDocument = new LSP.TextDocumentIdentifier { Uri = lspClient.ProtocolConverter.ToProtocolUri(new Uri(document.FilePath)) } }; var request = new LspRequest <TextDocumentParams, RoslynDiagnostic[]>(CustomMethods.GetDocumentDiagnosticsName); var lspDiagnostics = await lspClient.RequestAsync(request, textDocumentParams, cancellationToken).ConfigureAwait(false); if (lspDiagnostics == null) { return(ImmutableArray <Diagnostic> .Empty); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var diagnostics = ImmutableArray.CreateBuilder <Diagnostic>(); foreach (var diagnostic in lspDiagnostics) { var location = Location.Create(document.FilePath, ProtocolConversions.RangeToTextSpan(diagnostic.Range, text), ProtocolConversions.RangeToLinePositionSpan(diagnostic.Range)); var severity = ToDiagnosticSeverity(diagnostic.Severity); var diag = Diagnostic.Create(diagnostic.Code ?? "VSLS", string.Empty, diagnostic.Message, severity, severity, true, severity == DiagnosticSeverity.Error ? 0 : 1, location: location, customTags: diagnostic.Tags); diagnostics.Add(diag); } return(diagnostics.ToImmutableArray()); }
public async Task <TOut> RequestAsync <TIn, TOut>(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)); }