コード例 #1
0
        public async Task <Hover> HandleRequestAsync(TextDocumentPositionParams request, ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
        {
            await _joinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            if (!_documentManager.TryGetDocument(request.TextDocument.Uri, out var documentSnapshot))
            {
                return(null);
            }

            // Switch to a background thread.
            await TaskScheduler.Default;

            var projectionResult = await _projectionProvider.GetProjectionAsync(documentSnapshot, request.Position, cancellationToken).ConfigureAwait(false);

            if (projectionResult == null)
            {
                return(null);
            }

            var serverKind = projectionResult.LanguageKind == RazorLanguageKind.CSharp ? LanguageServerKind.CSharp : LanguageServerKind.Html;

            var textDocumentPositionParams = new TextDocumentPositionParams()
            {
                Position     = projectionResult.Position,
                TextDocument = new TextDocumentIdentifier()
                {
                    Uri = projectionResult.Uri
                }
            };

            Hover result;

            try
            {
                result = await _requestInvoker.RequestServerAsync <TextDocumentPositionParams, Hover>(
                    Methods.TextDocumentHoverName,
                    serverKind,
                    textDocumentPositionParams,
                    cancellationToken).ConfigureAwait(false);
            }
            catch
            {
                // Ensure we fail silently (Temporary till roslyn update is live)
                return(null);
            }

            if (result?.Range == null || result?.Contents == null)
            {
                return(null);
            }

            var mappingResult = await _documentMappingProvider.MapToDocumentRangeAsync(projectionResult.LanguageKind, request.TextDocument.Uri, result.Range, cancellationToken).ConfigureAwait(false);

            if (mappingResult == null)
            {
                // Couldn't remap the edits properly. Returning hover at initial request position.
                return(new Hover
                {
                    Contents = result.Contents,
                    Range = new Range()
                    {
                        Start = request.Position,
                        End = request.Position
                    }
                });
            }
            else if (mappingResult.HostDocumentVersion != documentSnapshot.Version)
            {
                // Discard hover if document has changed.
                return(null);
            }

            return(new Hover
            {
                Contents = result.Contents,
                Range = mappingResult.Range
            });
        }
コード例 #2
0
        public async Task <TextEdit[]> HandleRequestAsync(DocumentOnTypeFormattingParams request, ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
        {
            if (!AllowedTriggerCharacters.Contains(request.Character, StringComparer.Ordinal))
            {
                // We haven't built support for this character yet.
                return(EmptyEdits);
            }

            await _joinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            if (!_documentManager.TryGetDocument(request.TextDocument.Uri, out var documentSnapshot))
            {
                return(EmptyEdits);
            }

            await SwitchToBackgroundThread().ConfigureAwait(false);

            var projectionResult = await _projectionProvider.GetProjectionAsync(documentSnapshot, request.Position, cancellationToken).ConfigureAwait(false);

            if (projectionResult == null || projectionResult.LanguageKind != RazorLanguageKind.Html)
            {
                return(EmptyEdits);
            }

            if (request.Options.OtherOptions == null)
            {
                request.Options.OtherOptions = new Dictionary <string, object>();
            }
            request.Options.OtherOptions[LanguageServerConstants.ExpectsCursorPlaceholderKey] = true;

            var formattingParams = new DocumentOnTypeFormattingParams()
            {
                Character    = request.Character,
                Options      = request.Options,
                Position     = projectionResult.Position,
                TextDocument = new TextDocumentIdentifier()
                {
                    Uri = projectionResult.Uri
                }
            };

            var serverKind = projectionResult.LanguageKind == RazorLanguageKind.CSharp ? LanguageServerKind.CSharp : LanguageServerKind.Html;
            var edits      = await _requestInvoker.ReinvokeRequestOnServerAsync <DocumentOnTypeFormattingParams, TextEdit[]>(
                Methods.TextDocumentOnTypeFormattingName,
                serverKind,
                formattingParams,
                cancellationToken).ConfigureAwait(false);

            if (edits == null)
            {
                return(EmptyEdits);
            }

            var mappedEdits = new List <TextEdit>();

            foreach (var edit in edits)
            {
                if (edit.Range == null || edit.NewText == null)
                {
                    // Sometimes the HTML language server returns invalid edits like these. We should just ignore those.
                    continue;
                }

                var mappingResult = await _documentMappingProvider.MapToDocumentRangeAsync(projectionResult.LanguageKind, request.TextDocument.Uri, edit.Range, cancellationToken).ConfigureAwait(false);

                if (mappingResult == null || mappingResult.HostDocumentVersion != documentSnapshot.Version)
                {
                    // Couldn't remap the edits properly. Discard this request.
                    return(EmptyEdits);
                }

                var mappedEdit = new TextEdit()
                {
                    NewText = edit.NewText,
                    Range   = mappingResult.Range
                };
                mappedEdits.Add(mappedEdit);
            }

            if (mappedEdits.Count == 0)
            {
                return(EmptyEdits);
            }

            await _joinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            if (!_documentManager.TryGetDocument(request.TextDocument.Uri, out var newDocumentSnapshot) ||
                newDocumentSnapshot.Version != documentSnapshot.Version)
            {
                // The document changed while were working on the background. Discard this request.
                return(EmptyEdits);
            }

            await _editorService.ApplyTextEditsAsync(documentSnapshot.Uri, documentSnapshot.Snapshot, mappedEdits).ConfigureAwait(false);

            // We would have already applied the edits and moved the cursor. Return empty.
            return(EmptyEdits);
        }