diff --git a/src/EditorFeatures/Test/Extensions/ITextSnapshotExtensionsTests.cs b/src/EditorFeatures/Test/Extensions/ITextSnapshotExtensionsTests.cs index f29172532117fbcd6b7bed5e2e4b017c3eb3f0fd..1eb83433813f4884a6fb4ba9e8ad264977ca7ebe 100644 --- a/src/EditorFeatures/Test/Extensions/ITextSnapshotExtensionsTests.cs +++ b/src/EditorFeatures/Test/Extensions/ITextSnapshotExtensionsTests.cs @@ -159,10 +159,17 @@ public void TryGetPositionTest() } [Fact] - public void GetPointTest() + public void TryGetPointValueTest() { var snapshot = GetSampleCodeSnapshot(); - Assert.Equal(new SnapshotPoint(snapshot, 15), snapshot.GetPoint(3, 0)); + Assert.Equal(new SnapshotPoint(snapshot, 15), snapshot.TryGetPoint(3, 0).Value); + } + + [Fact] + public void TryGetPointNullTest() + { + var snapshot = GetSampleCodeSnapshot(); + Assert.Null(snapshot.TryGetPoint(3000, 0)); } [Fact] diff --git a/src/EditorFeatures/Text/Shared/Extensions/ITextSnapshotExtensions.cs b/src/EditorFeatures/Text/Shared/Extensions/ITextSnapshotExtensions.cs index 49e201ed27cfbd14bdda302bfe5809233f7424c6..8708033a71bafd64fc2156747c002e31b1d2a6c6 100644 --- a/src/EditorFeatures/Text/Shared/Extensions/ITextSnapshotExtensions.cs +++ b/src/EditorFeatures/Text/Shared/Extensions/ITextSnapshotExtensions.cs @@ -11,8 +11,18 @@ internal static partial class ITextSnapshotExtensions public static SnapshotPoint GetPoint(this ITextSnapshot snapshot, int position) => new SnapshotPoint(snapshot, position); - public static SnapshotPoint GetPoint(this ITextSnapshot snapshot, int lineNumber, int columnIndex) - => new SnapshotPoint(snapshot, snapshot.GetPosition(lineNumber, columnIndex)); + public static SnapshotPoint? TryGetPoint(this ITextSnapshot snapshot, int lineNumber, int columnIndex) + { + var position = snapshot.TryGetPosition(lineNumber, columnIndex); + if (position.HasValue) + { + return new SnapshotPoint(snapshot, position.Value); + } + else + { + return null; + } + } /// /// Convert a to . diff --git a/src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractLanguageService`2.VsLanguageDebugInfo.cs b/src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractLanguageService`2.VsLanguageDebugInfo.cs index 3f7a868cad113a86eca708d404fcf838cc288382..7923955d60d7b7cd89ad5ee54c756f1c8a03e863 100644 --- a/src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractLanguageService`2.VsLanguageDebugInfo.cs +++ b/src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractLanguageService`2.VsLanguageDebugInfo.cs @@ -92,21 +92,25 @@ public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out str var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { - var point = textBuffer.CurrentSnapshot.GetPoint(iLine, iCol); - var document = point.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); - - if (document != null) + var nullablePoint = textBuffer.CurrentSnapshot.TryGetPoint(iLine, iCol); + if (nullablePoint.HasValue) { - // NOTE(cyrusn): We have to wait here because the debuggers' - // GetNameOfLocation is a blocking call. In the future, it - // would be nice if they could make it async. - var debugLocationInfo = _languageDebugInfo.GetLocationInfoAsync(document, point, cancellationToken).WaitAndGetResult(cancellationToken); + var point = nullablePoint.Value; + var document = point.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); - if (!debugLocationInfo.IsDefault) + if (document != null) { - succeeded = true; - name = debugLocationInfo.Name; - lineOffset = debugLocationInfo.LineOffset; + // NOTE(cyrusn): We have to wait here because the debuggers' + // GetNameOfLocation is a blocking call. In the future, it + // would be nice if they could make it async. + var debugLocationInfo = _languageDebugInfo.GetLocationInfoAsync(document, point, cancellationToken).WaitAndGetResult(cancellationToken); + + if (!debugLocationInfo.IsDefault) + { + succeeded = true; + name = debugLocationInfo.Name; + lineOffset = debugLocationInfo.LineOffset; + } } } } @@ -146,16 +150,20 @@ public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, i if (textBuffer != null) { var snapshot = textBuffer.CurrentSnapshot; - Document document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); - if (document != null) + var nullablePoint = snapshot.TryGetPoint(iLine, iCol); + if (nullablePoint.HasValue) { - var point = snapshot.GetPoint(iLine, iCol); - var proximityExpressions = _proximityExpressionsService.GetProximityExpressionsAsync(document, point.Position, waitContext.CancellationToken).WaitAndGetResult(waitContext.CancellationToken); - - if (proximityExpressions != null) + Document document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); + if (document != null) { - enumBSTR = new VsEnumBSTR(proximityExpressions); - succeeded = true; + var point = nullablePoint.Value; + var proximityExpressions = _proximityExpressionsService.GetProximityExpressionsAsync(document, point.Position, waitContext.CancellationToken).WaitAndGetResult(waitContext.CancellationToken); + + if (proximityExpressions != null) + { + enumBSTR = new VsEnumBSTR(proximityExpressions); + succeeded = true; + } } } } @@ -278,10 +286,17 @@ public int ValidateBreakpointLocation(IVsTextBuffer pBuffer, int iLine, int iCol if (textBuffer != null) { var snapshot = textBuffer.CurrentSnapshot; + var nullablePoint = snapshot.TryGetPoint(iLine, iCol); + if (nullablePoint == null) + { + // The point disappeared between sessions. Do not allow a breakpoint here. + return VSConstants.E_FAIL; + } + Document document = snapshot.AsText().GetDocumentWithFrozenPartialSemantics(cancellationToken); if (document != null) { - var point = snapshot.GetPoint(iLine, iCol); + var point = nullablePoint.Value; var length = 0; if (pCodeSpan != null && pCodeSpan.Length > 0) {