public Task <LinkedEditingRanges?> GetLinkedEditingRangesAsync(LinkedEditingRangeParams renameParams, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called.");

            return(RequestDispatcher.ExecuteRequestAsync <LinkedEditingRangeParams, LinkedEditingRanges?>(Queue, Methods.TextDocumentLinkedEditingRangeName,
                                                                                                          renameParams, _clientCapabilities, ClientName, cancellationToken));
        }
示例#2
0
        public Task <LinkedEditingRanges> OnLinkedEditingRangeAsync(LinkedEditingRangeParams request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            return(ExecuteRequestAsync <LinkedEditingRangeParams, LinkedEditingRanges>(Methods.TextDocumentLinkedEditingRangeName, request, ClientCapabilities, cancellationToken));
        }
#pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member.
        // The return type of the handler should be nullable. O# tracking issue:
        // https://github.com/OmniSharp/csharp-language-server-protocol/issues/644
        public async Task <LinkedEditingRanges?> Handle(
#pragma warning restore CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member.
            LinkedEditingRangeParams request,
            CancellationToken cancellationToken)
        {
            var uri      = request.TextDocument.Uri.GetAbsoluteOrUNCPath();
            var document = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() =>
            {
                if (!_documentResolver.TryResolveDocument(uri, out var documentSnapshot))
                {
                    _logger.LogWarning("Unable to resolve document for {Uri}", uri);
                    return(null);
                }

                return(documentSnapshot);
            }, cancellationToken).ConfigureAwait(false);

            if (document is null || cancellationToken.IsCancellationRequested)
            {
                _logger.LogWarning("Unable to resolve document for {Uri} or cancellation was requested.", uri);
                return(null);
            }

            var codeDocument = await document.GetGeneratedOutputAsync();

            if (codeDocument.IsUnsupported())
            {
                _logger.LogWarning("FileKind {FileKind} is unsupported", codeDocument.GetFileKind());
                return(null);
            }

            var location = await GetSourceLocation(request, document).ConfigureAwait(false);

            // We only care if the user is within a TagHelper or HTML tag with a valid start and end tag.
            if (TryGetNearestMarkupNameTokens(codeDocument, location, out var startTagNameToken, out var endTagNameToken) &&
                (startTagNameToken.Span.Contains(location.AbsoluteIndex) || endTagNameToken.Span.Contains(location.AbsoluteIndex) ||
                 startTagNameToken.Span.End == location.AbsoluteIndex || endTagNameToken.Span.End == location.AbsoluteIndex))
            {
                var startSpan = startTagNameToken.GetLinePositionSpan(codeDocument.Source);
                var endSpan   = endTagNameToken.GetLinePositionSpan(codeDocument.Source);
                var ranges    = new Range[2] {
                    startSpan.AsRange(), endSpan.AsRange()
                };

                return(new LinkedEditingRanges
                {
                    Ranges = ranges,
                    WordPattern = WordPattern
                });
            }

            _logger.LogInformation("LinkedEditingRange request was null at {location} for {uri}", location, uri);
            return(null);
            static async Task <SourceLocation> GetSourceLocation(
                LinkedEditingRangeParams request,
                DocumentSnapshot document)
            {
                var sourceText = await document.GetTextAsync().ConfigureAwait(false);

                var linePosition      = new LinePosition(request.Position.Line, request.Position.Character);
                var hostDocumentIndex = sourceText.Lines.GetPosition(linePosition);
                var location          = new SourceLocation(hostDocumentIndex, request.Position.Line, request.Position.Character);

                return(location);
            }
        public async Task Handle_TagHelperStartTag_ReturnsCorrectRange_EndSpan()
        {
            // Arrange
            var txt              = $"@addTagHelper *, TestAssembly{Environment.NewLine}<test1></test1>";
            var codeDocument     = CreateCodeDocument(txt, DefaultTagHelpers);
            var uri              = new Uri("file://path/test.razor");
            var documentResolver = CreateDocumentResolver(uri.GetAbsoluteOrUNCPath(), codeDocument);
            var endpoint         = new LinkedEditingRangeEndpoint(LegacyDispatcher, documentResolver, LoggerFactory);
            var request          = new LinkedEditingRangeParams
            {
                TextDocument = new TextDocumentIdentifier(uri),
                Position     = new Position {
                    Line = 1, Character = 6
                }                                                   // <test1[||]></test1>
            };

            var expectedRanges = new Range[]
            {
                new Range
                {
                    Start = new Position {
                        Line = 1, Character = 1
                    },
                    End = new Position {
                        Line = 1, Character = 6
                    }
                },
                new Range
                {
                    Start = new Position {
                        Line = 1, Character = 9
                    },
                    End = new Position {
                        Line = 1, Character = 14
                    }
                }
            };

            // Act
            var result = await endpoint.Handle(request, CancellationToken.None);

            // Assert
            Assert.Equal(expectedRanges, result.Ranges);
            Assert.Equal(LinkedEditingRangeEndpoint.WordPattern, result.WordPattern);
        }
        public async Task Handle_SelfClosingHTMLTag_ReturnsNull()
        {
            // Arrange
            var txt              = $"@addTagHelper *, TestAssembly{Environment.NewLine}<body />";
            var codeDocument     = CreateCodeDocument(txt, DefaultTagHelpers);
            var uri              = new Uri("file://path/test.razor");
            var documentResolver = CreateDocumentResolver(uri.GetAbsoluteOrUNCPath(), codeDocument);
            var endpoint         = new LinkedEditingRangeEndpoint(LegacyDispatcher, documentResolver, LoggerFactory);
            var request          = new LinkedEditingRangeParams
            {
                TextDocument = new TextDocumentIdentifier(uri),
                Position     = new Position {
                    Line = 1, Character = 3
                }                                                   // <bo[||]dy />
            };

            // Act
            var result = await endpoint.Handle(request, CancellationToken.None);

            // Assert
            Assert.Null(result);
        }