@@ -1147,5 +1147,91 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
11471147 case _ =>
11481148 EmptyTree
11491149 }
1150+
1151+ /**
1152+ * The symbols that are imported with `expr.name`
1153+ *
1154+ * @param expr The base of the import statement
1155+ * @param name The name that is being imported.
1156+ * @return All the symbols that would be imported with `expr.name`.
1157+ */
1158+ def importedSymbols (expr : Tree , name : Name )(implicit ctx : Context ): List [Symbol ] = {
1159+ def lookup (name : Name ): Symbol = expr.tpe.member(name).symbol
1160+ val symbols =
1161+ List (lookup(name.toTermName),
1162+ lookup(name.toTypeName),
1163+ lookup(name.moduleClassName),
1164+ lookup(name.sourceModuleName))
1165+
1166+ symbols.map(_.sourceSymbol).filter(_.exists).distinct
1167+ }
1168+
1169+ /**
1170+ * All the symbols that are imported by the first selector of `imp` that matches
1171+ * `selectorPredicate`.
1172+ *
1173+ * @param imp The import statement to analyze
1174+ * @param selectorPredicate A test to find the selector to use.
1175+ * @return The symbols imported.
1176+ */
1177+ def importedSymbols (imp : Import ,
1178+ selectorPredicate : untpd.Tree => Boolean = util.common.alwaysTrue)
1179+ (implicit ctx : Context ): List [Symbol ] = {
1180+ imp.selectors.find(selectorPredicate) match {
1181+ case Some (id : untpd.Ident ) =>
1182+ importedSymbols(imp.expr, id.name)
1183+ case Some (Thicket ((id : untpd.Ident ) :: (_ : untpd.Ident ) :: Nil )) =>
1184+ importedSymbols(imp.expr, id.name)
1185+ case _ =>
1186+ Nil
1187+ }
1188+ }
1189+
1190+ /**
1191+ * The list of select trees that resolve to the same symbols as the ones that are imported
1192+ * by `imp`.
1193+ */
1194+ def importSelections (imp : Import )(implicit ctx : Context ): List [Select ] = {
1195+ def imported (sym : Symbol , id : untpd.Ident , rename : Option [untpd.Ident ]): List [Select ] = {
1196+ // Give a zero-extent position to the qualifier to prevent it from being included several
1197+ // times in results in the language server.
1198+ val noPosExpr = focusPositions(imp.expr)
1199+ val selectTree = Select (noPosExpr, sym.name).withPos(id.pos)
1200+ rename match {
1201+ case None =>
1202+ selectTree :: Nil
1203+ case Some (rename) =>
1204+ // Get the type of the symbol that is actually selected, and construct a select
1205+ // node with the new name and the type of the real symbol.
1206+ val name = if (sym.name.isTypeName) rename.name.toTypeName else rename.name
1207+ val actual = Select (noPosExpr, sym.name)
1208+ val renameTree = Select (noPosExpr, name).withPos(rename.pos).withType(actual.tpe)
1209+ selectTree :: renameTree :: Nil
1210+ }
1211+ }
1212+
1213+ imp.selectors.flatMap {
1214+ case Ident (nme.WILDCARD ) =>
1215+ Nil
1216+ case id : untpd.Ident =>
1217+ importedSymbols(imp.expr, id.name).flatMap { sym =>
1218+ imported(sym, id, None )
1219+ }
1220+ case Thicket ((id : untpd.Ident ) :: (newName : untpd.Ident ) :: Nil ) =>
1221+ importedSymbols(imp.expr, id.name).flatMap { sym =>
1222+ imported(sym, id, Some (newName))
1223+ }
1224+ }
1225+ }
1226+
1227+ /** Replaces all positions in `tree` with zero-extent positions */
1228+ private def focusPositions (tree : Tree )(implicit ctx : Context ): Tree = {
1229+ val transformer = new tpd.TreeMap {
1230+ override def transform (tree : Tree )(implicit ctx : Context ): Tree = {
1231+ super .transform(tree).withPos(tree.pos.focus)
1232+ }
1233+ }
1234+ transformer.transform(tree)
1235+ }
11501236}
11511237
0 commit comments