@@ -48,6 +48,16 @@ case class Completion(label: String, description: String, symbols: List[Symbol])
4848
4949object Completion :
5050
51+ def scopeContext (pos : SourcePosition )(using Context ): CompletionResult =
52+ val tpdPath = Interactive .pathTo(ctx.compilationUnit.tpdTree, pos.span)
53+ val completionContext = Interactive .contextOfPath(tpdPath).withPhase(Phases .typerPhase)
54+ inContext(completionContext):
55+ val untpdPath = Interactive .resolveTypedOrUntypedPath(tpdPath, pos)
56+ val mode = completionMode(untpdPath, pos, forSymbolSearch = true )
57+ val rawPrefix = completionPrefix(untpdPath, pos)
58+ val completer = new Completer (mode, pos, untpdPath, _ => true )
59+ completer.scopeCompletions
60+
5161 /** Get possible completions from tree at `pos`
5262 *
5363 * @return offset and list of symbols for possible completions
@@ -60,7 +70,6 @@ object Completion:
6070 val mode = completionMode(untpdPath, pos)
6171 val rawPrefix = completionPrefix(untpdPath, pos)
6272 val completions = rawCompletions(pos, mode, rawPrefix, tpdPath, untpdPath)
63-
6473 postProcessCompletions(untpdPath, completions, rawPrefix)
6574
6675 /** Get possible completions from tree at `pos`
@@ -89,7 +98,7 @@ object Completion:
8998 *
9099 * Otherwise, provide no completion suggestion.
91100 */
92- def completionMode (path : List [untpd.Tree ], pos : SourcePosition ): Mode = path match
101+ def completionMode (path : List [untpd.Tree ], pos : SourcePosition , forSymbolSearch : Boolean = false ): Mode = path match
93102 // Ignore `package foo@@` and `package foo.bar@@`
94103 case ((_ : tpd.Select ) | (_ : tpd.Ident )):: (_ : tpd.PackageDef ) :: _ => Mode .None
95104 case GenericImportSelector (sel) =>
@@ -102,11 +111,14 @@ object Completion:
102111 case untpd.Literal (Constants .Constant (_ : String )) :: _ => Mode .Term | Mode .Scope // literal completions
103112 case (ref : untpd.RefTree ) :: _ =>
104113 val maybeSelectMembers = if ref.isInstanceOf [untpd.Select ] then Mode .Member else Mode .Scope
105-
106- if (ref.name.isTermName) Mode .Term | maybeSelectMembers
114+ if (forSymbolSearch) then Mode . Term | Mode . Type | maybeSelectMembers
115+ else if (ref.name.isTermName) Mode .Term | maybeSelectMembers
107116 else if (ref.name.isTypeName) Mode .Type | maybeSelectMembers
108117 else Mode .None
109118
119+ case (_ : tpd.TypeTree | _ : tpd.MemberDef ) :: _ if forSymbolSearch => Mode .Type | Mode .Term
120+ case (_ : tpd.CaseDef ) :: _ if forSymbolSearch => Mode .Type | Mode .Term
121+ case Nil if forSymbolSearch => Mode .Type | Mode .Term
110122 case _ => Mode .None
111123
112124 /** When dealing with <errors> in varios palces we check to see if they are
@@ -174,12 +186,12 @@ object Completion:
174186 case _ => None
175187
176188 private object StringContextApplication :
177- def unapply (path : List [tpd.Tree ]): Option [tpd.Apply ] =
189+ def unapply (path : List [tpd.Tree ]): Option [tpd.Apply ] =
178190 path match
179191 case tpd.Select (qual @ tpd.Apply (tpd.Select (tpd.Select (_, StdNames .nme.StringContext ), _), _), _) :: _ =>
180192 Some (qual)
181193 case _ => None
182-
194+
183195
184196 /** Inspect `path` to determine the offset where the completion result should be inserted. */
185197 def completionOffset (untpdPath : List [untpd.Tree ]): Int =
@@ -230,14 +242,14 @@ object Completion:
230242 val result = adjustedPath match
231243 // Ignore synthetic select from `This` because in code it was `Ident`
232244 // See example in dotty.tools.languageserver.CompletionTest.syntheticThis
233- case tpd.Select (qual @ tpd.This (_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions
245+ case tpd.Select (qual @ tpd.This (_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions.names
234246 case StringContextApplication (qual) =>
235- completer.scopeCompletions ++ completer.selectionCompletions(qual)
236- case tpd.Select (qual, _) :: _ if qual.typeOpt.hasSimpleKind =>
247+ completer.scopeCompletions.names ++ completer.selectionCompletions(qual)
248+ case tpd.Select (qual, _) :: _ if qual.typeOpt.hasSimpleKind =>
237249 completer.selectionCompletions(qual)
238250 case tpd.Select (qual, _) :: _ => Map .empty
239251 case (tree : tpd.ImportOrExport ) :: _ => completer.directMemberCompletions(tree.expr)
240- case _ => completer.scopeCompletions
252+ case _ => completer.scopeCompletions.names
241253
242254 interactiv.println(i """ completion info with pos = $pos,
243255 | term = ${completer.mode.is(Mode .Term )},
@@ -338,6 +350,7 @@ object Completion:
338350 (completionMode.is(Mode .Term ) && (sym.isTerm || sym.is(ModuleClass ))
339351 || (completionMode.is(Mode .Type ) && (sym.isType || sym.isStableMember)))
340352 )
353+ end isValidCompletionSymbol
341354
342355 given ScopeOrdering (using Context ): Ordering [Seq [SingleDenotation ]] with
343356 val order =
@@ -371,7 +384,7 @@ object Completion:
371384 * (even if the import follows it syntactically)
372385 * - a more deeply nested import shadowing a member or a local definition causes an ambiguity
373386 */
374- def scopeCompletions (using context : Context ): CompletionMap =
387+ def scopeCompletions (using context : Context ): CompletionResult =
375388
376389 /** Temporary data structure representing denotations with the same name introduced in a given scope
377390 * as a member of a type, by a local definition or by an import clause
@@ -382,14 +395,19 @@ object Completion:
382395 ScopedDenotations (denots.filter(includeFn), ctx)
383396
384397 val mappings = collection.mutable.Map .empty[Name , List [ScopedDenotations ]].withDefaultValue(List .empty)
398+ val renames = collection.mutable.Map .empty[Symbol , Name ]
385399 def addMapping (name : Name , denots : ScopedDenotations ) =
386400 mappings(name) = mappings(name) :+ denots
387401
388402 ctx.outersIterator.foreach { case ctx @ given Context =>
389403 if ctx.isImportContext then
390- importedCompletions.foreach { (name, denots) =>
404+ val imported = importedCompletions
405+ imported.names.foreach { (name, denots) =>
391406 addMapping(name, ScopedDenotations (denots, ctx, include(_, name)))
392407 }
408+ imported.renames.foreach { (name, newName) =>
409+ renames(name) = newName
410+ }
393411 else if ctx.owner.isClass then
394412 accessibleMembers(ctx.owner.thisType)
395413 .groupByName.foreach { (name, denots) =>
@@ -433,7 +451,6 @@ object Completion:
433451 // most deeply nested member or local definition if not shadowed by an import
434452 case Some (local) if local.ctx.scope == first.ctx.scope =>
435453 resultMappings += name -> local.denots
436-
437454 case None if isSingleImport || isImportedInDifferentScope || isSameSymbolImportedDouble =>
438455 resultMappings += name -> first.denots
439456 case None if notConflictingWithDefaults =>
@@ -443,7 +460,7 @@ object Completion:
443460 }
444461 }
445462
446- resultMappings
463+ CompletionResult ( resultMappings, renames.toMap)
447464 end scopeCompletions
448465
449466 /** Widen only those types which are applied or are exactly nothing
@@ -485,15 +502,20 @@ object Completion:
485502 /** Completions introduced by imports directly in this context.
486503 * Completions from outer contexts are not included.
487504 */
488- private def importedCompletions (using Context ): CompletionMap =
505+ private def importedCompletions (using Context ): CompletionResult =
489506 val imp = ctx.importInfo
507+ val renames = collection.mutable.Map .empty[Symbol , Name ]
490508
491509 if imp == null then
492- Map .empty
510+ CompletionResult ( Map .empty, Map .empty)
493511 else
494512 def fromImport (name : Name , nameInScope : Name ): Seq [(Name , SingleDenotation )] =
495513 imp.site.member(name).alternatives
496- .collect { case denot if include(denot, nameInScope) => nameInScope -> denot }
514+ .collect { case denot if include(denot, nameInScope) =>
515+ if name != nameInScope then
516+ renames(denot.symbol) = nameInScope
517+ nameInScope -> denot
518+ }
497519
498520 val givenImports = imp.importedImplicits
499521 .map { ref => (ref.implicitName: Name , ref.underlyingRef.denot.asSingleDenotation) }
@@ -519,7 +541,8 @@ object Completion:
519541 fromImport(original.toTypeName, nameInScope.toTypeName)
520542 }.toSeq.groupByName
521543
522- givenImports ++ wildcardMembers ++ explicitMembers
544+ val results = givenImports ++ wildcardMembers ++ explicitMembers
545+ CompletionResult (results, renames.toMap)
523546 end importedCompletions
524547
525548 /** Completions from implicit conversions including old style extensions using implicit classes */
@@ -597,7 +620,7 @@ object Completion:
597620
598621 // 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
599622 val termCompleter = new Completer (Mode .Term , pos, untpdPath, matches)
600- val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap:
623+ val extMethodsInScope = termCompleter.scopeCompletions.names. toList.flatMap:
601624 case (name, denots) => denots.collect:
602625 case d : SymDenotation if d.isTerm && d.termRef.symbol.is(Extension ) => (d.termRef, name.asTermName)
603626
@@ -699,6 +722,7 @@ object Completion:
699722
700723 private type CompletionMap = Map [Name , Seq [SingleDenotation ]]
701724
725+ case class CompletionResult (names : Map [Name , Seq [SingleDenotation ]], renames : Map [Symbol , Name ])
702726 /**
703727 * The completion mode: defines what kinds of symbols should be included in the completion
704728 * results.
0 commit comments