Skip to content

Commit 7769bd8

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 da1e196 commit 7769bd8

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
@@ -269,7 +269,7 @@ class Definitions {
269269
lazy val Any_getClass: TermSymbol = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
270270
lazy val Any_isInstanceOf: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
271271
lazy val Any_asInstanceOf: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, _.paramRefs(0), Final)
272-
lazy val Any_typeTest: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOfPM, _ => BooleanType, Final | Synthetic)
272+
lazy val Any_typeTest: TermSymbol = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOfPM, _ => BooleanType, Final | Synthetic | Artifact)
273273
// generated by pattern matcher, eliminated by erasure
274274

275275
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
@@ -97,4 +97,25 @@ class TabcompleteTests extends ReplTest {
9797
assertEquals(comp.find(_.startsWith("<")), None)
9898
assert(!comp.contains("package"))
9999
}
100+
101+
@Test def `null` = fromInitialState { implicit s =>
102+
val comp = tabComplete("null.")
103+
assertEquals(
104+
List("!=", "##", "==", "asInstanceOf", "clone", "eq", "equals", "finalize", "getClass", "hashCode",
105+
"isInstanceOf", "ne", "notify", "notifyAll", "synchronized", "toString", "wait"),
106+
comp.distinct.sorted)
107+
}
108+
109+
@Test def anyRef = fromInitialState { implicit s =>
110+
val comp = tabComplete("(null: AnyRef).")
111+
assertEquals(
112+
List("!=", "##", "+", "->", "==", "asInstanceOf", "clone", "ensuring", "eq", "equals", "finalize", "formatted",
113+
"getClass", "hashCode", "isInstanceOf", "ne", "notify", "notifyAll", "synchronized", "toString", "wait", ""),
114+
comp.distinct.sorted)
115+
}
116+
117+
@Test def `???` = fromInitialState { implicit s =>
118+
val comp = tabComplete("???.")
119+
assertEquals(Nil, comp)
120+
}
100121
}

0 commit comments

Comments
 (0)