From dff5e447f252fda3a469506350be18af9fffd5ad Mon Sep 17 00:00:00 2001 From: Florian3k Date: Mon, 21 Jul 2025 17:39:06 +0200 Subject: [PATCH 1/2] compare points in pathTo --- .../dotty/tools/dotc/ast/NavigateAST.scala | 20 +++++++++++--- .../tools/pc/tests/hover/HoverTermSuite.scala | 27 +++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala index 90bd9b7923ae..861db55b1903 100644 --- a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -94,7 +94,8 @@ object NavigateAST { * When choosing better fit we compare spans. If candidate span has starting or ending point inside (exclusive) * current best fit it is selected as new best fit. This means that same spans are failing the first predicate. * - * In case when spans start and end at same offsets we prefer non synthethic one. + * In case when spans start and end at same offsets we prefer non synthethic one, + * and then one with better point (see isBetterPoint below). */ def isBetterFit(currentBest: List[Positioned], candidate: List[Positioned]): Boolean = if currentBest.isEmpty && candidate.nonEmpty then true @@ -102,9 +103,20 @@ object NavigateAST { val bestSpan = currentBest.head.span val candidateSpan = candidate.head.span - bestSpan != candidateSpan && - envelops(bestSpan, candidateSpan) || - bestSpan.contains(candidateSpan) && bestSpan.isSynthetic && !candidateSpan.isSynthetic + def isBetterPoint = + // Given two spans with same end points, + // we compare their points in relation to the point we are looking for (span.point) + // The candidate (candidateSpan.point) is better than what we have so far (bestSpan.point), when: + // 1) candidate is closer to target from the right + span.point <= candidateSpan.point && candidateSpan.point < bestSpan.point + // 2) candidate is closer to target from the left + || bestSpan.point < candidateSpan.point && candidateSpan.point <= span.point + // 3) candidate is to on the left side of target, and best so far is on the right + || candidateSpan.point <= span.point && span.point < bestSpan.point + + bestSpan != candidateSpan && envelops(bestSpan, candidateSpan) + || bestSpan.contains(candidateSpan) && bestSpan.isSynthetic && !candidateSpan.isSynthetic + || candidateSpan.start == bestSpan.start && candidateSpan.end == bestSpan.end && isBetterPoint else false def isRecoveryTree(sel: untpd.Select): Boolean = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index f46a2ba506b9..de80ad7031ad 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -815,3 +815,30 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, "def substring(x$0: Int, x$1: Int): String".hover ) + + @Test def `multiple-valdefs-1` = + check( + """|object O { + | val x@@x, yy, zz = 1 + |} + |""".stripMargin, + "val xx: Int".hover + ) + + @Test def `multiple-valdefs-2` = + check( + """|object O { + | val xx, y@@y, zz = 1 + |} + |""".stripMargin, + "val yy: Int".hover + ) + + @Test def `multiple-valdefs-3` = + check( + """|object O { + | val xx, yy, z@@z = 1 + |} + |""".stripMargin, + "val zz: Int".hover + ) From 7e3d0a3f7b85fae24fbd8babec36c651fecb5054 Mon Sep 17 00:00:00 2001 From: Florian3k Date: Tue, 22 Jul 2025 10:20:07 +0200 Subject: [PATCH 2/2] apply suggestions from code review, fix formatting --- .../tools/pc/tests/hover/HoverTermSuite.scala | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index de80ad7031ad..c483dc289b0e 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -822,23 +822,32 @@ class HoverTermSuite extends BaseHoverSuite: | val x@@x, yy, zz = 1 |} |""".stripMargin, - "val xx: Int".hover + "val xx: Int".hover ) @Test def `multiple-valdefs-2` = - check( - """|object O { - | val xx, y@@y, zz = 1 - |} - |""".stripMargin, - "val yy: Int".hover - ) + check( + """|object O { + | val xx, y@@y, zz = 1 + |} + |""".stripMargin, + "val yy: Int".hover + ) @Test def `multiple-valdefs-3` = - check( - """|object O { - | val xx, yy, z@@z = 1 - |} - |""".stripMargin, - "val zz: Int".hover - ) + check( + """|object O { + | val xx, yy, z@@z = 1 + |} + |""".stripMargin, + "val zz: Int".hover + ) + + @Test def `multiple-valdefs-4` = + check( + """|object O { + | val xx, thisIsAVeryLongNa@@me, zz = 1 + |} + |""".stripMargin, + "val thisIsAVeryLongName: Int".hover + )