diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 81afc68e2342..c841184675fc 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -242,9 +242,7 @@ object Completion: case tpd.Select(qual @ tpd.This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions.names case StringContextApplication(qual) => completer.scopeCompletions.names ++ completer.selectionCompletions(qual) - case tpd.Select(qual, _) :: _ if qual.typeOpt.hasSimpleKind => - completer.selectionCompletions(qual) - case tpd.Select(qual, _) :: _ => Map.empty + case tpd.Select(qual, _) :: _ => completer.selectionCompletions(qual) case (tree: tpd.ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr) case _ => completer.scopeCompletions.names @@ -367,7 +365,7 @@ object Completion: * For the results of all `xyzCompletions` methods term names and type names are always treated as different keys in the same map * and they never conflict with each other. */ - class Completer(val mode: Mode, pos: SourcePosition, untpdPath: List[untpd.Tree], matches: Name => Boolean): + class Completer(val mode: Mode, pos: SourcePosition, untpdPath: List[untpd.Tree], matches: Name => Boolean)(using Context): /** Completions for terms and types that are currently in scope: * the members of the current class, local definitions and the symbols that have been imported, * recursively adding completions from outer scopes. @@ -381,7 +379,7 @@ object Completion: * (even if the import follows it syntactically) * - a more deeply nested import shadowing a member or a local definition causes an ambiguity */ - def scopeCompletions(using context: Context): CompletionResult = + lazy val scopeCompletions: CompletionResult = /** Temporary data structure representing denotations with the same name introduced in a given scope * as a member of a type, by a local definition or by an import clause @@ -475,9 +473,15 @@ object Completion: def selectionCompletions(qual: tpd.Tree)(using Context): CompletionMap = val adjustedQual = widenQualifier(qual) - implicitConversionMemberCompletions(adjustedQual) ++ + if qual.symbol.is(Package) then + directMemberCompletions(adjustedQual) + else if qual.typeOpt.hasSimpleKind then + implicitConversionMemberCompletions(adjustedQual) ++ extensionCompletions(adjustedQual) ++ directMemberCompletions(adjustedQual) + else + Map.empty + /** Completions for members of `qual`'s type. * These include inherited definitions but not members added by extensions or implicit conversions @@ -584,8 +588,7 @@ object Completion: // There are four possible ways for an extension method to be applicable // 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference. - val termCompleter = new Completer(Mode.Term, pos, untpdPath, matches) - val extMethodsInScope = termCompleter.scopeCompletions.names.toList.flatMap: + val extMethodsInScope = scopeCompletions.names.toList.flatMap: case (name, denots) => denots.collect: case d: SymDenotation if d.isTerm && d.termRef.symbol.is(Extension) => (d.termRef, name.asTermName) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 1bae825f7fde..84ee3129b0ea 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -2203,3 +2203,28 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin, "" ) + + @Test def `no-completions-on-package-selection` = + check( + """package one.@@ + |""".stripMargin, + "" + ) + + @Test def `no-extension-completion-on-packages` = + check( + """object M: + | scala.runt@@ + |""".stripMargin, + """runtime scala + |PartialFunction scala""".stripMargin // those are the actual members of scala + ) + + @Test def `no-extension-completions-on-package-objects` = + check( + """package object magic { def test: Int = ??? } + |object M: + | magic.@@ + |""".stripMargin, + "test: Int" + )