Skip to content

Commit 4331311

Browse files
committed
Prefer types over terms in import completions
When completing imports, and several symbols with the same name are possible options, we show only the type symbols.
1 parent 36de05b commit 4331311

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -220,28 +220,19 @@ object Interactive {
220220
* 1. start with given name prefix, and
221221
* 2. do not contain '$' except in prefix where it is explicitly written by user, and
222222
* 3. are not a primary constructor,
223-
* 4. have an existing source symbol,
224-
* 5. are the module class in case of packages,
225-
* 6. are not Java module classes when completing imports (to avoid duplicate results).
226-
* 7. are mutable accessors, to exclude setters for `var`,
227-
* 8. have same term/type kind as name prefix given so far
223+
* 4. are the module class in case of packages,
224+
* 5. are mutable accessors, to exclude setters for `var`,
225+
* 6. have same term/type kind as name prefix given so far
228226
*
229227
* The reason for (2) is that we do not want to present compiler-synthesized identifiers
230228
* as completion results. However, if a user explicitly writes all '$' characters in an
231229
* identifier, we should complete the rest.
232-
*
233-
* The reason for (4) is that we want to filter, for instance, non-existnet `Module`
234-
* symbols that accompany class symbols. We can't simply return only the source symbols,
235-
* because this would discard some synthetic symbols such as the copy method of case
236-
* classes.
237230
*/
238231
def include(sym: Symbol) =
239232
sym.name.startsWith(info.prefix) &&
240233
!sym.name.toString.drop(info.prefix.length).contains('$') &&
241234
!sym.isPrimaryConstructor &&
242-
sym.sourceSymbol.exists &&
243235
(!sym.is(Package) || !sym.moduleClass.exists) &&
244-
(!info.inImport || !sym.is(allOf(JavaDefined, Module), butNot = Package)) &&
245236
!sym.is(allOf(Mutable, Accessor)) &&
246237
(!info.termOnly || sym.isTerm) &&
247238
(!info.typeOnly || sym.isType)
@@ -336,7 +327,16 @@ object Interactive {
336327
case _ => getScopeCompletions(ctx)
337328
}
338329

339-
val completionList = completions.toList
330+
val completionList =
331+
if (!info.inImport) completions.toList
332+
else {
333+
// In imports, show only the type symbols when there are multiple options with the same name
334+
completions.toList.groupBy(_.name.stripModuleClassSuffix.toSimpleName).mapValues {
335+
case sym :: Nil => sym :: Nil
336+
case syms => syms.filter(_.isType)
337+
}.values.flatten.toList
338+
}
339+
340340
interactiv.println(i"completion with pos = $pos, prefix = $info.prefix, termOnly = $info.termOnly, typeOnly = $info.typeOnly = $completionList%, %")
341341
(info.position, completionList)
342342
}

language-server/test/dotty/tools/languageserver/CompletionTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ class CompletionTest {
8080
).completion(m1, Set(("MyObject", Module, "O.MyObject")))
8181
}
8282

83-
@Test def importCompleteIncludeClassAndCompanion: Unit = {
83+
@Test def importCompleteWithClassAndCompanion: Unit = {
8484
withSources(
8585
code"""package pkg0
8686
class Foo
8787
object Foo""",
8888
code"""package pgk1
8989
import pkg0.F${m1}"""
90-
).completion(m1, Set(("Foo", Class, "Object{...}"), ("Foo", Module, "pkg0.Foo")))
90+
).completion(m1, Set(("Foo", Class, "Object{...}")))
9191
}
9292

9393
@Test def importCompleteIncludePackage: Unit = {

0 commit comments

Comments
 (0)