Skip to content

Commit a4b60c4

Browse files
authored
Merge pull request #5151 from dotty-staging/fix-nopos
IDE: Fix crash on malformed input
2 parents a0b429b + 77e67c3 commit a4b60c4

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

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

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ class DottyLanguageServer extends LanguageServer
288288
(Nil, Include.overriding)
289289
}
290290
val defs = Interactive.namedTrees(trees, include, sym)
291-
defs.map(d => location(d.namePos)).asJava
291+
defs.flatMap(d => location(d.namePos)).asJava
292292
}
293293
}
294294

@@ -311,7 +311,7 @@ class DottyLanguageServer extends LanguageServer
311311
Include.references | Include.overriding | (if (includeDeclaration) Include.definitions else 0)
312312
val refs = Interactive.findTreesMatching(trees, includes, sym)
313313

314-
refs.map(ref => location(ref.namePos)).asJava
314+
refs.flatMap(ref => location(ref.namePos)).asJava
315315
}
316316
}
317317

@@ -331,7 +331,10 @@ class DottyLanguageServer extends LanguageServer
331331
Include.references | Include.definitions | Include.linkedClass | Include.overriding
332332
val refs = Interactive.findTreesMatching(trees, includes, sym)
333333

334-
val changes = refs.groupBy(ref => toUri(ref.source).toString).mapValues(_.map(ref => new TextEdit(range(ref.namePos), newName)).asJava)
334+
val changes = refs.groupBy(ref => toUri(ref.source).toString)
335+
.mapValues(refs =>
336+
refs.flatMap(ref =>
337+
range(ref.namePos).map(nameRange => new TextEdit(nameRange, newName))).asJava)
335338

336339
new WorkspaceEdit(changes.asJava)
337340
}
@@ -349,9 +352,10 @@ class DottyLanguageServer extends LanguageServer
349352
if (sym == NoSymbol) Nil.asJava
350353
else {
351354
val refs = Interactive.namedTrees(uriTrees, Include.references | Include.overriding, sym)
352-
( for (ref <- refs if ref.namePos.exists)
353-
yield new DocumentHighlight(range(ref.namePos), DocumentHighlightKind.Read)
354-
).asJava
355+
(for {
356+
ref <- refs
357+
nameRange <- range(ref.namePos)
358+
} yield new DocumentHighlight(nameRange, DocumentHighlightKind.Read)).asJava
355359
}
356360
}
357361

@@ -382,7 +386,10 @@ class DottyLanguageServer extends LanguageServer
382386
val uriTrees = driver.openedTrees(uri)
383387

384388
val defs = Interactive.namedTrees(uriTrees, includeReferences = false, _ => true)
385-
defs.map(d => JEither.forLeft(symbolInfo(d.tree.symbol, d.namePos))).asJava
389+
(for {
390+
d <- defs
391+
info <- symbolInfo(d.tree.symbol, d.namePos)
392+
} yield JEither.forLeft(info)).asJava
386393
}
387394

388395
override def symbol(params: WorkspaceSymbolParams) = computeAsync { cancelToken =>
@@ -393,7 +400,7 @@ class DottyLanguageServer extends LanguageServer
393400

394401
val trees = driver.allTrees
395402
val defs = Interactive.namedTrees(trees, includeReferences = false, nameSubstring = query)
396-
defs.map(d => symbolInfo(d.tree.symbol, d.namePos))
403+
defs.flatMap(d => symbolInfo(d.tree.symbol, d.namePos))
397404
}.asJava
398405
}
399406

@@ -427,15 +434,18 @@ object DottyLanguageServer {
427434
}
428435

429436
/** Convert a SourcePosition to an lsp4j.Range */
430-
def range(p: SourcePosition): lsp4j.Range =
431-
new lsp4j.Range(
432-
new lsp4j.Position(p.startLine, p.startColumn),
433-
new lsp4j.Position(p.endLine, p.endColumn)
434-
)
437+
def range(p: SourcePosition): Option[lsp4j.Range] =
438+
if (p.exists)
439+
Some(new lsp4j.Range(
440+
new lsp4j.Position(p.startLine, p.startColumn),
441+
new lsp4j.Position(p.endLine, p.endColumn)
442+
))
443+
else
444+
None
435445

436446
/** Convert a SourcePosition to an lsp4.Location */
437-
def location(p: SourcePosition): lsp4j.Location =
438-
new lsp4j.Location(toUri(p.source).toString, range(p))
447+
def location(p: SourcePosition): Option[lsp4j.Location] =
448+
range(p).map(r => new lsp4j.Location(toUri(p.source).toString, r))
439449

440450
/** Convert a MessageContainer to an lsp4j.Diagnostic */
441451
def diagnostic(mc: MessageContainer): Option[lsp4j.Diagnostic] =
@@ -457,8 +467,9 @@ object DottyLanguageServer {
457467
}
458468

459469
val code = mc.contained().errorId.errorNumber.toString
460-
Some(new lsp4j.Diagnostic(
461-
range(mc.pos), mc.message, severity(mc.level), /*source =*/ "", code))
470+
range(mc.pos).map(r =>
471+
new lsp4j.Diagnostic(
472+
r, mc.message, severity(mc.level), /*source =*/ "", code))
462473
}
463474

464475
/** Create an lsp4j.CompletionItem from a Symbol */
@@ -506,7 +517,7 @@ object DottyLanguageServer {
506517
}
507518

508519
/** Create an lsp4j.SymbolInfo from a Symbol and a SourcePosition */
509-
def symbolInfo(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): lsp4j.SymbolInformation = {
520+
def symbolInfo(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Option[lsp4j.SymbolInformation] = {
510521
def symbolKind(sym: Symbol)(implicit ctx: Context): lsp4j.SymbolKind = {
511522
import lsp4j.{SymbolKind => SK}
512523

@@ -531,6 +542,6 @@ object DottyLanguageServer {
531542
else
532543
null
533544

534-
new lsp4j.SymbolInformation(name, symbolKind(sym), location(pos), containerName)
545+
location(pos).map(l => new lsp4j.SymbolInformation(name, symbolKind(sym), l, containerName))
535546
}
536547
}

language-server/test/dotty/tools/languageserver/DocumentSymbolTest.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import dotty.tools.languageserver.util.Code._
88

99
class DocumentSymbolTest {
1010

11+
@Test def withErroneousTree: Unit =
12+
code"class ${m1}Foo$m2 { def }"
13+
.withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class))
14+
1115
@Test def documentSymbol0: Unit =
1216
code"class ${m1}Foo$m2".withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class))
1317

0 commit comments

Comments
 (0)