Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigate to the mapped span when navigating to a mapped file #75460

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public async Task<bool> CanNavigateToPositionAsync(Workspace workspace, Document
documentId,
_ => Task.FromResult(textSpan),
text => GetVsTextSpan(text, textSpan, allowInvalidSpan),
(text, span) => GetVsTextSpan(text, span, allowInvalidSpan),
cancellationToken).ConfigureAwait(false);
}

Expand All @@ -118,7 +119,8 @@ public async Task<bool> CanNavigateToPositionAsync(Workspace workspace, Document
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 @@ -132,7 +134,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 @@ -155,10 +157,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 @@ -178,6 +181,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 @@ -208,26 +212,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 @@ -252,7 +259,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
Loading