From 19fb504cdcfbf7ae0daf1ac445de8fa0e0db3d80 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Fri, 18 Feb 2022 12:35:21 +0100 Subject: [PATCH] Set proper position for ValDefs generated from tuples Previously, the span for ValDefs generated for tuples would encompas the entire expression, which led to difficulties identifying the exact path to the current position. Now, we set the span to be the same as the name underneath. Not sure if this is a proper solution, since normally ValDefs ecompans the entire span, but in this case it makes 2 different ValDef have the same span. An alternative solution would be to find the one with point nearer to the current position. This popped up within the Nightly tests we do in Metals. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 17 +++++++++++++---- .../dotty/tools/languageserver/HoverTest.scala | 10 ++++++++-- .../tools/languageserver/WorksheetTest.scala | 6 ------ tests/neg/t5702-neg-bad-and-wild.check | 8 +++++++- tests/neg/t5702-neg-bad-and-wild.scala | 3 ++- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 8f0abf9cd999..9c8201b4fa02 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1143,10 +1143,11 @@ object desugar { ) // no `_` val ids = for ((named, _) <- vars) yield Ident(named.name) - val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) val matchExpr = if (tupleOptimizable) rhs - else Match(makeSelector(rhs, MatchCheck.IrrefutablePatDef), caseDef :: Nil) + else + val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) + Match(makeSelector(rhs, MatchCheck.IrrefutablePatDef), caseDef :: Nil) vars match { case Nil if !mods.is(Lazy) => matchExpr @@ -1166,8 +1167,16 @@ object desugar { val restDefs = for (((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD) yield - if (mods.is(Lazy)) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy) - else derivedValDef(original, named, tpt, selector(n), mods) + if mods.is(Lazy) then + DefDef(named.name.asTermName, Nil, tpt, selector(n)) + .withMods(mods &~ Lazy) + .withSpan(named.span) + else + valDef( + ValDef(named.name.asTermName, tpt, selector(n)) + .withMods(mods) + .withSpan(named.span) + ) flatTree(firstDef :: restDefs) } } diff --git a/language-server/test/dotty/tools/languageserver/HoverTest.scala b/language-server/test/dotty/tools/languageserver/HoverTest.scala index f23aac2ad6b6..5c2a1aa25efe 100644 --- a/language-server/test/dotty/tools/languageserver/HoverTest.scala +++ b/language-server/test/dotty/tools/languageserver/HoverTest.scala @@ -234,7 +234,13 @@ class HoverTest { @Test def tuple: Unit = { code"""|object A: - | val (${m1}first${m2}, second) = (1, 2)""".withSource - .hover(m1 to m2, hoverContent("Int")) + | val (${m1}first${m2}, second) = (1.0, 2)""".withSource + .hover(m1 to m2, hoverContent("Double")) + } + + @Test def multiAssigment: Unit = { + code"""|val ${m1}x${m2}, ${m3}y${m4} = 42.0""".withSource + .hover(m1 to m2, hoverContent("Double")) + .hover(m3 to m4, hoverContent("Double")) } } diff --git a/language-server/test/dotty/tools/languageserver/WorksheetTest.scala b/language-server/test/dotty/tools/languageserver/WorksheetTest.scala index d2e09060da9a..1b5972287659 100644 --- a/language-server/test/dotty/tools/languageserver/WorksheetTest.scala +++ b/language-server/test/dotty/tools/languageserver/WorksheetTest.scala @@ -93,12 +93,6 @@ class WorksheetTest { ((m1 to m2), "val res0: String = odd")) } - @Test def patternMatching1: Unit = { - ws"""${m1}val (foo, bar) = (1, 2)${m2}""".withSource - .run(m1, - ((m1 to m2), s"val foo: Int = 1${nl}val bar: Int = 2")) - } - @Test def evaluationException: Unit = { ws"""${m1}val foo = 1 / 0${m2} ${m3}val bar = 2${m4}""".withSource diff --git a/tests/neg/t5702-neg-bad-and-wild.check b/tests/neg/t5702-neg-bad-and-wild.check index cecfb1dfa996..761613fcf75c 100644 --- a/tests/neg/t5702-neg-bad-and-wild.check +++ b/tests/neg/t5702-neg-bad-and-wild.check @@ -23,11 +23,17 @@ | | longer explanation available when compiling with `-explain` -- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:23:17 --------------------------------------------------- -23 | val K(ns @ _*, x) = k // error: pattern expected +23 | val K(ns @ _*, xx) = k // error: pattern expected | ^ | pattern expected | | longer explanation available when compiling with `-explain` +-- [E161] Naming Error: tests/neg/t5702-neg-bad-and-wild.scala:24:10 --------------------------------------------------- +24 | val K(x) = k // error: x is already defined as value x + | ^^^^^^^^^^^^ + | x is already defined as value x + | + | Note that overloaded methods must all be defined in the same group of toplevel definitions -- Error: tests/neg/t5702-neg-bad-and-wild.scala:10:21 ----------------------------------------------------------------- 10 | case List(1, _*,) => // error: pattern expected // error | ^ diff --git a/tests/neg/t5702-neg-bad-and-wild.scala b/tests/neg/t5702-neg-bad-and-wild.scala index c8e27278eca0..b943fc15ba2b 100644 --- a/tests/neg/t5702-neg-bad-and-wild.scala +++ b/tests/neg/t5702-neg-bad-and-wild.scala @@ -20,7 +20,8 @@ object Test { // good syntax, bad semantics, detected by typer //gowild.scala:14: error: star patterns must correspond with varargs parameters val K(x @ _*) = k - val K(ns @ _*, x) = k // error: pattern expected + val K(ns @ _*, xx) = k // error: pattern expected + val K(x) = k // error: x is already defined as value x val (b, _ * ) = (5,6) // ok // no longer complains //bad-and-wild.scala:15: error: ')' expected but '}' found.