summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-05 20:42:42 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-05 20:42:42 -0800
commitc7d96c649cf2b2832a597df405f3c1afcd674009 (patch)
tree3aca3cf0c316a4ed08039c009bbd22ff7c1097b6
parent8e8f9bb1d2e05d946ba55e273027d05345057d4d (diff)
downloadhands-on-scala-js-c7d96c649cf2b2832a597df405f3c1afcd674009.tar.gz
hands-on-scala-js-c7d96c649cf2b2832a597df405f3c1afcd674009.tar.bz2
hands-on-scala-js-c7d96c649cf2b2832a597df405f3c1afcd674009.zip
A bunch of error tests work, trimming is causing problems with multi-line error messages
-rw-r--r--build.sbt1
-rw-r--r--scalatexApi/src/main/scala/scalatex/stages/Compiler.scala28
-rw-r--r--scalatexApi/src/main/scala/scalatex/stages/Parser.scala19
-rw-r--r--scalatexApi/src/test/scala/scalatex/ErrorTests.scala104
-rw-r--r--scalatexApi/src/test/scala/scalatex/ParserTests.scala54
5 files changed, 123 insertions, 83 deletions
diff --git a/build.sbt b/build.sbt
index a6d87ed..9a40e85 100644
--- a/build.sbt
+++ b/build.sbt
@@ -60,4 +60,5 @@ lazy val book = Project(
}
)
+
lazy val demos = project.in(file("examples/demos")) \ No newline at end of file
diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
index 7d1492c..9c1c3c4 100644
--- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
+++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
@@ -15,23 +15,43 @@ object Compiler{
import c.universe._
def fragType = tq"scalatags.Text.all.Frag"
+ def incPosRec(trees: c.Tree, offset: Int): trees.type = {
+ println(s"incPosRec\t$offset\t$trees")
+ trees.foreach(incPos(_, offset))
+ trees
+ }
+ def incPos(tree: c.Tree, offset: Int): tree.type = {
+ println(s"incPos\t$offset\t$tree")
+ val current = if (tree.pos == NoPosition) 0 else tree.pos.point
+ c.internal.setPos(tree,
+ new OffsetPosition(
+ fragPos.source,
+ offset + current + fragPos.point
+ ).asInstanceOf[c.universe.Position]
+ )
+ tree
+ }
+
println(template)
def compileChain(code: String, parts: Seq[Ast.Chain.Sub], offset: Int): c.Tree = {
println("CODE " + code)
- parts.foldLeft(c.parse(code)){
- case (curr, Ast.Chain.Prop(str, offset2)) => q"$curr.${TermName(str)}"
+ val out = parts.foldLeft(incPosRec(c.parse(code), offset + 1)){
+ case (curr, Ast.Chain.Prop(str, offset2)) =>
+ incPos(q"$curr.${TermName(str)}", offset2 + 1)
case (curr, Ast.Chain.Args(str, offset2)) =>
val Apply(fun, args) = c.parse(s"omg$str")
- Apply(curr, args)
+ incPos(Apply(curr, args.map(incPosRec(_, offset2 - 2))), offset2)
case (curr, Ast.Chain.TypeArgs(str, offset2)) =>
val TypeApply(fun, args) = c.parse(s"omg$str")
- TypeApply(curr, args)
+ incPos(TypeApply(curr, args.map(incPosRec(_, offset2 - 2))), offset2)
case (curr, Ast.Block(parts, offset)) =>
q"$curr(..${compileBlock(parts, offset)})"
case (curr, Ast.Header(header, block, offset)) =>
q"$curr(${compileHeader(header, block, offset)})"
}
+ out.foreach(o => println(o.pos + "\t" + o))
+ out
}
def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): Seq[c.Tree] = {
parts.map{
diff --git a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
index 7b694da..45f82e0 100644
--- a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
+++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
@@ -11,12 +11,13 @@ import Util._
* enough until we stuff the code-strings into the real Scala
* parser later
*/
-object Parser extends (String => Ast.Block){
- def apply(input: String): Ast.Block = {
+object Parser extends ((String, Int) => Ast.Block){
+ def apply(input: String, offset: Int = 0): Ast.Block = {
new Parser(input).Body.run().get
}
}
-class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
+class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends ScalaSyntax(input) {
+ def offsetCursor = offset + cursor
val txt = input.sliceString(0, input.length)
val indentTable = txt.split('\n').map{ s =>
if (s.trim == "") -1
@@ -45,7 +46,7 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
}
def HeaderBlock: Rule1[Ast.Header] = rule{
- Header ~ zeroOrMore(capture(NewlineS) ~ Header ~> (_ + _)) ~ runSubParser{new Parser(_, indent).Body0} ~> {
+ Header ~ zeroOrMore(capture(NewlineS) ~ Header ~> (_ + _)) ~ runSubParser{new Parser(_, indent, cursor).Body0} ~> {
(start: String, heads: Seq[String], body: Ast.Block) => Ast.Header(start + heads.mkString, body)
}
}
@@ -63,7 +64,7 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
def IndentBlock = rule{
&("\n") ~
test(cursorNextIndent() > indent) ~
- runSubParser(new Parser(_, cursorNextIndent()).Body)
+ runSubParser(new Parser(_, cursorNextIndent(), cursor).Body)
}
def IfHead = rule{ "@" ~ capture("if" ~ "(" ~ Expr ~ ")") }
def IfElse1 = rule{
@@ -91,12 +92,12 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
}
def ScalaChain = rule {
- Code ~ zeroOrMore(Extension) ~> {Ast.Chain(_, _)}
+ push(offsetCursor) ~ Code ~ zeroOrMore(Extension) ~> { (a, b, c) => Ast.Chain(b, c, a)}
}
def Extension: Rule1[Ast.Chain.Sub] = rule {
- ('.' ~ capture(Id) ~> (Ast.Chain.Prop(_))) |
- (capture(TypeArgs2) ~> (Ast.Chain.TypeArgs(_))) |
- (capture(ArgumentExprs2) ~> (Ast.Chain.Args(_))) |
+ (push(offsetCursor) ~ '.' ~ capture(Id) ~> ((x, y) => Ast.Chain.Prop(y, x))) |
+ (push(offsetCursor) ~ capture(TypeArgs2) ~> ((x, y) => Ast.Chain.TypeArgs(y, x))) |
+ (push(offsetCursor) ~ capture(ArgumentExprs2) ~> ((x, y) => Ast.Chain.Args(y, x))) |
BraceBlock
}
def Ws = Whitespace
diff --git a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala
index 4a2b5c8..7b40c40 100644
--- a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala
+++ b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala
@@ -1,35 +1,35 @@
-//package scalatex
-//
-//import utest._
-//import scalatex.stages._
-//import scalatags.Text.all._
-//import scalatex.Internals.{DebugFailure, twRuntimeErrors}
-//
-///**
-//* Created by haoyi on 7/14/14.
-//*/
-//object ErrorTests extends TestSuite{
-// def check(x: => Unit, expectedMsg: String, expectedError: String) = {
-// val DebugFailure(msg, pos) = intercept[DebugFailure](x)
-// def format(str: String) = {
-// val whitespace = " \t\n".toSet
-// "\n" + str.dropWhile(_ == '\n')
-// .reverse
-// .dropWhile(whitespace.contains)
-// .reverse
-// }
-// // Format these guys nicely to normalize them and make them
-// // display nicely in the assert error message if it blows up
-// val formattedPos = format(pos)
-// val formattedExpectedPos = format(expectedError)
-//
-// assert(msg.contains(expectedMsg))
-// assert(formattedPos == formattedExpectedPos)
-//
-// }
-// val tests = TestSuite{
-//
-//
+package scalatex
+
+import utest._
+import scalatex.stages._
+import scalatags.Text.all._
+import scalatex.Internals.{DebugFailure, twRuntimeErrors}
+
+/**
+* Created by haoyi on 7/14/14.
+*/
+object ErrorTests extends TestSuite{
+ def check(x: => Unit, expectedMsg: String, expectedError: String) = {
+ val DebugFailure(msg, pos) = intercept[DebugFailure](x)
+ def format(str: String) = {
+ val whitespace = " \t\n".toSet
+ "\n" + str.dropWhile(_ == '\n')
+ .reverse
+ .dropWhile(whitespace.contains)
+ .reverse
+ }
+ // Format these guys nicely to normalize them and make them
+ // display nicely in the assert error message if it blows up
+ val formattedPos = format(pos)
+ val formattedExpectedPos = format(expectedError)
+
+ assert(msg.contains(expectedMsg))
+ assert(formattedPos == formattedExpectedPos)
+
+ }
+ val tests = TestSuite{
+
+
// 'simple - check(
// twRuntimeErrors("omg @notInScope lol"),
// """not found: value notInScope""",
@@ -40,7 +40,7 @@
// )
//
// 'chained{
-// 'properties {
+ 'properties {
// * - check(
// twRuntimeErrors("omg @math.lol lol"),
// """object lol is not a member of package math""",
@@ -133,18 +133,34 @@
// """
// )
// * - check(
-// twRuntimeErrors("""
-// I am cow hear me moo
-// @scala.math.abs(-10).tdo(10).sum.z
-// I weigh twice as much as you
-// """),
-// "value tdo is not a member of Int",
+// twRuntimeErrors("@scala.math.cos('omg)"),
+// "type mismatch",
// """
-// @scala.math.abs(-10).tdo(10).sum.z
-// ^
+// twRuntimeErrors("@scala.math.cos('omg)"),
+// ^
// """
// )
-// }
+// * - check(
+// twRuntimeErrors("@scala.math.cos[omg]('omg)"),
+// "not found: type omg",
+// """
+// twRuntimeErrors("@scala.math.cos[omg]('omg)"),
+// ^
+// """
+// )
+ * - check(
+ twRuntimeErrors("""
+ I am cow hear me moo
+ @scala.math.abs(-10).tdo(10).sum.z
+ I weigh twice as much as you
+ """),
+ "value tdo is not a member of Int",
+ """
+ @scala.math.abs(-10).tdo(10).sum.z
+ ^
+ """
+ )
+ }
// 'curlies{
// * - check(
// twRuntimeErrors("@p{@Seq(1, 2, 3).foldLeft(0)}"),
@@ -353,5 +369,5 @@
// """
// )
// }
-// }
-//}
+ }
+}
diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala
index 150f766..401cfae 100644
--- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala
+++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala
@@ -123,28 +123,28 @@ object ParserTests extends utest.TestSuite{
* - check("{i @am a @cow}", _.BraceBlock.run(),
Block(Seq(
Block.Text("i "),
- Chain("am",Seq()),
+ Chain("am",Seq(), 3),
Block.Text(" a "),
- Chain("cow",Seq())
+ Chain("cow",Seq(), 9)
))
)
}
'Chain{
* - check("@omg.bbq[omg].fff[fff](123) ", _.ScalaChain.run(),
Chain("omg",Seq(
- Chain.Prop("bbq"),
- Chain.TypeArgs("[omg]"),
- Chain.Prop("fff"),
- Chain.TypeArgs("[fff]"),
- Chain.Args("(123)")
+ Chain.Prop("bbq", 4),
+ Chain.TypeArgs("[omg]", 8),
+ Chain.Prop("fff", 13),
+ Chain.TypeArgs("[fff]", 17),
+ Chain.Args("(123)", 22)
))
)
* - check("@omg{bbq}.cow(moo){a @b}\n", _.ScalaChain.run(),
Chain("omg",Seq(
Block(Seq(Block.Text("bbq"))),
- Chain.Prop("cow"),
- Chain.Args("(moo)"),
- Block(Seq(Block.Text("a "), Chain("b", Nil)))
+ Chain.Prop("cow", 9),
+ Chain.Args("(moo)", 13),
+ Block(Seq(Block.Text("a "), Chain("b", Nil, 21)))
))
)
}
@@ -240,7 +240,7 @@ object ParserTests extends utest.TestSuite{
Text("\n "), Text("Hello"), Text("\n "))),
Some(Block(Vector(
Text("\n "), Text("lols"), Text("\n "))))
- ))))),
+ )))), 1),
Text("\n")
))
assert(res == expected)
@@ -276,10 +276,10 @@ object ParserTests extends utest.TestSuite{
Text("\n "),
Chain("bbq",Seq(Block(Seq(
Text("\n "),
- Chain("lol",Seq())
- ))))
- ))))
- ))))
+ Chain("lol",Seq(), 16)
+ ))), 12)
+ ))), 8)
+ ))), 1)
))
)
'dedents - check(
@@ -293,11 +293,11 @@ object ParserTests extends utest.TestSuite{
Chain("omg",Seq(Block(
Seq(
Text("\n "),
- Chain("wtf",Seq())
+ Chain("wtf",Seq(), 8)
)
- ))),
+ )), 1),
Text("\n"),
- Chain("bbq", Seq())
+ Chain("bbq", Seq(), 13)
))
)
'braces - check(
@@ -312,12 +312,12 @@ object ParserTests extends utest.TestSuite{
Chain("omg",Seq(Block(
Seq(
Text("\n "),
- Chain("wtf",Seq()),
+ Chain("wtf",Seq(), 9),
Text("\n")
)
- ))),
+ )), 1),
Text("\n"),
- Chain("bbq", Seq())
+ Chain("bbq", Seq(), 16)
))
)
'dedentText - check(
@@ -329,11 +329,12 @@ object ParserTests extends utest.TestSuite{
Block(Seq(
Text("\n"),
Chain("omg",Seq(
- Args("""("lol", 1, 2)"""),
+ Args("""("lol", 1, 2)""", 5),
Block(Seq(
Text("\n "),
- Chain("wtf",Seq())))
- )),
+ Chain("wtf",Seq(), 21)
+ ))
+ ), 1),
Text("\n"),
Text("bbq")
))
@@ -368,13 +369,14 @@ object ParserTests extends utest.TestSuite{
_.Body.run(),
Block(Seq(
Text("\n"),
- Chain("{\"lol\" * 3}", Seq()),
+ Chain("{\"lol\" * 3}", Seq(), 1),
Text("\n"),
Chain("""{
| val omg = "omg"
| omg * 2
|}""".stripMargin,
- Seq()
+ Seq(),
+ 14
)
))
)