Skip to content

Commit

Permalink
Merge pull request #75460 from davidwengier/NavigateToMappedSpan
Browse files Browse the repository at this point in the history
Navigate to the mapped span when navigating to a mapped file
  • Loading branch information
davidwengier authored Oct 10, 2024
2 parents ee185b2 + 6feb9ff commit c9dd07d
Showing 1 changed file with 16 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public async Task<bool> CanNavigateToPositionAsync(
documentId,
_ => Task.FromResult(textSpan),
text => GetVsTextSpan(text, textSpan, allowInvalidSpan),
(text, span) => GetVsTextSpan(text, span, allowInvalidSpan),
cancellationToken).ConfigureAwait(false);
}

Expand All @@ -119,7 +120,8 @@ public async Task<bool> CanNavigateToPositionAsync(
return await GetNavigableLocationAsync(workspace,
documentId,
document => GetTextSpanFromPositionAsync(document, position, virtualSpace, cancellationToken),
text => GetVsTextSpan(text, position, virtualSpace),
text => GetVsTextSpanFromPosition(text, position, virtualSpace),
(text, span) => GetVsTextSpan(text, span, allowInvalidSpan: false),
cancellationToken).ConfigureAwait(false);

static async Task<TextSpan> GetTextSpanFromPositionAsync(Document document, int position, int virtualSpace, CancellationToken cancellationToken)
Expand All @@ -133,7 +135,7 @@ static async Task<TextSpan> GetTextSpanFromPositionAsync(Document document, int
return text.Lines.GetTextSpan(new LinePositionSpan(linePosition, linePosition));
}

static VsTextSpan GetVsTextSpan(SourceText text, int position, int virtualSpace)
static VsTextSpan GetVsTextSpanFromPosition(SourceText text, int position, int virtualSpace)
{
var boundedPosition = GetPositionWithinDocumentBounds(position, text.Length);
if (boundedPosition != position)
Expand All @@ -156,10 +158,11 @@ static VsTextSpan GetVsTextSpan(SourceText text, int position, int virtualSpace)
DocumentId documentId,
Func<Document, Task<TextSpan>> getTextSpanForMappingAsync,
Func<SourceText, VsTextSpan> getVsTextSpan,
Func<SourceText, TextSpan, VsTextSpan> getVsTextSpanForMapping,
CancellationToken cancellationToken)
{
var callback = await GetNavigationCallbackAsync(
workspace, documentId, getTextSpanForMappingAsync, getVsTextSpan, cancellationToken).ConfigureAwait(true);
workspace, documentId, getTextSpanForMappingAsync, getVsTextSpan, getVsTextSpanForMapping, cancellationToken).ConfigureAwait(true);
if (callback == null)
return null;

Expand All @@ -179,6 +182,7 @@ static VsTextSpan GetVsTextSpan(SourceText text, int position, int virtualSpace)
DocumentId documentId,
Func<Document, Task<TextSpan>> getTextSpanForMappingAsync,
Func<SourceText, VsTextSpan> getVsTextSpan,
Func<SourceText, TextSpan, VsTextSpan> getVsTextSpanForMapping,
CancellationToken cancellationToken)
{
// Navigation should not change the context of linked files and Shared Projects.
Expand Down Expand Up @@ -209,26 +213,29 @@ static VsTextSpan GetVsTextSpan(SourceText text, int position, int virtualSpace)
var spanMappingService = document.DocumentServiceProvider.GetService<ISpanMappingService>();
if (spanMappingService != null)
{
var mappedSpan = await GetMappedSpanAsync(
var mappedSpanResult = await GetMappedSpanAsync(
spanMappingService,
document,
await getTextSpanForMappingAsync(document).ConfigureAwait(false),
cancellationToken).ConfigureAwait(false);
if (mappedSpan.HasValue)
if (mappedSpanResult is { IsDefault: false } mappedSpan)
{
// Check if the mapped file matches one already in the workspace.
// If so use the workspace APIs to navigate to it. Otherwise use VS APIs to navigate to the file path.
var documentIdsForFilePath = solution.GetDocumentIdsWithFilePath(mappedSpan.Value.FilePath);
var documentIdsForFilePath = solution.GetDocumentIdsWithFilePath(mappedSpan.FilePath);
if (!documentIdsForFilePath.IsEmpty)
{
// If the mapped file maps to the same document that was passed in, then re-use the documentId to preserve context.
// Otherwise, just pick one of the ids to use for navigation.
var documentIdToNavigate = documentIdsForFilePath.Contains(documentId) ? documentId : documentIdsForFilePath.First();
return GetNavigationCallback(documentIdToNavigate, workspace, getVsTextSpan);
return GetNavigationCallback(
documentIdToNavigate,
workspace,
sourceText => getVsTextSpanForMapping(sourceText, mappedSpan.Span));
}

return await GetNavigableLocationForMappedFileAsync(
workspace, document, mappedSpan.Value, cancellationToken).ConfigureAwait(false);
workspace, document, mappedSpan, cancellationToken).ConfigureAwait(false);
}
}

Expand All @@ -253,7 +260,7 @@ await getTextSpanForMappingAsync(document).ConfigureAwait(false),
return false;

// Now that we've opened the document reacquire the corresponding Document in the current solution.
var document = workspace.CurrentSolution.GetDocument(documentId);
var document = workspace.CurrentSolution.GetTextDocument(documentId);
if (document == null)
return false;

Expand Down

0 comments on commit c9dd07d

Please sign in to comment.