Skip to content

Commit 07b67a8

Browse files
authored
Merge pull request #1951 from dotty-staging/fix-1484
fix #1484: position of while incorrect in debug
2 parents 5bcbad2 + 1489eff commit 07b67a8

File tree

17 files changed

+471
-4
lines changed

17 files changed

+471
-4
lines changed

.drone.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pipeline:
77
- ln -s /var/cache/drone/ivy2 "$HOME/.ivy2"
88
- ./scripts/update-scala-library
99
- sbt -J-Xmx4096m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m -Ddotty.drone.mem=4096m "${TEST}"
10+
- ./compiler/test/debug/test
1011
when:
1112
branch:
1213
exclude: gh-pages

.drone.yml.sig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIGxuIC1zIC92YXIvY2FjaGUvZHJvbmUvc2NhbGEtc2NhbGEgc2NhbGEtc2NhbGEKICAgICAgLSBsbiAtcyAvdmFyL2NhY2hlL2Ryb25lL2l2eTIgIiRIT01FLy5pdnkyIgogICAgICAtIC4vc2NyaXB0cy91cGRhdGUtc2NhbGEtbGlicmFyeQogICAgICAtIHNidCAtSi1YbXg0MDk2bSAtSi1YWDpSZXNlcnZlZENvZGVDYWNoZVNpemU9NTEybSAtSi1YWDpNYXhNZXRhc3BhY2VTaXplPTEwMjRtIC1EZG90dHkuZHJvbmUubWVtPTQwOTZtICIke1RFU1R9IgogICAgd2hlbjoKICAgICAgYnJhbmNoOgogICAgICAgIGV4Y2x1ZGU6IGdoLXBhZ2VzCgogIGRvY3VtZW50YXRpb246CiAgICBpbWFnZTogbGFtcGVwZmwvZG90dHk6bGF0ZXN0CiAgICBwdWxsOiB0cnVlCiAgICBjb21tYW5kczoKICAgICAgLSAuL3Byb2plY3Qvc2NyaXB0cy9nZW5Eb2NzICIke1RFU1R9IiAkQk9UX1BBU1MKICAgIHdoZW46CiAgICAgIGJyYW5jaDogbWFzdGVyCgogIGdpdHRlcjoKICAgIGltYWdlOiBwbHVnaW5zL2dpdHRlcgogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgc3RhdHVzOiBjaGFuZ2VkCgogIHNsYWNrOgogICAgaW1hZ2U6IHBsdWdpbnMvc2xhY2sKICAgIGNoYW5uZWw6IGRvdHR5CiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgogICAgICBzdGF0dXM6IGNoYW5nZWQKCm1hdHJpeDoKICBURVNUOgogICAgLSA7dGVzdDtkb3R0eS1iaW4tdGVzdHMvdGVzdAogICAgLSA7cHVibGlzaExvY2FsO2RvdHR5LWJvb3RzdHJhcHBlZC90ZXN0CiAgICAtIHBhcnRlc3Qtb25seS1uby1ib290c3RyYXAgLS1zaG93LWRpZmYgLS12ZXJib3NlCiAgICAtIHBhcnRlc3Qtb25seSAtLXNob3ctZGlmZiAtLXZlcmJvc2UK.VRqZiSgeE6OumPlEvs4TWfxIHNOEVjR_ZmyBmapxZ-U
1+
eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIGxuIC1zIC92YXIvY2FjaGUvZHJvbmUvc2NhbGEtc2NhbGEgc2NhbGEtc2NhbGEKICAgICAgLSBsbiAtcyAvdmFyL2NhY2hlL2Ryb25lL2l2eTIgIiRIT01FLy5pdnkyIgogICAgICAtIC4vc2NyaXB0cy91cGRhdGUtc2NhbGEtbGlicmFyeQogICAgICAtIHNidCAtSi1YbXg0MDk2bSAtSi1YWDpSZXNlcnZlZENvZGVDYWNoZVNpemU9NTEybSAtSi1YWDpNYXhNZXRhc3BhY2VTaXplPTEwMjRtIC1EZG90dHkuZHJvbmUubWVtPTQwOTZtICIke1RFU1R9IgogICAgICAtIC4vY29tcGlsZXIvdGVzdC9kZWJ1Zy90ZXN0CiAgICB3aGVuOgogICAgICBicmFuY2g6CiAgICAgICAgZXhjbHVkZTogZ2gtcGFnZXMKCiAgZG9jdW1lbnRhdGlvbjoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIC4vcHJvamVjdC9zY3JpcHRzL2dlbkRvY3MgIiR7VEVTVH0iICRCT1RfUEFTUwogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKCiAgZ2l0dGVyOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0dGVyCiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgogICAgICBzdGF0dXM6IGNoYW5nZWQKCiAgc2xhY2s6CiAgICBpbWFnZTogcGx1Z2lucy9zbGFjawogICAgY2hhbm5lbDogZG90dHkKICAgIHdoZW46CiAgICAgIGJyYW5jaDogbWFzdGVyCiAgICAgIHN0YXR1czogY2hhbmdlZAoKbWF0cml4OgogIFRFU1Q6CiAgICAtIDt0ZXN0O2RvdHR5LWJpbi10ZXN0cy90ZXN0CiAgICAtIDtwdWJsaXNoTG9jYWw7ZG90dHktYm9vdHN0cmFwcGVkL3Rlc3QKICAgIC0gcGFydGVzdC1vbmx5LW5vLWJvb3RzdHJhcCAtLXNob3ctZGlmZiAtLXZlcmJvc2UKICAgIC0gcGFydGVzdC1vbmx5IC0tc2hvdy1kaWZmIC0tdmVyYm9zZQo.NgZCPjkR9Z1A96-ryvHIVJOsL9GI6aIvU6tGC_hv5Lo

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ build/
5252

5353
# Put local stuff here
5454
local/
55+
compiler/test/debug/Gen.jar
5556

bin/dotr

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ fi
88
DOTTY_ROOT="$(dirname "$DOTTY_ROOT")"
99
DOTTY_ROOT="$( cd "$DOTTY_ROOT" >& /dev/null && pwd )/.." # absolute
1010

11+
# debug
12+
DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
13+
DEBUG=
14+
1115
# Load common functions and variables
1216
source "$DOTTY_ROOT"/bin/common
1317

@@ -24,10 +28,21 @@ function runMain {
2428
echo "java bin not detected - please specify with \$JAVA_BIN or install java to a default location"
2529
exit 1
2630
else
27-
eval "$jbin $CLASS_PATH $@"
31+
eval "$jbin $DEBUG $CLASS_PATH $@"
2832
fi
2933
}
3034

35+
# parse command line params -d to enable debugging
36+
while getopts "dx" opt; do
37+
case "$opt" in
38+
d)
39+
DEBUG="$DEBUG_STR"
40+
;;
41+
esac
42+
done
43+
44+
shift $((OPTIND-1))
45+
3146
first_arg="$1"
3247

3348
if [ -z "$1" ]; then

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -991,12 +991,12 @@ object desugar {
991991
else Apply(ref(tupleTypeRef.classSymbol.companionModule.valRef), ts)
992992
case WhileDo(cond, body) =>
993993
// { <label> def while$(): Unit = if (cond) { body; while$() } ; while$() }
994-
val call = Apply(Ident(nme.WHILE_PREFIX), Nil)
994+
val call = Apply(Ident(nme.WHILE_PREFIX), Nil).withPos(tree.pos)
995995
val rhs = If(cond, Block(body, call), unitLiteral)
996996
labelDefAndCall(nme.WHILE_PREFIX, rhs, call)
997997
case DoWhile(body, cond) =>
998998
// { label def doWhile$(): Unit = { body; if (cond) doWhile$() } ; doWhile$() }
999-
val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil)
999+
val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil).withPos(tree.pos)
10001000
val rhs = Block(body, If(cond, call, unitLiteral))
10011001
labelDefAndCall(nme.DO_WHILE_PREFIX, rhs, call)
10021002
case ForDo(enums, body) =>

compiler/test/debug/Gen

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#! /usr/bin/env bash
2+
3+
DIR="$( cd "$( dirname "$0" )" && pwd )"
4+
5+
SOURCE=$DIR/Gen.scala
6+
CLASS=./Gen.class
7+
8+
if [ ! -e $CLASS ] || [ $SOURCE -nt $CLASS ]; then
9+
./bin/dotc $DIR/Gen.scala
10+
fi
11+
12+
./bin/dotr Gen $@
13+

compiler/test/debug/Gen.scala

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import scala.io.Source
2+
import scala.collection.mutable.ListBuffer
3+
4+
/** Automate testing debuggability of generated code using JDB and expect
5+
*
6+
* The debugging information is annotated as comments to the code in brackets:
7+
*
8+
* val x = f(3) // [break] [next: line=5]
9+
* val y = 5
10+
*
11+
* 1. A jdb command must be wrapped in brackets, like `[step]`. All jdb commands can be used.
12+
* 2. To check output of jdb for a command, use `[cmd: expect]`.
13+
* 3. If `expect` is wrapped in double quotes, regex is supported.
14+
* 4. Break commands are collected and set globally.
15+
* 5. Other commands will be send to jdb in the order they appear in the source file
16+
*
17+
* Note: jdb uses line number starts from 1
18+
*/
19+
20+
object Gen {
21+
val MainObject = "Test"
22+
val CommandWait = 0.5
23+
24+
sealed trait Tree
25+
26+
case class Break(line: Int) extends Tree
27+
28+
case class Command(val name: String, val expect: Expect = EmptyExpect) extends Tree
29+
30+
sealed trait Expect
31+
32+
case object EmptyExpect extends Expect
33+
34+
case class LitExpect(lit: String) extends Expect
35+
36+
case class PatExpect(pat: String) extends Expect
37+
38+
case class Program(breaks: Seq[Break], commands: Seq[Command])
39+
40+
def error(msg: String): Nothing = {
41+
throw new Exception(msg)
42+
}
43+
44+
def parseCommand(command: String, lineNo: Int): Tree = {
45+
val index = command.indexOf(':')
46+
if (index == -1) {
47+
// simple command
48+
if (command == "break") Break(lineNo)
49+
else Command(command)
50+
} else {
51+
val Seq(cmd, rhs) = command.split(":", 2).toSeq.map(_.trim)
52+
if (rhs.startsWith("\"")) {
53+
// regex match
54+
val content = "\"(.+)\"".r
55+
rhs match {
56+
case content(expect) => Command(cmd, PatExpect(expect))
57+
case _ => error(s"""incorrect specification: `$rhs` for `$cmd` at line $lineNo. Ending " expected.""")
58+
}
59+
} else {
60+
// literal match
61+
Command(cmd, LitExpect(rhs))
62+
}
63+
}
64+
}
65+
66+
def parse(file: String): Program = {
67+
val lines = Source.fromFile(file).getLines.toBuffer
68+
69+
val breaks = new ListBuffer[Break]()
70+
val cmds = new ListBuffer[Command]()
71+
lines.zipWithIndex.map { case (code, line) =>
72+
val comment = if (code.indexOf("//") != -1) code.split("//").last else ""
73+
val regex = """(?<=\[).*?(?=\])""".r
74+
for (p <- regex findAllIn comment) parseCommand(p.trim, line + 1) match { // jdb index from 0
75+
case b: Break => breaks += b
76+
case c: Command => cmds += c
77+
}
78+
}
79+
80+
Program(breaks, cmds)
81+
}
82+
83+
def generate(program: Program, source: String = "tests/debug/"): String = {
84+
val Program(breaks, cmds) = program
85+
val breakpoints = (breaks.map {
86+
case Break(point) =>
87+
s"""|send "stop at $MainObject$$:$point\\r"
88+
|sleep $CommandWait
89+
|expect "breakpoint $MainObject$$:$point"
90+
|expect -re $$
91+
""".stripMargin
92+
}).mkString("\n\n")
93+
94+
val commands = (cmds.map {
95+
case Command(cmd, EmptyExpect) =>
96+
s"""|# send_user "send command `$cmd`\\n"
97+
|send "$cmd\\r"
98+
|sleep $CommandWait
99+
|expect -re $$
100+
""".stripMargin
101+
case Command(cmd, LitExpect(lit)) =>
102+
s"""|# send_user "send command `$cmd`\\n"
103+
|send "$cmd\\r"
104+
|sleep $CommandWait
105+
|expect {
106+
| "*$lit*" { send_user "success - $cmd : $lit \\n" }
107+
| timeout {
108+
| send_user "timeout while waiting for response: $cmd : $lit\\n"
109+
| exit 1
110+
| }
111+
|}
112+
|expect -re $$
113+
|""".stripMargin
114+
case Command(cmd, PatExpect(pat)) =>
115+
s"""|# send_user "send command `$cmd`\\n"
116+
|send "$cmd\\r"
117+
|sleep $CommandWait
118+
|expect {
119+
| -re {$pat} { send_user "success - $cmd : $pat \\n" }
120+
| timeout {
121+
| send_user "timeout while waiting for response: $cmd : $pat\\n"
122+
| exit 1
123+
| }
124+
|}
125+
|expect -re $$
126+
|""".stripMargin
127+
}).mkString("\n\n")
128+
129+
s"""|#!/usr/bin/expect
130+
|
131+
|# log_user 1
132+
|# exp_internal 1
133+
|# set timeout 5
134+
|
135+
|send_user "spawning job...\\n"
136+
|
137+
|spawn jdb -attach 5005 -sourcepath $source
138+
|
139+
|send_user "interacting...\\n"
140+
|
141+
|expect {
142+
| "*VM Started*" { send_user "success - connected to server \\n" }
143+
| timeout {
144+
| send_user "timeout while waiting for: *VM Started*\\n"
145+
| exit 1
146+
| }
147+
|}
148+
|
149+
|send_user "setting breakpoints...\\n"
150+
|
151+
|# breakpoints
152+
|$breakpoints
153+
|
154+
|# run
155+
|send_user "run program...\\n"
156+
|send "run\\r"
157+
|expect "Breakpoint hit"
158+
|
159+
|# interactions
160+
|$commands""".stripMargin
161+
}
162+
163+
def main(args: Array[String]): Unit = {
164+
val prog = Gen.parse(args(0))
165+
// println("--------------------------------")
166+
// println("prog:" + prog)
167+
// println("\n\n\n scrip:")
168+
// println("--------------------------------")
169+
println(Gen.generate(prog))
170+
}
171+
}

compiler/test/debug/test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
3+
DIR="$( cd "$( dirname "$0" )" && pwd )"
4+
5+
echo "start debug test..."
6+
for file in tests/debug/*.scala; do
7+
./bin/dotc $file || exit 1
8+
./bin/dotr -d Test > /dev/null &
9+
$DIR/Gen $file > robot
10+
expect robot 2>&1 > /dev/null
11+
12+
if [[ $? != 0 ]]; then
13+
echo "debug test failed for file $file"
14+
exit 1
15+
fi
16+
17+
echo "$file -- success"
18+
done
19+
20+
echo "debug test success!"
21+

0 commit comments

Comments
 (0)