Skip to content

Commit 9817323

Browse files
authored
Merge pull request #15119 from rochala/signature-help-enclosing-apply-fix
Fix signatureHelp to show enclosing apply instead of closest one.
2 parents d02c7c2 + ff459b1 commit 9817323

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ object Interactive {
7979
def enclosingTree(trees: List[SourceTree], pos: SourcePosition)(using Context): Tree =
8080
enclosingTree(pathTo(trees, pos))
8181

82-
/** The closes enclosing tree with a symbol, or the `EmptyTree`.
82+
/** The closest enclosing tree with a symbol, or the `EmptyTree`.
8383
*/
8484
def enclosingTree(path: List[Tree])(using Context): Tree =
8585
path.dropWhile(!_.symbol.exists).headOption.getOrElse(tpd.EmptyTree)

compiler/src/dotty/tools/dotc/util/Signatures.scala

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,21 @@ object Signatures {
4848
* being called, the list of overloads of this function).
4949
*/
5050
def callInfo(path: List[tpd.Tree], span: Span)(using Context): (Int, Int, List[SingleDenotation]) =
51-
path match {
52-
case UnApply(fun, _, patterns) :: _ =>
53-
callInfo(span, patterns, fun, Signatures.countParams(fun))
54-
case Apply(fun, params) :: _ =>
55-
callInfo(span, params, fun, Signatures.countParams(fun))
56-
case _ =>
57-
(0, 0, Nil)
51+
val enclosingApply = path.find {
52+
case Apply(fun, _) => !fun.span.contains(span)
53+
case UnApply(fun, _, _) => !fun.span.contains(span)
54+
case _ => false
5855
}
5956

57+
enclosingApply.map {
58+
case UnApply(fun, _, patterns) => callInfo(span, patterns, fun, Signatures.countParams(fun))
59+
case Apply(fun, params) => callInfo(span, params, fun, Signatures.countParams(fun))
60+
}.getOrElse((0, 0, Nil))
61+
6062
def callInfo(
6163
span: Span,
62-
params: List[Tree[Type]],
63-
fun: Tree[Type],
64+
params: List[Tree[Type]],
65+
fun: Tree[Type],
6466
alreadyAppliedCount : Int
6567
)(using Context): (Int, Int, List[SingleDenotation]) =
6668
val paramIndex = params.indexWhere(_.span.contains(span)) match {

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ class DottyLanguageServer extends LanguageServer
556556

557557
val pos = sourcePosition(driver, uri, params.getPosition)
558558
val trees = driver.openedTrees(uri)
559-
val path = Interactive.pathTo(trees, pos).dropWhile(t => !t.isInstanceOf[Apply | UnApply])
559+
val path = Interactive.pathTo(trees, pos)
560560
val (paramN, callableN, alternatives) = Signatures.callInfo(path, pos.span)
561561
val signatureInfos = alternatives.flatMap(Signatures.toSignature)
562562

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,63 @@ class SignatureHelpTest {
433433
Some("Option[A]"), None)
434434
), None, 2)
435435
}
436+
437+
@Test def nestedApplySignatures: Unit = {
438+
val signatures = (1 to 5).map { i =>
439+
S(s"foo$i", Nil, List(List(P("x", "Int"))), Some("Int"))
440+
}
441+
val booSignature = S(s"boo", Nil, List(List(P("x", "Int"), P("y", "Int"))), Some("Int"))
442+
code"""|object O:
443+
| def foo1(x: Int): Int = ???
444+
| def foo2(x: Int): Int = ???
445+
| def foo3(x: Int): Int = ???
446+
| def foo4(x: Int): Int = ???
447+
| def foo5(x: Int): Int = ???
448+
| def boo(x: Int, y: Int): Int = ???
449+
| boo(${m1}, fo${m2}o1(fo${m3}o2(fo${m4}o3(fo${m5}o4(fo${m6}o5(${m7}))))))"""
450+
.signatureHelp(m1, List(booSignature), None, 0)
451+
.signatureHelp(m2, List(booSignature), None, 1)
452+
.signatureHelp(m3, List(signatures(0)), None, 0)
453+
.signatureHelp(m4, List(signatures(1)), None, 0)
454+
.signatureHelp(m5, List(signatures(2)), None, 0)
455+
.signatureHelp(m6, List(signatures(3)), None, 0)
456+
.signatureHelp(m7, List(signatures(4)), None, 0)
457+
}
458+
459+
@Test def multipleNestedApplySignatures: Unit = {
460+
val simpleSignature = S(s"simpleFoo", Nil, List(List(P("x", "Int"))), Some("Int"))
461+
val complicatedSignature = S(s"complicatedFoo", Nil, List(List(P("x", "Int"), P("y", "Int"), P("z", "Int"))), Some("Int"))
462+
code"""|object O:
463+
| def simpleFoo(x: Int): Int = ???
464+
| def complicatedFoo(x: Int, y: Int, z: Int): Int = ???
465+
| simpleFoo(
466+
| complicated${m1}Foo(
467+
| simp${m2}leFoo(${m3}),
468+
| complic${m4}atedFoo(
469+
| 2,
470+
| ${m5},
471+
| simpleF${m6}oo(${m7})),
472+
| complicated${m8}Foo(5,${m9},7)
473+
| )
474+
| )"""
475+
.signatureHelp(m1, List(simpleSignature), None, 0)
476+
.signatureHelp(m2, List(complicatedSignature), None, 0)
477+
.signatureHelp(m3, List(simpleSignature), None, 0)
478+
.signatureHelp(m4, List(complicatedSignature), None, 1)
479+
.signatureHelp(m5, List(complicatedSignature), None, 1)
480+
.signatureHelp(m6, List(complicatedSignature), None, 2)
481+
.signatureHelp(m7, List(simpleSignature), None, 0)
482+
.signatureHelp(m8, List(complicatedSignature), None, 2)
483+
.signatureHelp(m9, List(complicatedSignature), None, 1)
484+
}
485+
486+
@Test def noHelpSignatureWithPositionedOnName: Unit = {
487+
val signature = S(s"foo", Nil, List(List(P("x", "Int"))), Some("Int"))
488+
code"""|object O:
489+
| def foo(x: Int): Int = ???
490+
| f${m1}oo(${m2})"""
491+
.signatureHelp(m1, Nil, None, 0)
492+
.signatureHelp(m2, List(signature), None, 0)
493+
}
494+
436495
}

0 commit comments

Comments
 (0)