private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } // start and end position can be swapped when mapped between primary and secondary buffer if start position is within visible span (at the edge) // but end position is outside of visible span. in that case, swap start and end position. originalSpan = GetLinePositionSpan(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition); mappedSpan = GetLinePositionSpan(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition); return(startChanged || endChanged); }
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } // start and end position can be swapped when mapped between primary and secondary buffer if start position is within visible span (at the edge) // but end position is outside of visible span. in that case, swap start and end position. originalSpan = GetLinePositionSpan(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition); mappedSpan = GetLinePositionSpan(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition); return startChanged || endChanged; }
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } originalSpan = new LinePositionSpan(startLineColumn.OriginalLinePosition, Max(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition)); mappedSpan = new LinePositionSpan(startLineColumn.MappedLinePosition, Max(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition)); return(startChanged || endChanged); }
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } originalSpan = new LinePositionSpan(startLineColumn.OriginalLinePosition, Max(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition)); mappedSpan = new LinePositionSpan(startLineColumn.MappedLinePosition, Max(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition)); return startChanged || endChanged; }
private static bool TryAdjustSpanIfNeededForVenus(VisualStudioWorkspaceImpl workspace, DocumentId documentId, int originalLine, int originalColumn, out MappedSpan mappedSpan) { mappedSpan = default(MappedSpan); if (documentId == null) { return(false); } var containedDocument = workspace.GetHostDocument(documentId) as ContainedDocument; if (containedDocument == null) { return(false); } var originalSpanOnSecondaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = originalLine, iStartIndex = originalColumn, iEndLine = originalLine, iEndIndex = originalColumn }; var containedLanguage = containedDocument.ContainedLanguage; var bufferCoordinator = containedLanguage.BufferCoordinator; var containedLanguageHost = containedLanguage.ContainedLanguageHost; var spansOnPrimaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK == bufferCoordinator.MapSecondaryToPrimarySpan(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // easy case, we can map span in subject buffer to surface buffer. no need to adjust any span mappedSpan = new MappedSpan(originalLine, originalColumn, spansOnPrimaryBuffer[0].iStartLine, spansOnPrimaryBuffer[0].iStartIndex); return(true); } // we can't directly map span in subject buffer to surface buffer. see whether there is any visible span we can use from the subject buffer span if (containedLanguageHost != null && VSConstants.S_OK != containedLanguageHost.GetNearestVisibleToken(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // no visible span we can use. return(false); } // We need to map both the original and mapped location into visible code so that features such as error list, squiggle, etc. points to user visible area // We have the mapped location in the primary buffer. var nearestVisibleSpanOnPrimaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = spansOnPrimaryBuffer[0].iStartLine, iStartIndex = spansOnPrimaryBuffer[0].iStartIndex, iEndLine = spansOnPrimaryBuffer[0].iStartLine, iEndIndex = spansOnPrimaryBuffer[0].iStartIndex }; // Map this location back to the secondary span to re-adjust the original location to be in user-code in secondary buffer. var spansOnSecondaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK != bufferCoordinator.MapPrimaryToSecondarySpan(nearestVisibleSpanOnPrimaryBuffer, spansOnSecondaryBuffer)) { // we can't adjust original position but we can adjust mapped one mappedSpan = new MappedSpan(originalLine, originalColumn, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); } var nearestVisibleSpanOnSecondaryBuffer = spansOnSecondaryBuffer[0]; var originalLocationMovedAboveInFile = IsOriginalLocationMovedAboveInFile(originalLine, originalColumn, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex); if (!originalLocationMovedAboveInFile) { mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); } LinePosition adjustedPosition; if (TryFixUpNearestVisibleSpan(containedLanguageHost, bufferCoordinator, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, out adjustedPosition)) { // span has changed yet again, re-calculate span return(TryAdjustSpanIfNeededForVenus(workspace, documentId, adjustedPosition.Line, adjustedPosition.Character, out mappedSpan)); } mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); }
private static bool TryAdjustSpanIfNeededForVenus(VisualStudioWorkspaceImpl workspace, DocumentId documentId, int originalLine, int originalColumn, out MappedSpan mappedSpan) { mappedSpan = default(MappedSpan); if (documentId == null) { return false; } var containedDocument = workspace.GetHostDocument(documentId) as ContainedDocument; if (containedDocument == null) { return false; } var originalSpanOnSecondaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = originalLine, iStartIndex = originalColumn, iEndLine = originalLine, iEndIndex = originalColumn }; var containedLanguage = containedDocument.ContainedLanguage; var bufferCoordinator = containedLanguage.BufferCoordinator; var containedLanguageHost = containedLanguage.ContainedLanguageHost; var spansOnPrimaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK == bufferCoordinator.MapSecondaryToPrimarySpan(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // easy case, we can map span in subject buffer to surface buffer. no need to adjust any span mappedSpan = new MappedSpan(originalLine, originalColumn, spansOnPrimaryBuffer[0].iStartLine, spansOnPrimaryBuffer[0].iStartIndex); return true; } // we can't directly map span in subject buffer to surface buffer. see whether there is any visible span we can use from the subject buffer span if (containedLanguageHost != null && VSConstants.S_OK != containedLanguageHost.GetNearestVisibleToken(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // no visible span we can use. return false; } // We need to map both the original and mapped location into visible code so that features such as error list, squiggle, etc. points to user visible area // We have the mapped location in the primary buffer. var nearestVisibleSpanOnPrimaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = spansOnPrimaryBuffer[0].iStartLine, iStartIndex = spansOnPrimaryBuffer[0].iStartIndex, iEndLine = spansOnPrimaryBuffer[0].iStartLine, iEndIndex = spansOnPrimaryBuffer[0].iStartIndex }; // Map this location back to the secondary span to re-adjust the original location to be in user-code in secondary buffer. var spansOnSecondaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK != bufferCoordinator.MapPrimaryToSecondarySpan(nearestVisibleSpanOnPrimaryBuffer, spansOnSecondaryBuffer)) { // we can't adjust original position but we can adjust mapped one mappedSpan = new MappedSpan(originalLine, originalColumn, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; } var nearestVisibleSpanOnSecondaryBuffer = spansOnSecondaryBuffer[0]; var originalLocationMovedAboveInFile = IsOriginalLocationMovedAboveInFile(originalLine, originalColumn, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex); if (!originalLocationMovedAboveInFile) { mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; } if (TryFixUpNearestVisibleSpan(containedLanguageHost, bufferCoordinator, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, out var adjustedPosition)) { // span has changed yet again, re-calculate span return TryAdjustSpanIfNeededForVenus(workspace, documentId, adjustedPosition.Line, adjustedPosition.Character, out mappedSpan); } mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; }