Skip to content

Commit e701d33

Browse files
committed
Fix #4535: Handle Null and Nothing in completions
Do not complete on Nothing and complete as AnyRef for Null. Add missing Artifact to remove `$isInstanceOf` completion and workaround missing decoding for `$u2192` to `→`.
1 parent e873908 commit e701d33

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class Definitions {
270270
lazy val Any_getClass: TermSymbol = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
271271
lazy val Any_isInstanceOf: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
272272
lazy val Any_asInstanceOf: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, _.paramRefs(0), Final)
273-
lazy val Any_typeTest: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOfPM, _ => BooleanType, Final | Synthetic)
273+
lazy val Any_typeTest: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOfPM, _ => BooleanType, Final | Synthetic | Artifact)
274274
// generated by pattern matcher, eliminated by erasure
275275

276276
def AnyMethods: List[TermSymbol] = List(Any_==, Any_!=, Any_equals, Any_hashCode,

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ object Completion {
150150
nameToSymbols.map { case (name, symbols) =>
151151
val typesFirst = symbols.sortWith((s1, s2) => s1.isType && !s2.isType)
152152
val desc = description(typesFirst)
153-
Completion(name.toString, desc, typesFirst)
153+
val strName = name.toString
154+
val label = if (strName == "$u2192") "" else strName // TODO fix name.decode and use it
155+
Completion(label, desc, typesFirst)
154156
}
155157
}
156158

@@ -207,11 +209,17 @@ object Completion {
207209
* considered.
208210
*/
209211
def addMemberCompletions(qual: Tree)(implicit ctx: Context): Unit = {
210-
addAccessibleMembers(qual.tpe)
211-
if (!mode.is(Mode.Import)) {
212-
// Implicit conversions do not kick in when importing
213-
implicitConversionTargets(qual)(ctx.fresh.setExploreTyperState())
214-
.foreach(addAccessibleMembers)
212+
if (qual.tpe =:= defn.NothingType)
213+
()
214+
else if (qual.tpe =:= defn.NullType)
215+
addAccessibleMembers(defn.AnyRefType)
216+
else {
217+
addAccessibleMembers(qual.tpe)
218+
if (!mode.is(Mode.Import)) {
219+
// Implicit conversions do not kick in when importing
220+
implicitConversionTargets(qual)(ctx.fresh.setExploreTyperState())
221+
.foreach(addAccessibleMembers)
222+
}
215223
}
216224
}
217225

compiler/test/dotty/tools/repl/TabcompleteTests.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,25 @@ class TabcompleteTests extends ReplTest {
103103
assertEquals(comp.find(_.startsWith("<")), None)
104104
assert(!comp.contains("package"))
105105
}
106+
107+
@Test def `null` = fromInitialState { implicit s =>
108+
val comp = tabComplete("null.")
109+
assertEquals(
110+
List("!=", "##", "==", "asInstanceOf", "clone", "eq", "equals", "finalize", "getClass", "hashCode",
111+
"isInstanceOf", "ne", "notify", "notifyAll", "synchronized", "toString", "wait"),
112+
comp.distinct.sorted)
113+
}
114+
115+
@Test def anyRef = fromInitialState { implicit s =>
116+
val comp = tabComplete("(null: AnyRef).")
117+
assertEquals(
118+
List("!=", "##", "+", "->", "==", "asInstanceOf", "clone", "ensuring", "eq", "equals", "finalize", "formatted",
119+
"getClass", "hashCode", "isInstanceOf", "ne", "notify", "notifyAll", "synchronized", "toString", "wait", ""),
120+
comp.distinct.sorted)
121+
}
122+
123+
@Test def `???` = fromInitialState { implicit s =>
124+
val comp = tabComplete("???.")
125+
assertEquals(Nil, comp)
126+
}
106127
}

0 commit comments

Comments
 (0)