Skip to content

Commit edf6230

Browse files
committed
Support multiple imports per line
1 parent f49ab22 commit edf6230

File tree

4 files changed

+78
-26
lines changed

4 files changed

+78
-26
lines changed

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

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -322,20 +322,23 @@ object Interactive {
322322

323323
def traverser(source: SourceFile) = {
324324
new untpd.TreeTraverser {
325-
private def handleImport(imported: List[Symbol],
326-
uexpr: untpd.Tree,
327-
id: untpd.Ident,
328-
rename: Option[untpd.Ident]): Unit = {
329-
val expr = uexpr.asInstanceOf[tpd.Tree]
325+
private def handleImport(imp: tpd.Import): Unit = {
326+
val imported =
327+
imp.selectors.flatMap {
328+
case id: untpd.Ident =>
329+
importedSymbols(imp.expr, id.name).map((_, id, None))
330+
case Thicket((id: untpd.Ident) :: (newName: untpd.Ident) :: Nil) =>
331+
importedSymbols(imp.expr, id.name).map((_, id, Some(newName)))
332+
}
330333
imported match {
331334
case Nil =>
332-
traverse(expr)
335+
traverse(imp.expr)
333336
case syms =>
334-
syms.foreach { sym =>
335-
val tree = tpd.Select(expr, sym.name).withPos(id.pos)
337+
syms.foreach { case (sym, name, rename) =>
338+
val tree = tpd.Select(imp.expr, sym.name).withPos(name.pos)
336339
val renameTree = rename.map { r =>
337340
val name = if (sym.name.isTypeName) r.name.toTypeName else r.name
338-
RenameTree(name, tpd.Select(expr, sym.name)).withPos(r.pos)
341+
RenameTree(name, tpd.Select(imp.expr, sym.name)).withPos(r.pos)
339342
}
340343
renameTree.foreach(traverse)
341344
traverse(tree)
@@ -344,12 +347,8 @@ object Interactive {
344347
}
345348
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
346349
tree match {
347-
case imp @ Import(uexpr, (id: untpd.Ident) :: Nil) if includeImports =>
348-
val imported = importedSymbols(imp.asInstanceOf[tpd.Import])
349-
handleImport(imported, uexpr, id, None)
350-
case imp @ Import(uexpr, Thicket((id: untpd.Ident) :: (rename: untpd.Ident) :: Nil) :: Nil) if includeImports =>
351-
val imported = importedSymbols(imp.asInstanceOf[tpd.Import])
352-
handleImport(imported, uexpr, id, Some(rename))
350+
case imp: untpd.Import if includeImports =>
351+
handleImport(imp.asInstanceOf[tpd.Import])
353352
case utree: untpd.NameTree if tree.hasType =>
354353
val tree = utree.asInstanceOf[tpd.NameTree]
355354
if (tree.symbol.exists
@@ -573,25 +572,33 @@ object Interactive {
573572
private def importedSymbols(imp: tpd.Import,
574573
selectorPredicate: untpd.Tree => Boolean = util.common.alwaysTrue)
575574
(implicit ctx: Context): List[Symbol] = {
576-
def lookup0(name: Name): Symbol = imp.expr.tpe.member(name).symbol
577-
def lookup(name: Name): List[Symbol] = {
578-
lookup0(name.toTermName) ::
579-
lookup0(name.toTypeName) ::
580-
lookup0(name.moduleClassName) ::
581-
lookup0(name.sourceModuleName) :: Nil
582-
}
583-
584575
val symbols = imp.selectors.find(selectorPredicate) match {
585576
case Some(id: untpd.Ident) =>
586-
lookup(id.name)
577+
importedSymbols(imp.expr, id.name)
587578
case Some(Thicket((id: untpd.Ident) :: (_: untpd.Ident) :: Nil)) =>
588-
lookup(id.name)
589-
case _ => Nil
579+
importedSymbols(imp.expr, id.name)
580+
case _ =>
581+
Nil
590582
}
591583

592584
symbols.map(sourceSymbol).filter(_.exists).distinct
593585
}
594586

587+
/**
588+
* The symbols that are imported with `expr.name`
589+
*
590+
* @param expr The base of the import statement
591+
* @param name The name that is being imported.
592+
* @return All the symbols that would be imported with `expr.name`.
593+
*/
594+
private def importedSymbols(expr: tpd.Tree, name: Name)(implicit ctx: Context): List[Symbol] = {
595+
def lookup(name: Name): Symbol = expr.tpe.member(name).symbol
596+
lookup(name.toTermName) ::
597+
lookup(name.toTypeName) ::
598+
lookup(name.moduleClassName) ::
599+
lookup(name.sourceModuleName) :: Nil
600+
}
601+
595602
/**
596603
* Used to represent a renaming import `{foo => bar}`.
597604
* We need this because the name of the tree must be the new name, but the

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,17 @@ class DefinitionTest {
309309
.definition(m11 to m12, List(m3 to m4))
310310
}
311311

312+
@Test def multipleImportsPerLineWithRename: Unit = {
313+
withSources(
314+
code"""object A { class ${m1}B${m2}; class ${m3}C${m4} }""",
315+
code"""import A.{${m5}B${m6} => ${m7}B2${m8}, ${m9}C${m10} => ${m11}C2${m12}}
316+
class E"""
317+
).definition(m1 to m2, List(m1 to m2))
318+
.definition(m3 to m4, List(m3 to m4))
319+
.definition(m5 to m6, List(m1 to m2))
320+
.definition(m7 to m8, List(m1 to m2))
321+
.definition(m9 to m10, List(m3 to m4))
322+
.definition(m11 to m12, List(m3 to m4))
323+
}
324+
312325
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,17 @@ class HighlightTest {
113113
.highlight(m7 to m8, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read))
114114
}
115115

116+
@Test def multipleImportsPerLineWithRename: Unit = {
117+
withSources(
118+
code"""object A { class ${m1}B${m2}; class ${m3}C${m4} }
119+
import A.{${m5}B${m6} => ${m7}B2${m8}, ${m9}C${m10} => ${m11}C2${m12}}
120+
class E"""
121+
).highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read))
122+
.highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read), (m11 to m12, DocumentHighlightKind.Read))
123+
.highlight(m5 to m6, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read))
124+
.highlight(m7 to m8, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read))
125+
.highlight(m9 to m10, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read), (m11 to m12, DocumentHighlightKind.Read))
126+
.highlight(m11 to m12, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read), (m11 to m12, DocumentHighlightKind.Read))
127+
}
128+
116129
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,23 @@ class ReferencesTest {
327327
.references(m7 to m8, List(m5 to m6, m7 to m8), withDecl = false)
328328
}
329329

330+
@Test def multipleImportsPerLineWithRename: Unit = {
331+
withSources(
332+
code"""object A { class ${m1}B${m2}; class ${m3}C${m4} }""",
333+
code"""import A.{${m5}B${m6} => ${m7}B2${m8}, ${m9}C${m10} => ${m11}C2${m12}}
334+
class E"""
335+
).references(m1 to m2, List(m1 to m2, m5 to m6, m7 to m8), withDecl = true)
336+
.references(m1 to m2, List(m5 to m6, m7 to m8), withDecl = false)
337+
.references(m3 to m4, List(m3 to m4, m9 to m10, m11 to m12), withDecl = true)
338+
.references(m3 to m4, List(m9 to m10, m11 to m12), withDecl = false)
339+
.references(m5 to m6, List(m1 to m2, m5 to m6, m7 to m8), withDecl = true)
340+
.references(m5 to m6, List(m5 to m6, m7 to m8), withDecl = false)
341+
.references(m7 to m8, List(m1 to m2, m5 to m6, m7 to m8), withDecl = true)
342+
.references(m7 to m8, List(m5 to m6, m7 to m8), withDecl = false)
343+
.references(m9 to m10, List(m3 to m4, m9 to m10, m11 to m12), withDecl = true)
344+
.references(m9 to m10, List(m9 to m10, m11 to m12), withDecl = false)
345+
.references(m11 to m12, List(m3 to m4, m9 to m10, m11 to m12), withDecl = true)
346+
.references(m11 to m12, List(m9 to m10, m11 to m12), withDecl = false)
347+
}
348+
330349
}

0 commit comments

Comments
 (0)