Skip to content

Commit f2b0b8a

Browse files
authored
Merge pull request #5389 from dotty-staging/fix-no-source
IDE: guard against SourceFile -> URI conversion failing
2 parents a5556b6 + 5adbf3b commit f2b0b8a

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

compiler/src/dotty/tools/dotc/interactive/Interactive.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ object Interactive {
475475
Include.definitions | Include.overriding | Include.overridden)
476476
else sym.topLevelClass match {
477477
case cls: ClassSymbol =>
478-
val trees = Option(cls.sourceFile).map(InteractiveDriver.toUri) match {
478+
val trees = Option(cls.sourceFile).flatMap(InteractiveDriver.toUriOption) match {
479479
case Some(uri) if driver.openedTrees.contains(uri) =>
480480
driver.openedTrees(uri)
481481
case _ => // Symbol comes from the classpath

compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,24 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
265265
}
266266

267267
object InteractiveDriver {
268-
def toUri(file: AbstractFile): URI = Paths.get(file.path).toUri
269-
def toUri(source: SourceFile): URI = toUri(source.file)
268+
def toUriOption(file: AbstractFile): Option[URI] =
269+
if (!file.exists)
270+
None
271+
else
272+
try {
273+
// We don't use file.file here since it'll be null
274+
// for the VirtualFiles created by InteractiveDriver#toSource
275+
// TODO: To avoid these round trip conversions, we could add an
276+
// AbstractFile#toUri method and implement it by returning a constant
277+
// passed as a parameter to a constructor of VirtualFile
278+
Some(Paths.get(file.path).toUri)
279+
} catch {
280+
case e: InvalidPathException =>
281+
None
282+
}
283+
def toUriOption(source: SourceFile): Option[URI] =
284+
if (!source.exists)
285+
None
286+
else
287+
toUriOption(source.file)
270288
}
271-

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ class DottyLanguageServer extends LanguageServer
315315
Include.references | Include.definitions | Include.linkedClass | Include.overriding
316316
val refs = Interactive.findTreesMatching(trees, includes, sym)
317317

318-
val changes = refs.groupBy(ref => toUri(ref.source).toString)
318+
val changes = refs.groupBy(ref => toUriOption(ref.source))
319+
.flatMap((uriOpt, ref) => uriOpt.map(uri => (uri.toString, ref)))
319320
.mapValues(refs =>
320321
refs.flatMap(ref =>
321322
range(ref.namePos, positionMapperFor(ref.source)).map(nameRange => new TextEdit(nameRange, newName))).asJava)
@@ -433,7 +434,10 @@ object DottyLanguageServer {
433434

434435
/** Convert a SourcePosition to an lsp4.Location */
435436
def location(p: SourcePosition, positionMapper: Option[SourcePosition => SourcePosition] = None): Option[lsp4j.Location] =
436-
range(p, positionMapper).map(r => new lsp4j.Location(toUri(p.source).toString, r))
437+
for {
438+
uri <- toUriOption(p.source)
439+
r <- range(p, positionMapper)
440+
} yield new lsp4j.Location(uri.toString, r)
437441

438442
/**
439443
* Convert a MessageContainer to an lsp4j.Diagnostic. The positions are transformed vy

0 commit comments

Comments
 (0)