Skip to content

Commit b0ba045

Browse files
authored
Repl - method signatures in autocomplete (#19917)
Closes #17367 This PR brings method signatures to repl completions, as in Scala 2 repl (but with syntax highlighting). After typing `List(1).max<TAB>`: ![image](https://github.com/scala/scala3/assets/24961583/0846e7b1-ff44-4e95-aaff-398069821b2f)
1 parent b782cbf commit b0ba045

File tree

2 files changed

+33
-21
lines changed

2 files changed

+33
-21
lines changed

compiler/src/dotty/tools/repl/ReplDriver.scala

+32-20
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import dotty.tools.dotc.util.{SourceFile, SourcePosition}
3131
import dotty.tools.dotc.{CompilationUnit, Driver}
3232
import dotty.tools.dotc.config.CompilerCommand
3333
import dotty.tools.io.*
34+
import dotty.tools.repl.Rendering.showUser
3435
import dotty.tools.runner.ScalaClassLoader.*
3536
import org.jline.reader.*
3637

@@ -149,11 +150,36 @@ class ReplDriver(settings: Array[String],
149150

150151
/** Blockingly read a line, getting back a parse result */
151152
def readLine()(using state: State): ParseResult = {
152-
val completer: Completer = { (_, line, candidates) =>
153+
given Context = state.context
154+
val completer: Completer = { (lineReader, line, candidates) =>
155+
def makeCandidate(label: String) = {
156+
new Candidate(
157+
/* value = */ label,
158+
/* displ = */ stripBackTicks(label), // displayed value
159+
/* group = */ null, // can be used to group completions together
160+
/* descr = */ null, // TODO use for documentation?
161+
/* suffix = */ null,
162+
/* key = */ null,
163+
/* complete = */ false // if true adds space when completing
164+
)
165+
}
153166
val comps = completions(line.cursor, line.line, state)
154-
candidates.addAll(comps.asJava)
167+
candidates.addAll(comps.map(_.label).distinct.map(makeCandidate).asJava)
168+
val lineWord = line.word()
169+
comps.filter(c => c.label == lineWord && c.symbols.nonEmpty) match
170+
case Nil =>
171+
case exachMatches =>
172+
val terminal = lineReader.nn.getTerminal
173+
lineReader.callWidget(LineReader.CLEAR)
174+
terminal.writer.println()
175+
exachMatches.foreach: exact =>
176+
exact.symbols.foreach: sym =>
177+
terminal.writer.println(SyntaxHighlighting.highlight(sym.showUser))
178+
lineReader.callWidget(LineReader.REDRAW_LINE)
179+
lineReader.callWidget(LineReader.REDISPLAY)
180+
terminal.flush()
155181
}
156-
given Context = state.context
182+
157183
try {
158184
val line = terminal.readLine(completer)
159185
ParseResult(line)
@@ -230,23 +256,10 @@ class ReplDriver(settings: Array[String],
230256
label
231257

232258
/** Extract possible completions at the index of `cursor` in `expr` */
233-
protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] =
234-
def makeCandidate(label: String) = {
235-
236-
new Candidate(
237-
/* value = */ label,
238-
/* displ = */ stripBackTicks(label), // displayed value
239-
/* group = */ null, // can be used to group completions together
240-
/* descr = */ null, // TODO use for documentation?
241-
/* suffix = */ null,
242-
/* key = */ null,
243-
/* complete = */ false // if true adds space when completing
244-
)
245-
}
246-
259+
protected final def completions(cursor: Int, expr: String, state0: State): List[Completion] =
247260
if expr.startsWith(":") then
248261
ParseResult.commands.collect {
249-
case command if command._1.startsWith(expr) => makeCandidate(command._1)
262+
case command if command._1.startsWith(expr) => Completion(command._1, "", List())
250263
}
251264
else
252265
given state: State = newRun(state0)
@@ -259,8 +272,7 @@ class ReplDriver(settings: Array[String],
259272
unit.tpdTree = tpdTree
260273
given Context = state.context.fresh.setCompilationUnit(unit)
261274
val srcPos = SourcePosition(file, Span(cursor))
262-
val completions = try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
263-
completions.map(_.label).distinct.map(makeCandidate)
275+
try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
264276
}
265277
.getOrElse(Nil)
266278
end completions

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na
4242

4343
/** Returns the `(<instance completions>, <companion completions>)`*/
4444
def tabComplete(src: String)(implicit state: State): List[String] =
45-
completions(src.length, src, state).map(_.value).sorted
45+
completions(src.length, src, state).map(_.label).sorted.distinct
4646

4747
extension [A](state: State)
4848
infix def andThen(op: State ?=> A): A = op(using state)

0 commit comments

Comments
 (0)