Skip to content

Commit 1eee888

Browse files
authored
Fix completion mode filtering + optimize scopeCompletions (#23172)
I've changed scopeCompletions to lazy val to memoize because I beliveve we don't need to recompute it. The actual fix is at the comment. There is no need to create a new Completer just to filter all of remaining completions at later stage. Fixes #23150
1 parent 3080a70 commit 1eee888

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

compiler/src/dotty/tools/dotc/interactive/Completion.scala

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,7 @@ object Completion:
245245
case tpd.Select(qual @ tpd.This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions.names
246246
case StringContextApplication(qual) =>
247247
completer.scopeCompletions.names ++ completer.selectionCompletions(qual)
248-
case tpd.Select(qual, _) :: _ if qual.typeOpt.hasSimpleKind =>
249-
completer.selectionCompletions(qual)
250-
case tpd.Select(qual, _) :: _ => Map.empty
248+
case tpd.Select(qual, _) :: _ => completer.selectionCompletions(qual)
251249
case (tree: tpd.ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr)
252250
case _ => completer.scopeCompletions.names
253251

@@ -370,7 +368,7 @@ object Completion:
370368
* For the results of all `xyzCompletions` methods term names and type names are always treated as different keys in the same map
371369
* and they never conflict with each other.
372370
*/
373-
class Completer(val mode: Mode, pos: SourcePosition, untpdPath: List[untpd.Tree], matches: Name => Boolean):
371+
class Completer(val mode: Mode, pos: SourcePosition, untpdPath: List[untpd.Tree], matches: Name => Boolean)(using Context):
374372
/** Completions for terms and types that are currently in scope:
375373
* the members of the current class, local definitions and the symbols that have been imported,
376374
* recursively adding completions from outer scopes.
@@ -384,7 +382,7 @@ object Completion:
384382
* (even if the import follows it syntactically)
385383
* - a more deeply nested import shadowing a member or a local definition causes an ambiguity
386384
*/
387-
def scopeCompletions(using context: Context): CompletionResult =
385+
lazy val scopeCompletions: CompletionResult =
388386

389387
/** Temporary data structure representing denotations with the same name introduced in a given scope
390388
* as a member of a type, by a local definition or by an import clause
@@ -478,17 +476,16 @@ object Completion:
478476
def selectionCompletions(qual: tpd.Tree)(using Context): CompletionMap =
479477
val adjustedQual = widenQualifier(qual)
480478

481-
val implicitConversionMembers = implicitConversionMemberCompletions(adjustedQual)
482-
val extensionMembers = extensionCompletions(adjustedQual)
483-
val directMembers = directMemberCompletions(adjustedQual)
484-
val namedTupleMembers = namedTupleCompletions(adjustedQual)
479+
if qual.symbol.is(Package) then
480+
directMemberCompletions(adjustedQual)
481+
else if qual.typeOpt.hasSimpleKind then
482+
implicitConversionMemberCompletions(adjustedQual) ++
483+
extensionCompletions(adjustedQual) ++
484+
directMemberCompletions(adjustedQual) ++
485+
namedTupleCompletions(adjustedQual)
486+
else
487+
Map.empty
485488

486-
List(
487-
implicitConversionMembers,
488-
extensionMembers,
489-
directMembers,
490-
namedTupleMembers
491-
).reduce(_ ++ _)
492489

493490
/** Completions for members of `qual`'s type.
494491
* These include inherited definitions but not members added by extensions or implicit conversions
@@ -619,8 +616,7 @@ object Completion:
619616
// There are four possible ways for an extension method to be applicable
620617

621618
// 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
622-
val termCompleter = new Completer(Mode.Term, pos, untpdPath, matches)
623-
val extMethodsInScope = termCompleter.scopeCompletions.names.toList.flatMap:
619+
val extMethodsInScope = scopeCompletions.names.toList.flatMap:
624620
case (name, denots) => denots.collect:
625621
case d: SymDenotation if d.isTerm && d.termRef.symbol.is(Extension) => (d.termRef, name.asTermName)
626622

presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,3 +2250,28 @@ class CompletionSuite extends BaseCompletionSuite:
22502250
|""".stripMargin,
22512251
""
22522252
)
2253+
2254+
@Test def `no-completions-on-package-selection` =
2255+
check(
2256+
"""package one.@@
2257+
|""".stripMargin,
2258+
""
2259+
)
2260+
2261+
@Test def `no-extension-completion-on-packages` =
2262+
check(
2263+
"""object M:
2264+
| scala.runt@@
2265+
|""".stripMargin,
2266+
"""runtime scala
2267+
|PartialFunction scala""".stripMargin // those are the actual members of scala
2268+
)
2269+
2270+
@Test def `no-extension-completions-on-package-objects` =
2271+
check(
2272+
"""package object magic { def test: Int = ??? }
2273+
|object M:
2274+
| magic.@@
2275+
|""".stripMargin,
2276+
"test: Int"
2277+
)

0 commit comments

Comments
 (0)