Skip to content

fix #1484: position of while incorrect in debug #1951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pipeline:
- ln -s /var/cache/drone/ivy2 "$HOME/.ivy2"
- ./scripts/update-scala-library
- sbt -J-Xmx4096m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m -Ddotty.drone.mem=4096m "${TEST}"
- ./compiler/test/debug/test
when:
branch:
exclude: gh-pages
Expand Down
2 changes: 1 addition & 1 deletion .drone.yml.sig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIGxuIC1zIC92YXIvY2FjaGUvZHJvbmUvc2NhbGEtc2NhbGEgc2NhbGEtc2NhbGEKICAgICAgLSBsbiAtcyAvdmFyL2NhY2hlL2Ryb25lL2l2eTIgIiRIT01FLy5pdnkyIgogICAgICAtIC4vc2NyaXB0cy91cGRhdGUtc2NhbGEtbGlicmFyeQogICAgICAtIHNidCAtSi1YbXg0MDk2bSAtSi1YWDpSZXNlcnZlZENvZGVDYWNoZVNpemU9NTEybSAtSi1YWDpNYXhNZXRhc3BhY2VTaXplPTEwMjRtIC1EZG90dHkuZHJvbmUubWVtPTQwOTZtICIke1RFU1R9IgogICAgd2hlbjoKICAgICAgYnJhbmNoOgogICAgICAgIGV4Y2x1ZGU6IGdoLXBhZ2VzCgogIGRvY3VtZW50YXRpb246CiAgICBpbWFnZTogbGFtcGVwZmwvZG90dHk6bGF0ZXN0CiAgICBwdWxsOiB0cnVlCiAgICBjb21tYW5kczoKICAgICAgLSAuL3Byb2plY3Qvc2NyaXB0cy9nZW5Eb2NzICIke1RFU1R9IiAkQk9UX1BBU1MKICAgIHdoZW46CiAgICAgIGJyYW5jaDogbWFzdGVyCgogIGdpdHRlcjoKICAgIGltYWdlOiBwbHVnaW5zL2dpdHRlcgogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgc3RhdHVzOiBjaGFuZ2VkCgogIHNsYWNrOgogICAgaW1hZ2U6IHBsdWdpbnMvc2xhY2sKICAgIGNoYW5uZWw6IGRvdHR5CiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgogICAgICBzdGF0dXM6IGNoYW5nZWQKCm1hdHJpeDoKICBURVNUOgogICAgLSA7dGVzdDtkb3R0eS1iaW4tdGVzdHMvdGVzdAogICAgLSA7cHVibGlzaExvY2FsO2RvdHR5LWJvb3RzdHJhcHBlZC90ZXN0CiAgICAtIHBhcnRlc3Qtb25seS1uby1ib290c3RyYXAgLS1zaG93LWRpZmYgLS12ZXJib3NlCiAgICAtIHBhcnRlc3Qtb25seSAtLXNob3ctZGlmZiAtLXZlcmJvc2UK.VRqZiSgeE6OumPlEvs4TWfxIHNOEVjR_ZmyBmapxZ-U
eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIGxuIC1zIC92YXIvY2FjaGUvZHJvbmUvc2NhbGEtc2NhbGEgc2NhbGEtc2NhbGEKICAgICAgLSBsbiAtcyAvdmFyL2NhY2hlL2Ryb25lL2l2eTIgIiRIT01FLy5pdnkyIgogICAgICAtIC4vc2NyaXB0cy91cGRhdGUtc2NhbGEtbGlicmFyeQogICAgICAtIHNidCAtSi1YbXg0MDk2bSAtSi1YWDpSZXNlcnZlZENvZGVDYWNoZVNpemU9NTEybSAtSi1YWDpNYXhNZXRhc3BhY2VTaXplPTEwMjRtIC1EZG90dHkuZHJvbmUubWVtPTQwOTZtICIke1RFU1R9IgogICAgICAtIC4vY29tcGlsZXIvdGVzdC9kZWJ1Zy90ZXN0CiAgICB3aGVuOgogICAgICBicmFuY2g6CiAgICAgICAgZXhjbHVkZTogZ2gtcGFnZXMKCiAgZG9jdW1lbnRhdGlvbjoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIC4vcHJvamVjdC9zY3JpcHRzL2dlbkRvY3MgIiR7VEVTVH0iICRCT1RfUEFTUwogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKCiAgZ2l0dGVyOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0dGVyCiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgogICAgICBzdGF0dXM6IGNoYW5nZWQKCiAgc2xhY2s6CiAgICBpbWFnZTogcGx1Z2lucy9zbGFjawogICAgY2hhbm5lbDogZG90dHkKICAgIHdoZW46CiAgICAgIGJyYW5jaDogbWFzdGVyCiAgICAgIHN0YXR1czogY2hhbmdlZAoKbWF0cml4OgogIFRFU1Q6CiAgICAtIDt0ZXN0O2RvdHR5LWJpbi10ZXN0cy90ZXN0CiAgICAtIDtwdWJsaXNoTG9jYWw7ZG90dHktYm9vdHN0cmFwcGVkL3Rlc3QKICAgIC0gcGFydGVzdC1vbmx5LW5vLWJvb3RzdHJhcCAtLXNob3ctZGlmZiAtLXZlcmJvc2UKICAgIC0gcGFydGVzdC1vbmx5IC0tc2hvdy1kaWZmIC0tdmVyYm9zZQo.NgZCPjkR9Z1A96-ryvHIVJOsL9GI6aIvU6tGC_hv5Lo
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ build/

# Put local stuff here
local/
compiler/test/debug/Gen.jar

17 changes: 16 additions & 1 deletion bin/dotr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ fi
DOTTY_ROOT="$(dirname "$DOTTY_ROOT")"
DOTTY_ROOT="$( cd "$DOTTY_ROOT" >& /dev/null && pwd )/.." # absolute

# debug
DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
DEBUG=

# Load common functions and variables
source "$DOTTY_ROOT"/bin/common

Expand All @@ -24,10 +28,21 @@ function runMain {
echo "java bin not detected - please specify with \$JAVA_BIN or install java to a default location"
exit 1
else
eval "$jbin $CLASS_PATH $@"
eval "$jbin $DEBUG $CLASS_PATH $@"
fi
}

# parse command line params -d to enable debugging
while getopts "dx" opt; do
case "$opt" in
d)
DEBUG="$DEBUG_STR"
;;
esac
done

shift $((OPTIND-1))

first_arg="$1"

if [ -z "$1" ]; then
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -991,12 +991,12 @@ object desugar {
else Apply(ref(tupleTypeRef.classSymbol.companionModule.valRef), ts)
case WhileDo(cond, body) =>
// { <label> def while$(): Unit = if (cond) { body; while$() } ; while$() }
val call = Apply(Ident(nme.WHILE_PREFIX), Nil)
val call = Apply(Ident(nme.WHILE_PREFIX), Nil).withPos(tree.pos)
val rhs = If(cond, Block(body, call), unitLiteral)
labelDefAndCall(nme.WHILE_PREFIX, rhs, call)
case DoWhile(body, cond) =>
// { label def doWhile$(): Unit = { body; if (cond) doWhile$() } ; doWhile$() }
val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil)
val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil).withPos(tree.pos)
val rhs = Block(body, If(cond, call, unitLiteral))
labelDefAndCall(nme.DO_WHILE_PREFIX, rhs, call)
case ForDo(enums, body) =>
Expand Down
13 changes: 13 additions & 0 deletions compiler/test/debug/Gen
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#! /usr/bin/env bash

DIR="$( cd "$( dirname "$0" )" && pwd )"

SOURCE=$DIR/Gen.scala
CLASS=./Gen.class

if [ ! -e $CLASS ] || [ $SOURCE -nt $CLASS ]; then
./bin/dotc $DIR/Gen.scala
fi

./bin/dotr Gen $@

171 changes: 171 additions & 0 deletions compiler/test/debug/Gen.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import scala.io.Source
import scala.collection.mutable.ListBuffer

/** Automate testing debuggability of generated code using JDB and expect
*
* The debugging information is annotated as comments to the code in brackets:
*
* val x = f(3) // [break] [next: line=5]
* val y = 5
*
* 1. A jdb command must be wrapped in brackets, like `[step]`. All jdb commands can be used.
* 2. To check output of jdb for a command, use `[cmd: expect]`.
* 3. If `expect` is wrapped in double quotes, regex is supported.
* 4. Break commands are collected and set globally.
* 5. Other commands will be send to jdb in the order they appear in the source file
*
* Note: jdb uses line number starts from 1
*/

object Gen {
val MainObject = "Test"
val CommandWait = 0.5

sealed trait Tree

case class Break(line: Int) extends Tree

case class Command(val name: String, val expect: Expect = EmptyExpect) extends Tree

sealed trait Expect

case object EmptyExpect extends Expect

case class LitExpect(lit: String) extends Expect

case class PatExpect(pat: String) extends Expect

case class Program(breaks: Seq[Break], commands: Seq[Command])

def error(msg: String): Nothing = {
throw new Exception(msg)
}

def parseCommand(command: String, lineNo: Int): Tree = {
val index = command.indexOf(':')
if (index == -1) {
// simple command
if (command == "break") Break(lineNo)
else Command(command)
} else {
val Seq(cmd, rhs) = command.split(":", 2).toSeq.map(_.trim)
if (rhs.startsWith("\"")) {
// regex match
val content = "\"(.+)\"".r
rhs match {
case content(expect) => Command(cmd, PatExpect(expect))
case _ => error(s"""incorrect specification: `$rhs` for `$cmd` at line $lineNo. Ending " expected.""")
}
} else {
// literal match
Command(cmd, LitExpect(rhs))
}
}
}

def parse(file: String): Program = {
val lines = Source.fromFile(file).getLines.toBuffer

val breaks = new ListBuffer[Break]()
val cmds = new ListBuffer[Command]()
lines.zipWithIndex.map { case (code, line) =>
val comment = if (code.indexOf("//") != -1) code.split("//").last else ""
val regex = """(?<=\[).*?(?=\])""".r
for (p <- regex findAllIn comment) parseCommand(p.trim, line + 1) match { // jdb index from 0
case b: Break => breaks += b
case c: Command => cmds += c
}
}

Program(breaks, cmds)
}

def generate(program: Program, source: String = "tests/debug/"): String = {
val Program(breaks, cmds) = program
val breakpoints = (breaks.map {
case Break(point) =>
s"""|send "stop at $MainObject$$:$point\\r"
|sleep $CommandWait
|expect "breakpoint $MainObject$$:$point"
|expect -re $$
""".stripMargin
}).mkString("\n\n")

val commands = (cmds.map {
case Command(cmd, EmptyExpect) =>
s"""|# send_user "send command `$cmd`\\n"
|send "$cmd\\r"
|sleep $CommandWait
|expect -re $$
""".stripMargin
case Command(cmd, LitExpect(lit)) =>
s"""|# send_user "send command `$cmd`\\n"
|send "$cmd\\r"
|sleep $CommandWait
|expect {
| "*$lit*" { send_user "success - $cmd : $lit \\n" }
| timeout {
| send_user "timeout while waiting for response: $cmd : $lit\\n"
| exit 1
| }
|}
|expect -re $$
|""".stripMargin
case Command(cmd, PatExpect(pat)) =>
s"""|# send_user "send command `$cmd`\\n"
|send "$cmd\\r"
|sleep $CommandWait
|expect {
| -re {$pat} { send_user "success - $cmd : $pat \\n" }
| timeout {
| send_user "timeout while waiting for response: $cmd : $pat\\n"
| exit 1
| }
|}
|expect -re $$
|""".stripMargin
}).mkString("\n\n")

s"""|#!/usr/bin/expect
|
|# log_user 1
|# exp_internal 1
|# set timeout 5
|
|send_user "spawning job...\\n"
|
|spawn jdb -attach 5005 -sourcepath $source
|
|send_user "interacting...\\n"
|
|expect {
| "*VM Started*" { send_user "success - connected to server \\n" }
| timeout {
| send_user "timeout while waiting for: *VM Started*\\n"
| exit 1
| }
|}
|
|send_user "setting breakpoints...\\n"
|
|# breakpoints
|$breakpoints
|
|# run
|send_user "run program...\\n"
|send "run\\r"
|expect "Breakpoint hit"
|
|# interactions
|$commands""".stripMargin
}

def main(args: Array[String]): Unit = {
val prog = Gen.parse(args(0))
// println("--------------------------------")
// println("prog:" + prog)
// println("\n\n\n scrip:")
// println("--------------------------------")
println(Gen.generate(prog))
}
}
21 changes: 21 additions & 0 deletions compiler/test/debug/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash

DIR="$( cd "$( dirname "$0" )" && pwd )"

echo "start debug test..."
for file in tests/debug/*.scala; do
./bin/dotc $file || exit 1
./bin/dotr -d Test > /dev/null &
$DIR/Gen $file > robot
expect robot 2>&1 > /dev/null

if [[ $? != 0 ]]; then
echo "debug test failed for file $file"
exit 1
fi

echo "$file -- success"
done

echo "debug test success!"

Loading