@@ -1147,5 +1147,91 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
1147
1147
case _ =>
1148
1148
EmptyTree
1149
1149
}
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
+ }
1150
1236
}
1151
1237
0 commit comments