@@ -46,6 +46,16 @@ case class Completion(label: String, description: String, symbols: List[Symbol])
46
46
47
47
object Completion :
48
48
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
+
49
59
/** Get possible completions from tree at `pos`
50
60
*
51
61
* @return offset and list of symbols for possible completions
@@ -58,7 +68,6 @@ object Completion:
58
68
val mode = completionMode(untpdPath, pos)
59
69
val rawPrefix = completionPrefix(untpdPath, pos)
60
70
val completions = rawCompletions(pos, mode, rawPrefix, tpdPath, untpdPath)
61
-
62
71
postProcessCompletions(untpdPath, completions, rawPrefix)
63
72
64
73
/** Get possible completions from tree at `pos`
@@ -87,7 +96,7 @@ object Completion:
87
96
*
88
97
* Otherwise, provide no completion suggestion.
89
98
*/
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
91
100
// Ignore `package foo@@` and `package foo.bar@@`
92
101
case ((_ : tpd.Select ) | (_ : tpd.Ident )):: (_ : tpd.PackageDef ) :: _ => Mode .None
93
102
case GenericImportSelector (sel) =>
@@ -100,11 +109,14 @@ object Completion:
100
109
case untpd.Literal (Constants .Constant (_ : String )) :: _ => Mode .Term | Mode .Scope // literal completions
101
110
case (ref : untpd.RefTree ) :: _ =>
102
111
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
105
114
else if (ref.name.isTypeName) Mode .Type | maybeSelectMembers
106
115
else Mode .None
107
116
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
108
120
case _ => Mode .None
109
121
110
122
/** When dealing with <errors> in varios palces we check to see if they are
@@ -227,14 +239,14 @@ object Completion:
227
239
val result = adjustedPath match
228
240
// Ignore synthetic select from `This` because in code it was `Ident`
229
241
// 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
231
243
case StringContextApplication (qual) =>
232
- completer.scopeCompletions ++ completer.selectionCompletions(qual)
244
+ completer.scopeCompletions.names ++ completer.selectionCompletions(qual)
233
245
case tpd.Select (qual, _) :: _ if qual.typeOpt.hasSimpleKind =>
234
246
completer.selectionCompletions(qual)
235
247
case tpd.Select (qual, _) :: _ => Map .empty
236
248
case (tree : tpd.ImportOrExport ) :: _ => completer.directMemberCompletions(tree.expr)
237
- case _ => completer.scopeCompletions
249
+ case _ => completer.scopeCompletions.names
238
250
239
251
interactiv.println(i """ completion info with pos = $pos,
240
252
| term = ${completer.mode.is(Mode .Term )},
@@ -335,6 +347,7 @@ object Completion:
335
347
(completionMode.is(Mode .Term ) && (sym.isTerm || sym.is(ModuleClass ))
336
348
|| (completionMode.is(Mode .Type ) && (sym.isType || sym.isStableMember)))
337
349
)
350
+ end isValidCompletionSymbol
338
351
339
352
given ScopeOrdering (using Context ): Ordering [Seq [SingleDenotation ]] with
340
353
val order =
@@ -368,7 +381,7 @@ object Completion:
368
381
* (even if the import follows it syntactically)
369
382
* - a more deeply nested import shadowing a member or a local definition causes an ambiguity
370
383
*/
371
- def scopeCompletions (using context : Context ): CompletionMap =
384
+ def scopeCompletions (using context : Context ): CompletionResult =
372
385
373
386
/** Temporary data structure representing denotations with the same name introduced in a given scope
374
387
* as a member of a type, by a local definition or by an import clause
@@ -379,14 +392,19 @@ object Completion:
379
392
ScopedDenotations (denots.filter(includeFn), ctx)
380
393
381
394
val mappings = collection.mutable.Map .empty[Name , List [ScopedDenotations ]].withDefaultValue(List .empty)
395
+ val renames = collection.mutable.Map .empty[Symbol , Name ]
382
396
def addMapping (name : Name , denots : ScopedDenotations ) =
383
397
mappings(name) = mappings(name) :+ denots
384
398
385
399
ctx.outersIterator.foreach { case ctx @ given Context =>
386
400
if ctx.isImportContext then
387
- importedCompletions.foreach { (name, denots) =>
401
+ val imported = importedCompletions
402
+ imported.names.foreach { (name, denots) =>
388
403
addMapping(name, ScopedDenotations (denots, ctx, include(_, name)))
389
404
}
405
+ imported.renames.foreach { (name, newName) =>
406
+ renames(name) = newName
407
+ }
390
408
else if ctx.owner.isClass then
391
409
accessibleMembers(ctx.owner.thisType)
392
410
.groupByName.foreach { (name, denots) =>
@@ -430,7 +448,6 @@ object Completion:
430
448
// most deeply nested member or local definition if not shadowed by an import
431
449
case Some (local) if local.ctx.scope == first.ctx.scope =>
432
450
resultMappings += name -> local.denots
433
-
434
451
case None if isSingleImport || isImportedInDifferentScope || isSameSymbolImportedDouble =>
435
452
resultMappings += name -> first.denots
436
453
case None if notConflictingWithDefaults =>
@@ -440,7 +457,7 @@ object Completion:
440
457
}
441
458
}
442
459
443
- resultMappings
460
+ CompletionResult ( resultMappings, renames.toMap)
444
461
end scopeCompletions
445
462
446
463
/** Widen only those types which are applied or are exactly nothing
@@ -474,15 +491,20 @@ object Completion:
474
491
/** Completions introduced by imports directly in this context.
475
492
* Completions from outer contexts are not included.
476
493
*/
477
- private def importedCompletions (using Context ): CompletionMap =
494
+ private def importedCompletions (using Context ): CompletionResult =
478
495
val imp = ctx.importInfo
496
+ val renames = collection.mutable.Map .empty[Symbol , Name ]
479
497
480
498
if imp == null then
481
- Map .empty
499
+ CompletionResult ( Map .empty, Map .empty)
482
500
else
483
501
def fromImport (name : Name , nameInScope : Name ): Seq [(Name , SingleDenotation )] =
484
502
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
+ }
486
508
487
509
val givenImports = imp.importedImplicits
488
510
.map { ref => (ref.implicitName: Name , ref.underlyingRef.denot.asSingleDenotation) }
@@ -508,7 +530,8 @@ object Completion:
508
530
fromImport(original.toTypeName, nameInScope.toTypeName)
509
531
}.toSeq.groupByName
510
532
511
- givenImports ++ wildcardMembers ++ explicitMembers
533
+ val results = givenImports ++ wildcardMembers ++ explicitMembers
534
+ CompletionResult (results, renames.toMap)
512
535
end importedCompletions
513
536
514
537
/** Completions from implicit conversions including old style extensions using implicit classes */
@@ -562,7 +585,7 @@ object Completion:
562
585
563
586
// 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
564
587
val termCompleter = new Completer (Mode .Term , pos, untpdPath, matches)
565
- val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap:
588
+ val extMethodsInScope = termCompleter.scopeCompletions.names. toList.flatMap:
566
589
case (name, denots) => denots.collect:
567
590
case d : SymDenotation if d.isTerm && d.termRef.symbol.is(Extension ) => (d.termRef, name.asTermName)
568
591
@@ -664,6 +687,7 @@ object Completion:
664
687
665
688
private type CompletionMap = Map [Name , Seq [SingleDenotation ]]
666
689
690
+ case class CompletionResult (names : Map [Name , Seq [SingleDenotation ]], renames : Map [Symbol , Name ])
667
691
/**
668
692
* The completion mode: defines what kinds of symbols should be included in the completion
669
693
* results.
0 commit comments