private async Task <(LSPDocumentSnapshot?, TextEdit[])> RemapTextEditsCoreAsync(
            Uri uri,
            TextEdit[] edits,
            TextEditKind textEditKind,
            CancellationToken cancellationToken,
            FormattingOptions?formattingOptions = null)
        {
            var languageKind = RazorLanguageKind.Razor;

            if (RazorLSPConventions.IsVirtualCSharpFile(uri))
            {
                languageKind = RazorLanguageKind.CSharp;
            }
            else if (RazorLSPConventions.IsVirtualHtmlFile(uri))
            {
                languageKind = RazorLanguageKind.Html;
            }
            else
            {
                Debug.Fail("This method should only be called for Razor background files.");
            }

            var razorDocumentUri = RazorLSPConventions.GetRazorDocumentUri(uri);

            var mapToDocumentEditsParams = new RazorMapToDocumentEditsParams()
            {
                Kind               = languageKind,
                RazorDocumentUri   = razorDocumentUri,
                ProjectedTextEdits = edits,
                TextEditKind       = textEditKind,
                FormattingOptions  = formattingOptions
            };

            if (!_lazyDocumentManager.Value.TryGetDocument(razorDocumentUri, out var documentSnapshot))
            {
                return(null, s_emptyEdits);
            }

            var response = await _requestInvoker.ReinvokeRequestOnServerAsync <RazorMapToDocumentEditsParams, RazorMapToDocumentEditsResponse>(
                documentSnapshot.Snapshot.TextBuffer,
                LanguageServerConstants.RazorMapToDocumentEditsEndpoint,
                RazorLSPConstants.RazorLanguageServerName,
                CheckRazorEditMappingCapability,
                mapToDocumentEditsParams,
                cancellationToken).ConfigureAwait(false);

            var mappingResult = response?.Response;

            if (mappingResult is null ||
                (_lazyDocumentManager.Value.TryGetDocument(razorDocumentUri, out documentSnapshot) &&
                 mappingResult.HostDocumentVersion != documentSnapshot.Version))
            {
                // Couldn't remap the location or the document changed in the meantime. Discard these ranges.
                return(null, s_emptyEdits);
            }

            return(documentSnapshot, mappingResult.TextEdits);
        }
        private async Task <VSInternalReferenceItem[]> RemapReferenceItemsAsync(VSInternalReferenceItem[] result, CancellationToken cancellationToken)
        {
            var remappedLocations = new List <VSInternalReferenceItem>();

            foreach (var referenceItem in result)
            {
                if (referenceItem?.Location is null || referenceItem.Text is null)
                {
                    continue;
                }

                // Temporary fix for codebehind leaking through
                // Revert when https://github.com/dotnet/aspnetcore/issues/22512 is resolved
                referenceItem.DefinitionText = FilterReferenceDisplayText(referenceItem.DefinitionText);
                referenceItem.Text           = FilterReferenceDisplayText(referenceItem.Text);

                // Indicates the reference item is directly available in the code
                referenceItem.Origin = VSInternalItemOrigin.Exact;

                if (!RazorLSPConventions.IsVirtualCSharpFile(referenceItem.Location.Uri) &&
                    !RazorLSPConventions.IsVirtualHtmlFile(referenceItem.Location.Uri))
                {
                    // This location doesn't point to a virtual cs file. No need to remap.
                    remappedLocations.Add(referenceItem);
                    continue;
                }

                var razorDocumentUri = RazorLSPConventions.GetRazorDocumentUri(referenceItem.Location.Uri);
                var languageKind     = RazorLSPConventions.IsVirtualCSharpFile(referenceItem.Location.Uri) ? RazorLanguageKind.CSharp : RazorLanguageKind.Html;
                var mappingResult    = await _documentMappingProvider.MapToDocumentRangesAsync(
                    languageKind,
                    razorDocumentUri,
                    new[] { referenceItem.Location.Range },
                    cancellationToken).ConfigureAwait(false);

                if (mappingResult == null ||
                    mappingResult.Ranges[0].IsUndefined() ||
                    (_documentManager.TryGetDocument(razorDocumentUri, out var mappedDocumentSnapshot) &&
                     mappingResult.HostDocumentVersion != mappedDocumentSnapshot.Version))
                {
                    // Couldn't remap the location or the document changed in the meantime. Discard this location.
                    continue;
                }

                referenceItem.Location.Uri   = razorDocumentUri;
                referenceItem.DisplayPath    = razorDocumentUri.AbsolutePath;
                referenceItem.Location.Range = mappingResult.Ranges[0];

                remappedLocations.Add(referenceItem);
            }

            return(remappedLocations.ToArray());
        }
예제 #3
0
        public async override Task <TextEdit[]> RemapTextEditsAsync(Uri uri, TextEdit[] edits, CancellationToken cancellationToken)
        {
            if (uri is null)
            {
                throw new ArgumentNullException(nameof(uri));
            }

            if (edits is null)
            {
                throw new ArgumentNullException(nameof(edits));
            }

            if (!RazorLSPConventions.IsVirtualCSharpFile(uri) && !RazorLSPConventions.IsVirtualHtmlFile(uri))
            {
                // This is not a virtual razor file. No need to remap.
                return(edits);
            }

            var(_, remappedEdits) = await RemapTextEditsCoreAsync(uri, edits, TextEditKind.Default, cancellationToken).ConfigureAwait(false);

            return(remappedEdits);
        }
예제 #4
0
        public async override Task <TextEdit[]> RemapFormattedTextEditsAsync(Uri uri, TextEdit[] edits, FormattingOptions options, bool containsSnippet, CancellationToken cancellationToken)
        {
            if (uri is null)
            {
                throw new ArgumentNullException(nameof(uri));
            }

            if (edits is null)
            {
                throw new ArgumentNullException(nameof(edits));
            }

            if (!RazorLSPConventions.IsVirtualCSharpFile(uri) && !RazorLSPConventions.IsVirtualHtmlFile(uri))
            {
                // This is not a virtual razor file. No need to remap.
                return(edits);
            }

            var textEditKind = containsSnippet ? TextEditKind.Snippet : TextEditKind.FormatOnType;

            var(_, remappedEdits) = await RemapTextEditsCoreAsync(uri, edits, textEditKind, cancellationToken, formattingOptions : options).ConfigureAwait(false);

            return(remappedEdits);
        }
예제 #5
0
        public async override Task <Location[]> RemapLocationsAsync(Location[] locations, CancellationToken cancellationToken)
        {
            if (locations is null)
            {
                throw new ArgumentNullException(nameof(locations));
            }

            var remappedLocations = new List <Location>();

            foreach (var location in locations)
            {
                var uri = location.Uri;
                RazorLanguageKind languageKind;
                if (RazorLSPConventions.IsVirtualCSharpFile(uri))
                {
                    languageKind = RazorLanguageKind.CSharp;
                }
                else if (RazorLSPConventions.IsVirtualHtmlFile(uri))
                {
                    languageKind = RazorLanguageKind.Html;
                }
                else
                {
                    // This location doesn't point to a virtual razor file. No need to remap.
                    remappedLocations.Add(location);
                    continue;
                }

                var razorDocumentUri = RazorLSPConventions.GetRazorDocumentUri(uri);

                var mappingResult = await MapToDocumentRangesAsync(
                    languageKind,
                    razorDocumentUri,
                    new[] { location.Range },
                    cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                if (mappingResult == null ||
                    (_lazyDocumentManager.Value.TryGetDocument(razorDocumentUri, out var documentSnapshot) &&
                     mappingResult.HostDocumentVersion != documentSnapshot.Version))
                {
                    // Couldn't remap the location or the document changed in the meantime. Discard these ranges.
                    continue;
                }

                var remappedRange = mappingResult.Ranges[0];
                if (remappedRange.IsUndefined())
                {
                    // Couldn't remap the range correctly. Discard this range.
                    continue;
                }

                var remappedLocation = new Location()
                {
                    Uri   = razorDocumentUri,
                    Range = remappedRange,
                };

                remappedLocations.Add(remappedLocation);
            }

            return(remappedLocations.ToArray());
        }
예제 #6
0
 private static bool CanRemap(Uri uri)
 {
     return(RazorLSPConventions.IsVirtualCSharpFile(uri) || RazorLSPConventions.IsVirtualHtmlFile(uri));
 }