@@ -137,7 +137,7 @@ object Completion {
137137
138138 private class CompletionBuffer (val mode : Mode , val prefix : String , pos : SourcePosition ) {
139139
140- private [this ] val completions = Scopes .newScope.openForMutations
140+ private [this ] val completions = new RenameAwareScope
141141
142142 /**
143143 * Return the list of symbols that shoudl be included in completion results.
@@ -146,7 +146,11 @@ object Completion {
146146 * the same `Completion`.
147147 */
148148 def getCompletions (implicit ctx : Context ): List [Completion ] = {
149- val groupedSymbols = completions.toList.groupBy(_.name.stripModuleClassSuffix.toSimpleName).toList
149+ val groupedSymbols = {
150+ val symbols = completions.toListWithNames
151+ val nameToSymbols = symbols.groupBy(_._2.stripModuleClassSuffix.toSimpleName)
152+ nameToSymbols.mapValues(_.map(_._1)).toList
153+ }
150154 groupedSymbols.map { case (name, symbols) =>
151155 val typesFirst = symbols.sortWith((s, _) => s.isType)
152156 // Use distinct to remove duplicates with class, module class, etc.
@@ -173,11 +177,11 @@ object Completion {
173177 if (ctx.owner.isClass) {
174178 addAccessibleMembers(ctx.owner.thisType)
175179 ctx.owner.asClass.classInfo.selfInfo match {
176- case selfSym : Symbol => add(selfSym)
180+ case selfSym : Symbol => add(selfSym, selfSym.name )
177181 case _ =>
178182 }
179183 }
180- else if (ctx.scope != null ) ctx.scope.foreach(add)
184+ else if (ctx.scope != null ) ctx.scope.foreach(s => add(s, s.name) )
181185
182186 addImportCompletions
183187
@@ -208,15 +212,16 @@ object Completion {
208212 * If `sym` exists, no symbol with the same name is already included, and it satisfies the
209213 * inclusion filter, then add it to the completions.
210214 */
211- private def add (sym : Symbol )(implicit ctx : Context ) =
212- if (sym.exists && ! completions.lookup(sym.name ).exists && include(sym)) {
213- completions.enter(sym)
215+ private def add (sym : Symbol , nameInScope : Name )(implicit ctx : Context ) =
216+ if (sym.exists && ! completions.lookup(nameInScope ).exists && include(sym, nameInScope )) {
217+ completions.enter(sym, nameInScope )
214218 }
215219
216220 /** Lookup members `name` from `site`, and try to add them to the completion list. */
217- private def addMember (site : Type , name : Name )(implicit ctx : Context ) =
218- if (! completions.lookup(name).exists)
219- for (alt <- site.member(name).alternatives) add(alt.symbol)
221+ private def addMember (site : Type , name : Name , nameInScope : Name )(implicit ctx : Context ) =
222+ if (! completions.lookup(nameInScope).exists) {
223+ for (alt <- site.member(name).alternatives) add(alt.symbol, nameInScope)
224+ }
220225
221226 /** Include in completion sets only symbols that
222227 * 1. start with given name prefix, and
@@ -230,9 +235,9 @@ object Completion {
230235 * as completion results. However, if a user explicitly writes all '$' characters in an
231236 * identifier, we should complete the rest.
232237 */
233- private def include (sym : Symbol )(implicit ctx : Context ): Boolean =
234- sym.name .startsWith(prefix) &&
235- ! sym.name .toString.drop(prefix.length).contains('$' ) &&
238+ private def include (sym : Symbol , nameInScope : Name )(implicit ctx : Context ): Boolean =
239+ nameInScope .startsWith(prefix) &&
240+ ! nameInScope .toString.drop(prefix.length).contains('$' ) &&
236241 ! sym.isPrimaryConstructor &&
237242 (! sym.is(Package ) || ! sym.moduleClass.exists) &&
238243 ! sym.is(allOf(Mutable , Accessor )) &&
@@ -249,20 +254,20 @@ object Completion {
249254 */
250255 private def accessibleMembers (site : Type )(implicit ctx : Context ): Seq [Symbol ] = site match {
251256 case site : NamedType if site.symbol.is(Package ) =>
252- site.decls.toList.filter(include) // Don't look inside package members -- it's too expensive.
257+ site.decls.toList.filter(sym => include(sym, sym.name) ) // Don't look inside package members -- it's too expensive.
253258 case _ =>
254259 def appendMemberSyms (name : Name , buf : mutable.Buffer [SingleDenotation ]): Unit =
255260 try buf ++= site.member(name).alternatives
256261 catch { case ex : TypeError => }
257262 site.memberDenots(takeAllFilter, appendMemberSyms).collect {
258- case mbr if include(mbr.symbol) => mbr.accessibleFrom(site, superAccess = true ).symbol
263+ case mbr if include(mbr.symbol, mbr.symbol.name ) => mbr.accessibleFrom(site, superAccess = true ).symbol
259264 case _ => NoSymbol
260265 }.filter(_.exists)
261266 }
262267
263268 /** Add all the accessible members of `site` in `info`. */
264269 private def addAccessibleMembers (site : Type )(implicit ctx : Context ): Unit =
265- for (mbr <- accessibleMembers(site)) addMember(site, mbr.name)
270+ for (mbr <- accessibleMembers(site)) addMember(site, mbr.name, mbr.name )
266271
267272 /**
268273 * Add in `info` the symbols that are imported by `ctx.importInfo`. If this is a wildcard import,
@@ -271,17 +276,18 @@ object Completion {
271276 private def addImportCompletions (implicit ctx : Context ): Unit = {
272277 val imp = ctx.importInfo
273278 if (imp != null ) {
274- def addImport (name : TermName ) = {
275- addMember(imp.site, name)
276- addMember(imp.site, name.toTypeName)
279+ def addImport (name : TermName , nameInScope : TermName ) = {
280+ addMember(imp.site, name, nameInScope)
281+ addMember(imp.site, name.toTypeName, nameInScope.toTypeName)
282+ }
283+ imp.reverseMapping.foreachBinding { (nameInScope, original) =>
284+ if (original != nameInScope || ! imp.excluded.contains(original)) {
285+ addImport(original, nameInScope)
286+ }
277287 }
278- // FIXME: We need to also take renamed items into account for completions,
279- // That means we have to return list of a pairs (Name, Symbol) instead of a list
280- // of symbols from `completions`.!=
281- for (imported <- imp.originals if ! imp.excluded.contains(imported)) addImport(imported)
282288 if (imp.isWildcardImport)
283289 for (mbr <- accessibleMembers(imp.site) if ! imp.excluded.contains(mbr.name.toTermName))
284- addMember(imp.site, mbr.name)
290+ addMember(imp.site, mbr.name, mbr.name )
285291 }
286292 }
287293
@@ -324,4 +330,23 @@ object Completion {
324330 val Import : Mode = new Mode (4 ) | Term | Type
325331 }
326332
333+ /** A scope that tracks renames of the entered symbols.
334+ * Useful for providing completions for renamed symbols
335+ * in the REPL and the IDE.
336+ */
337+ private class RenameAwareScope extends Scopes .MutableScope {
338+ private [this ] val renames : mutable.Map [Symbol , Name ] = mutable.Map .empty
339+
340+ /** Enter the symbol `sym` in this scope, recording a potential renaming. */
341+ def enter [T <: Symbol ](sym : T , name : Name )(implicit ctx : Context ): T = {
342+ if (name != sym.name) renames += sym -> name
343+ newScopeEntry(name, sym)
344+ sym
345+ }
346+
347+ /** Lists the symbols in this scope along with the name associated with them. */
348+ def toListWithNames (implicit ctx : Context ): List [(Symbol , Name )] =
349+ toList.map(sym => (sym, renames.get(sym).getOrElse(sym.name)))
350+ }
351+
327352}
0 commit comments