Skip to content

Commit 4342f8f

Browse files
committed
IDE: Guard against out of bounds positions in requests
This can happen when a line is removed at the end of a file immediately after a request on the removed line and the messages are processed out of order on the server.
1 parent f409c88 commit 4342f8f

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

compiler/src/dotty/tools/dotc/util/SourceFile.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
115115
/** Map line to offset of first character in line */
116116
def lineToOffset(index: Int): Int = lineIndices(index)
117117

118+
/** Like `lineToOffset`, but doesn't crash if the index is out of bounds. */
119+
def lineToOffsetOpt(index: Int): Option[Int] =
120+
if (index < 0 || index >= lineIndices.length)
121+
None
122+
else
123+
Some(lineToOffset(index))
124+
118125
/** A cache to speed up offsetToLine searches to similar lines */
119126
private[this] var lastLine = 0
120127

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -651,10 +651,14 @@ object DottyLanguageServer {
651651
if (isWorksheet(uri)) toWrappedPosition(pos)
652652
else pos
653653
val source = driver.openedFiles(uri)
654-
if (source.exists) {
655-
val p = Spans.Span(source.lineToOffset(actualPosition.getLine) + actualPosition.getCharacter)
656-
new SourcePosition(source, p)
657-
}
654+
if (source.exists)
655+
source.lineToOffsetOpt(actualPosition.getLine).map(_ + actualPosition.getCharacter) match {
656+
case Some(offset) if offset < source.content().length =>
657+
val p = Spans.Span(offset)
658+
new SourcePosition(source, p)
659+
case _ =>
660+
NoSourcePosition
661+
}
658662
else NoSourcePosition
659663
}
660664

0 commit comments

Comments
 (0)