Skip to content

Commit 98c594f

Browse files
authored
Compare span points in pathTo to determine best span (#23581)
Closes #22207
1 parent ea6b0a4 commit 98c594f

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

compiler/src/dotty/tools/dotc/ast/NavigateAST.scala

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,29 @@ object NavigateAST {
9494
* When choosing better fit we compare spans. If candidate span has starting or ending point inside (exclusive)
9595
* current best fit it is selected as new best fit. This means that same spans are failing the first predicate.
9696
*
97-
* In case when spans start and end at same offsets we prefer non synthethic one.
97+
* In case when spans start and end at same offsets we prefer non synthethic one,
98+
* and then one with better point (see isBetterPoint below).
9899
*/
99100
def isBetterFit(currentBest: List[Positioned], candidate: List[Positioned]): Boolean =
100101
if currentBest.isEmpty && candidate.nonEmpty then true
101102
else if currentBest.nonEmpty && candidate.nonEmpty then
102103
val bestSpan = currentBest.head.span
103104
val candidateSpan = candidate.head.span
104105

105-
bestSpan != candidateSpan &&
106-
envelops(bestSpan, candidateSpan) ||
107-
bestSpan.contains(candidateSpan) && bestSpan.isSynthetic && !candidateSpan.isSynthetic
106+
def isBetterPoint =
107+
// Given two spans with same end points,
108+
// we compare their points in relation to the point we are looking for (span.point)
109+
// The candidate (candidateSpan.point) is better than what we have so far (bestSpan.point), when:
110+
// 1) candidate is closer to target from the right
111+
span.point <= candidateSpan.point && candidateSpan.point < bestSpan.point
112+
// 2) candidate is closer to target from the left
113+
|| bestSpan.point < candidateSpan.point && candidateSpan.point <= span.point
114+
// 3) candidate is to on the left side of target, and best so far is on the right
115+
|| candidateSpan.point <= span.point && span.point < bestSpan.point
116+
117+
bestSpan != candidateSpan && envelops(bestSpan, candidateSpan)
118+
|| bestSpan.contains(candidateSpan) && bestSpan.isSynthetic && !candidateSpan.isSynthetic
119+
|| candidateSpan.start == bestSpan.start && candidateSpan.end == bestSpan.end && isBetterPoint
108120
else false
109121

110122
def isRecoveryTree(sel: untpd.Select): Boolean =

presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,3 +815,39 @@ class HoverTermSuite extends BaseHoverSuite:
815815
|""".stripMargin,
816816
"def substring(x$0: Int, x$1: Int): String".hover
817817
)
818+
819+
@Test def `multiple-valdefs-1` =
820+
check(
821+
"""|object O {
822+
| val x@@x, yy, zz = 1
823+
|}
824+
|""".stripMargin,
825+
"val xx: Int".hover
826+
)
827+
828+
@Test def `multiple-valdefs-2` =
829+
check(
830+
"""|object O {
831+
| val xx, y@@y, zz = 1
832+
|}
833+
|""".stripMargin,
834+
"val yy: Int".hover
835+
)
836+
837+
@Test def `multiple-valdefs-3` =
838+
check(
839+
"""|object O {
840+
| val xx, yy, z@@z = 1
841+
|}
842+
|""".stripMargin,
843+
"val zz: Int".hover
844+
)
845+
846+
@Test def `multiple-valdefs-4` =
847+
check(
848+
"""|object O {
849+
| val xx, thisIsAVeryLongNa@@me, zz = 1
850+
|}
851+
|""".stripMargin,
852+
"val thisIsAVeryLongName: Int".hover
853+
)

0 commit comments

Comments
 (0)