diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 79c4f52fb0ba..c5de3024fcd2 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -263,8 +263,12 @@ object Completion { */ private def accessibleMembers(site: Type)(using Context): Seq[Symbol] = site match { case site: NamedType if site.symbol.is(Package) => - // Don't look inside package members -- it's too expensive. - site.decls.toList.filter(sym => sym.isAccessibleFrom(site, superAccess = false)) + extension (tpe: Type) + def accessibleSymbols = tpe.decls.toList.filter(sym => sym.isAccessibleFrom(site, superAccess = false)) + + val packageDecls = site.accessibleSymbols + val packageObjectsDecls = packageDecls.filter(_.isPackageObject).flatMap(_.thisType.accessibleSymbols) + packageDecls ++ packageObjectsDecls case _ => def appendMemberSyms(name: Name, buf: mutable.Buffer[SingleDenotation]): Unit = try buf ++= site.member(name).alternatives diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 81abc54666b8..a54b24fe62cc 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -277,7 +277,7 @@ object Interactive { def contextOfPath(path: List[Tree])(using Context): Context = path match { case Nil | _ :: Nil => - ctx.run.runContext.fresh.setCompilationUnit(ctx.compilationUnit) + ctx.fresh case nested :: encl :: rest => val outer = contextOfPath(encl :: rest) try encl match { diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index f117d483c809..e0b08ab1f3ee 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -143,13 +143,15 @@ class InteractiveDriver(val settings: List[String]) extends Driver { def run(uri: URI, sourceCode: String): List[Diagnostic] = run(uri, toSource(uri, sourceCode)) def run(uri: URI, source: SourceFile): List[Diagnostic] = { + import typer.ImportInfo._ + val previousCtx = myCtx try { val reporter = new StoreReporter(null) with UniqueMessagePositions with HideNonSensicalMessages val run = compiler.newRun(using myInitCtx.fresh.setReporter(reporter)) - myCtx = run.runContext + myCtx = run.runContext.withRootImports given Context = myCtx diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index e16df58a7527..a6d9246a7bee 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -10,10 +10,44 @@ import dotty.tools.languageserver.util.actions.CodeCompletion class CompletionTest { @Test def completion0: Unit = { - code"class Foo { val xyz: Int = 0; def y: Int = xy$m1 }".withSource + code"class Foo { val xyz: Int = 0; def y: Int = xy${m1} }".withSource .completion(m1, Set(("xyz", Field, "Int"))) } + @Test def completionFromScalaPredef: Unit = { + code"class Foo { def foo: Unit = prin${m1} }".withSource + .completion(m1, Set( + ("print", Method, "(x: Any): Unit"), + ("printf", Method, "(text: String, xs: Any*): Unit"), + ("println", Method, "(x: Any): Unit") + )) + } + + @Test def completionFromDottyPredef: Unit = { + code"class Foo { val foo = summ${m1} }".withSource + .completion(m1, Set(("summon", Method, "[T](using x: T): x.type"))) + } + + @Test def completionFromScalaPackage: Unit = { + code"class Foo { val foo: Conv${m1} }".withSource + .completion(m1, Set(("Conversion", Class, "scala.Conversion"))) + } + + @Test def completionFromScalaPackageObject: Unit = { + code"class Foo { val foo: BigD${m1} }".withSource + .completion(m1, Set(("BigDecimal", Field, "type and getter BigDecimal"))) + } + + @Test def completionFromSyntheticPackageObject: Unit = { + code"class Foo { val foo: IArr${m1} }".withSource + .completion(m1, Set(("IArray", Field, "type and object IArray"))) + } + + @Test def completionFromJavaDefaults: Unit = { + code"class Foo { val foo: Runn${m1} }".withSource + .completion(m1, Set(("Runnable", Class, "trait and object Runnable"))) + } + @Test def completionWithImplicitConversion: Unit = { withSources( code"object Foo { implicit class WithBaz(bar: Bar) { def baz = 0 } }", @@ -29,7 +63,7 @@ class CompletionTest { ).completion(m1, Set(("MyClass", Class, "Foo.MyClass"))) } - @Test def ImportCompleteClassNoPrefix: Unit = { + @Test def importCompleteClassNoPrefix: Unit = { withSources( code"""object Foo { class MyClass }""", code"""import Foo.${m1}"""