Skip to content

Commit 6ba333b

Browse files
Backport "Repl - method signatures in autocomplete" to LTS (#20995)
Backports #19917 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents e48cbe7 + 9960977 commit 6ba333b

File tree

2 files changed

+42
-15
lines changed

2 files changed

+42
-15
lines changed

Diff for: compiler/src/dotty/tools/repl/ReplDriver.scala

+41-14
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

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

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

231-
/** Extract possible completions at the index of `cursor` in `expr` */
257+
@deprecated("Use completionsWithSignatures instead", "3.3.4")
232258
protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] =
233-
def makeCandidate(label: String) = {
234-
259+
completionsWithSignatures(cursor, expr, state0).map: c =>
235260
new Candidate(
236-
/* value = */ label,
237-
/* displ = */ stripBackTicks(label), // displayed value
261+
/* value = */ c.label,
262+
/* displ = */ stripBackTicks(c.label), // displayed value
238263
/* group = */ null, // can be used to group completions together
239264
/* descr = */ null, // TODO use for documentation?
240265
/* suffix = */ null,
241266
/* key = */ null,
242267
/* complete = */ false // if true adds space when completing
243268
)
244-
}
269+
end completions
245270

271+
272+
/** Extract possible completions at the index of `cursor` in `expr` */
273+
protected final def completionsWithSignatures(cursor: Int, expr: String, state0: State): List[Completion] =
246274
if expr.startsWith(":") then
247275
ParseResult.commands.collect {
248-
case command if command._1.startsWith(expr) => makeCandidate(command._1)
276+
case command if command._1.startsWith(expr) => Completion(command._1, "", List())
249277
}
250278
else
251279
given state: State = newRun(state0)
@@ -258,11 +286,10 @@ class ReplDriver(settings: Array[String],
258286
unit.tpdTree = tpdTree
259287
given Context = state.context.fresh.setCompilationUnit(unit)
260288
val srcPos = SourcePosition(file, Span(cursor))
261-
val completions = try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
262-
completions.map(_.label).distinct.map(makeCandidate)
289+
try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
263290
}
264291
.getOrElse(Nil)
265-
end completions
292+
end completionsWithSignatures
266293

267294
protected def interpret(res: ParseResult, quiet: Boolean = false)(using state: State): State = {
268295
res match {

Diff for: compiler/test/dotty/tools/repl/TabcompleteTests.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class TabcompleteTests extends ReplTest {
1010

1111
/** Returns the `(<instance completions>, <companion completions>)`*/
1212
private def tabComplete(src: String)(implicit state: State): List[String] =
13-
completions(src.length, src, state).map(_.value).sorted
13+
completionsWithSignatures(src.length, src, state).map(_.label).sorted.distinct
1414

1515
@Test def tabCompleteList = initially {
1616
val comp = tabComplete("List.r")

0 commit comments

Comments
 (0)