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;
        }