@@ -46,6 +46,16 @@ case class Completion(label: String, description: String, symbols: List[Symbol])
4646
4747object Completion :
4848
49+ def scopeContext (pos : SourcePosition )(using Context ): CompletionResult =
50+ val tpdPath = Interactive .pathTo(ctx.compilationUnit.tpdTree, pos.span)
51+ val completionContext = Interactive .contextOfPath(tpdPath).withPhase(Phases .typerPhase)
52+ inContext(completionContext):
53+ val untpdPath = Interactive .resolveTypedOrUntypedPath(tpdPath, pos)
54+ val mode = completionMode(untpdPath, pos, forSymbolSearch = true )
55+ val rawPrefix = completionPrefix(untpdPath, pos)
56+ val completer = new Completer (mode, pos, untpdPath, _ => true )
57+ completer.scopeCompletions
58+
4959 /** Get possible completions from tree at `pos`
5060 *
5161 * @return offset and list of symbols for possible completions
@@ -58,7 +68,6 @@ object Completion:
5868 val mode = completionMode(untpdPath, pos)
5969 val rawPrefix = completionPrefix(untpdPath, pos)
6070 val completions = rawCompletions(pos, mode, rawPrefix, tpdPath, untpdPath)
61-
6271 postProcessCompletions(untpdPath, completions, rawPrefix)
6372
6473 /** Get possible completions from tree at `pos`
@@ -87,7 +96,7 @@ object Completion:
8796 *
8897 * Otherwise, provide no completion suggestion.
8998 */
90- def completionMode (path : List [untpd.Tree ], pos : SourcePosition ): Mode = path match
99+ def completionMode (path : List [untpd.Tree ], pos : SourcePosition , forSymbolSearch : Boolean = false ): Mode = path match
91100 // Ignore `package foo@@` and `package foo.bar@@`
92101 case ((_ : tpd.Select ) | (_ : tpd.Ident )):: (_ : tpd.PackageDef ) :: _ => Mode .None
93102 case GenericImportSelector (sel) =>
@@ -100,11 +109,14 @@ object Completion:
100109 case untpd.Literal (Constants .Constant (_ : String )) :: _ => Mode .Term | Mode .Scope // literal completions
101110 case (ref : untpd.RefTree ) :: _ =>
102111 val maybeSelectMembers = if ref.isInstanceOf [untpd.Select ] then Mode .Member else Mode .Scope
103-
104- if (ref.name.isTermName) Mode .Term | maybeSelectMembers
112+ if (forSymbolSearch) then Mode . Term | Mode . Type | maybeSelectMembers
113+ else if (ref.name.isTermName) Mode .Term | maybeSelectMembers
105114 else if (ref.name.isTypeName) Mode .Type | maybeSelectMembers
106115 else Mode .None
107116
117+ case (_ : tpd.TypeTree | _ : tpd.MemberDef ) :: _ if forSymbolSearch => Mode .Type | Mode .Term
118+ case (_ : tpd.CaseDef ) :: _ if forSymbolSearch => Mode .Type | Mode .Term
119+ case Nil if forSymbolSearch => Mode .Type | Mode .Term
108120 case _ => Mode .None
109121
110122 /** When dealing with <errors> in varios palces we check to see if they are
@@ -227,14 +239,14 @@ object Completion:
227239 val result = adjustedPath match
228240 // Ignore synthetic select from `This` because in code it was `Ident`
229241 // See example in dotty.tools.languageserver.CompletionTest.syntheticThis
230- case tpd.Select (qual @ tpd.This (_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions
242+ case tpd.Select (qual @ tpd.This (_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions.names
231243 case StringContextApplication (qual) =>
232- completer.scopeCompletions ++ completer.selectionCompletions(qual)
244+ completer.scopeCompletions.names ++ completer.selectionCompletions(qual)
233245 case tpd.Select (qual, _) :: _ if qual.typeOpt.hasSimpleKind =>
234246 completer.selectionCompletions(qual)
235247 case tpd.Select (qual, _) :: _ => Map .empty
236248 case (tree : tpd.ImportOrExport ) :: _ => completer.directMemberCompletions(tree.expr)
237- case _ => completer.scopeCompletions
249+ case _ => completer.scopeCompletions.names
238250
239251 interactiv.println(i """ completion info with pos = $pos,
240252 | term = ${completer.mode.is(Mode .Term )},
@@ -335,6 +347,7 @@ object Completion:
335347 (completionMode.is(Mode .Term ) && (sym.isTerm || sym.is(ModuleClass ))
336348 || (completionMode.is(Mode .Type ) && (sym.isType || sym.isStableMember)))
337349 )
350+ end isValidCompletionSymbol
338351
339352 given ScopeOrdering (using Context ): Ordering [Seq [SingleDenotation ]] with
340353 val order =
@@ -368,7 +381,7 @@ object Completion:
368381 * (even if the import follows it syntactically)
369382 * - a more deeply nested import shadowing a member or a local definition causes an ambiguity
370383 */
371- def scopeCompletions (using context : Context ): CompletionMap =
384+ def scopeCompletions (using context : Context ): CompletionResult =
372385
373386 /** Temporary data structure representing denotations with the same name introduced in a given scope
374387 * as a member of a type, by a local definition or by an import clause
@@ -379,14 +392,19 @@ object Completion:
379392 ScopedDenotations (denots.filter(includeFn), ctx)
380393
381394 val mappings = collection.mutable.Map .empty[Name , List [ScopedDenotations ]].withDefaultValue(List .empty)
395+ val renames = collection.mutable.Map .empty[Symbol , Name ]
382396 def addMapping (name : Name , denots : ScopedDenotations ) =
383397 mappings(name) = mappings(name) :+ denots
384398
385399 ctx.outersIterator.foreach { case ctx @ given Context =>
386400 if ctx.isImportContext then
387- importedCompletions.foreach { (name, denots) =>
401+ val imported = importedCompletions
402+ imported.names.foreach { (name, denots) =>
388403 addMapping(name, ScopedDenotations (denots, ctx, include(_, name)))
389404 }
405+ imported.renames.foreach { (name, newName) =>
406+ renames(name) = newName
407+ }
390408 else if ctx.owner.isClass then
391409 accessibleMembers(ctx.owner.thisType)
392410 .groupByName.foreach { (name, denots) =>
@@ -430,7 +448,6 @@ object Completion:
430448 // most deeply nested member or local definition if not shadowed by an import
431449 case Some (local) if local.ctx.scope == first.ctx.scope =>
432450 resultMappings += name -> local.denots
433-
434451 case None if isSingleImport || isImportedInDifferentScope || isSameSymbolImportedDouble =>
435452 resultMappings += name -> first.denots
436453 case None if notConflictingWithDefaults =>
@@ -440,7 +457,7 @@ object Completion:
440457 }
441458 }
442459
443- resultMappings
460+ CompletionResult ( resultMappings, renames.toMap)
444461 end scopeCompletions
445462
446463 /** Widen only those types which are applied or are exactly nothing
@@ -474,15 +491,20 @@ object Completion:
474491 /** Completions introduced by imports directly in this context.
475492 * Completions from outer contexts are not included.
476493 */
477- private def importedCompletions (using Context ): CompletionMap =
494+ private def importedCompletions (using Context ): CompletionResult =
478495 val imp = ctx.importInfo
496+ val renames = collection.mutable.Map .empty[Symbol , Name ]
479497
480498 if imp == null then
481- Map .empty
499+ CompletionResult ( Map .empty, Map .empty)
482500 else
483501 def fromImport (name : Name , nameInScope : Name ): Seq [(Name , SingleDenotation )] =
484502 imp.site.member(name).alternatives
485- .collect { case denot if include(denot, nameInScope) => nameInScope -> denot }
503+ .collect { case denot if include(denot, nameInScope) =>
504+ if name != nameInScope then
505+ renames(denot.symbol) = nameInScope
506+ nameInScope -> denot
507+ }
486508
487509 val givenImports = imp.importedImplicits
488510 .map { ref => (ref.implicitName: Name , ref.underlyingRef.denot.asSingleDenotation) }
@@ -508,7 +530,8 @@ object Completion:
508530 fromImport(original.toTypeName, nameInScope.toTypeName)
509531 }.toSeq.groupByName
510532
511- givenImports ++ wildcardMembers ++ explicitMembers
533+ val results = givenImports ++ wildcardMembers ++ explicitMembers
534+ CompletionResult (results, renames.toMap)
512535 end importedCompletions
513536
514537 /** Completions from implicit conversions including old style extensions using implicit classes */
@@ -562,7 +585,7 @@ object Completion:
562585
563586 // 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
564587 val termCompleter = new Completer (Mode .Term , pos, untpdPath, matches)
565- val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap:
588+ val extMethodsInScope = termCompleter.scopeCompletions.names. toList.flatMap:
566589 case (name, denots) => denots.collect:
567590 case d : SymDenotation if d.isTerm && d.termRef.symbol.is(Extension ) => (d.termRef, name.asTermName)
568591
@@ -664,6 +687,7 @@ object Completion:
664687
665688 private type CompletionMap = Map [Name , Seq [SingleDenotation ]]
666689
690+ case class CompletionResult (names : Map [Name , Seq [SingleDenotation ]], renames : Map [Symbol , Name ])
667691 /**
668692 * The completion mode: defines what kinds of symbols should be included in the completion
669693 * results.
0 commit comments