diff options
author | Li Haoyi <haoyi@dropbox.com> | 2014-11-05 22:25:58 -0800 |
---|---|---|
committer | Li Haoyi <haoyi@dropbox.com> | 2014-11-05 22:25:58 -0800 |
commit | 784f3da4192a0e30ddd94cfb10f91d0bc8dc4f7f (patch) | |
tree | 83bc659db8b89e904b6b3377d91ef3016be98d18 | |
parent | 62871430033658a36e04772a4417526ac399b0dc (diff) | |
download | hands-on-scala-js-784f3da4192a0e30ddd94cfb10f91d0bc8dc4f7f.tar.gz hands-on-scala-js-784f3da4192a0e30ddd94cfb10f91d0bc8dc4f7f.tar.bz2 hands-on-scala-js-784f3da4192a0e30ddd94cfb10f91d0bc8dc4f7f.zip |
Fixed the Scala grammar, property/call/type-param chaining now works and more tests pass
-rw-r--r-- | scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala | 33 | ||||
-rw-r--r-- | scalatexApi/src/test/scala/scalatex/BasicTests.scala | 868 | ||||
-rw-r--r-- | scalatexApi/src/test/scala/scalatex/ErrorTests.scala | 650 | ||||
-rw-r--r-- | scalatexApi/src/test/scala/scalatex/ParserTests.scala | 732 |
4 files changed, 1148 insertions, 1135 deletions
diff --git a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala index 3e0c408..caaac87 100644 --- a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala +++ b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala @@ -98,7 +98,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif ForCFlow | "throw" ~ Expr | "return" ~ optional(Expr) | - SimpleExpr1 ~ ArgumentExprs ~ '=' ~ Expr | + SimpleExpr ~ ArgumentExprs ~ '=' ~ Expr | optional(SimpleExpr ~ '.') ~ IdS ~ '=' ~ Expr | PostfixExpr ~ optional("match" ~ '{' ~ CaseClauses ~ '}' | Ascription) } @@ -111,19 +111,32 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif def PostfixExpr: Rule0 = rule { InfixExpr ~ optional(IdS ~ optional(NewlineS)) } def InfixExpr: Rule0 = rule { PrefixExpr ~ zeroOrMore(IdS ~ optional(NewlineS) ~ PrefixExpr) } def PrefixExpr = rule { optional(anyOf("-+~!")) ~ SimpleExpr } - def SimpleExpr: Rule0 = rule { SimpleExpr1 ~ optional(ArgumentExprs) ~ optional('_') | SimpleExprNoLiteral} - def SimpleExprNoLiteral: Rule0 = rule { - "new" ~ (ClassTemplate | TemplateBody) | BlockExpr | '(' ~ optional(Exprs) ~ ')' +""" + SimpleExpr ::= ‘new’ (ClassTemplate | TemplateBody) + | BlockExpr + | SimpleExpr1 [‘_’] + SimpleExpr1 ::= Literal + | Path + | ‘_’ + | ‘(’ [Exprs] ‘)’ + | SimpleExpr ‘.’ id s + | SimpleExpr TypeArgs + | SimpleExpr1 ArgmentExprs +""" + def SimpleExpr: Rule0 = rule { + SimpleExpr1 ~ zeroOrMore('.' ~ IdS | TypeArgs | ArgumentExprs) ~ optional('_') } - def SimpleExpr1: Rule0 = rule { - // run(println("SimpleExpr1 matching on " + pos)) ~ - LiteralS ~ drop[String] | //literal currently captures, so it can be used outside. but since all our rules lack AST, we drop its value in order to be able to compose them + + def SimpleExpr1 = rule{ + "new" ~ (ClassTemplate | TemplateBody) | + BlockExpr | + LiteralS ~ drop[String] | Path | '_' | - SimpleExprNoLiteral ~ '.' ~ IdS | - SimpleExprNoLiteral ~ TypeArgs /*| - XmlExpr*/ + '(' ~ optional(Exprs) ~ ')' } + + def Exprs: Rule0 = rule { oneOrMore(Expr).separatedBy(',') } def ArgumentExprs: Rule0 = rule { '(' ~ (optional(Exprs ~ ',') ~ PostfixExpr ~ ':' ~ '_' ~ '*' | optional(Exprs)) ~ ')' | diff --git a/scalatexApi/src/test/scala/scalatex/BasicTests.scala b/scalatexApi/src/test/scala/scalatex/BasicTests.scala index fc4bff8..4bc362c 100644 --- a/scalatexApi/src/test/scala/scalatex/BasicTests.scala +++ b/scalatexApi/src/test/scala/scalatex/BasicTests.scala @@ -1,468 +1,468 @@ -//package scalatex -//import utest._ -//import scala.collection.mutable.ArrayBuffer -//import scalatex.stages._ -//import scalatags.Text.all._ +package scalatex +import utest._ +import scala.collection.mutable.ArrayBuffer +import scalatex.stages._ +import scalatags.Text.all._ + + +/** +* Created by haoyi on 7/14/14. +*/ +object BasicTests extends TestSuite{ + import TestUtil._ + + val tests = TestSuite{ + + 'helloWorld{ + object omg { + def wtf(s: Frag*): Frag = Seq[Frag]("|", s, "|") + } + def str = "hear me moo" + check( + tw(""" + @omg.wtf + i @b{am} cow @str + """), + "|i<b>am</b>cowhearmemoo|" + ) + } + 'interpolation{ + 'chained-check( + tw("omg @scala.math.pow(0.5, 3) wtf"), + "omg 0.125 wtf" + ) + 'parens-check( + tw("omg @(1 + 2 + 3 + 4) wtf"), + "omg 10 wtf" + ) + 'block-check( + tw(""" + @{"lol" * 3} + @{ + val omg = "omg" + omg * 2 + } + """), + """ + lollollol + omgomg + """ + ) + } + 'definitions{ + 'imports{ + object Whee{ + def func(x: Int) = x * 2 + } + check( + tw(""" + @import math._ + @import Whee.func + @abs(-10) + @p + @max(1, 2) + @func(2) + """), + """ + 10 + <p> + 2 + 4 + </p> + """ + ) + } + 'valDefVar{ + check( + tw(""" + Hello + @val x = 1 + World @x + @def y = "omg" + mooo + @y + """), + """ + Hello + World 1 + mooo + omg + """ + ) + } + 'classObjectTrait{ + check( + tw(""" + @trait Trait{ + def tt = 2 + } + Hello + @case object moo extends Trait{ + val omg = "wtf" + } + + @moo.toString + @moo.omg + @case class Foo(i: Int, s: String, b: Boolean) + TT is @moo.tt + @Foo(10, "10", true).toString + """), + """ + Hello + moo + wtf + TT is 2 + Foo(10, 10, true) + """ + ) + } + } + 'parenArgumentLists{ + 'attributes{ + check( + tw(""" + @div(id:="my-id"){ omg } + @div(id:="my-id") + omg + """), + """ + <divid="my-id">omg</div> + <divid="my-id">omg</div> + """ + ) + } +// 'multiline{ // -// -///** -//* Created by haoyi on 7/14/14. -//*/ -//object BasicTests extends TestSuite{ -// import TestUtil._ -// -// val tests = TestSuite{ -// -// 'helloWorld{ -// object omg { -// def wtf(s: Frag*): Frag = Seq[Frag]("|", s, "|") -// } -// def str = "hear me moo" -// check( -// tw(""" -// @omg.wtf -// i @b{am} cow @str -// """), -// "|i<b>am</b>cowhearmemoo|" -// ) -// } -// 'interpolation{ -// 'chained-check( -// tw("omg @scala.math.pow(0.5, 3) wtf"), -// "omg 0.125 wtf" -// ) -// 'parens-check( -// tw("omg @(1 + 2 + 3 + 4) wtf"), -// "omg 10 wtf" -// ) -// 'block-check( -// tw(""" -// @{"lol" * 3} -// @{ -// val omg = "omg" -// omg * 2 -// } -// """), -// """ -// lollollol -// omgomg -// """ -// ) -// } -// 'definitions{ -// 'imports{ -// object Whee{ -// def func(x: Int) = x * 2 -// } -// check( -// tw(""" -// @import math._ -// @import Whee.func -// @abs(-10) -// @p -// @max(1, 2) -// @func(2) -// """), -// """ -// 10 -// <p> -// 2 -// 4 -// </p> -// """ -// ) -// } -// 'valDefVar{ // check( // tw(""" -// Hello -// @val x = 1 -// World @x -// @def y = "omg" -// mooo -// @y +// @div( +// h1("Hello World"), +// p("I am a ", b{"cow"}) +// ) // """), // """ -// Hello -// World 1 -// mooo -// omg +// <div> +// <h1>Hello World</h1> +// <p>I am a <b>cow</b></p> +// </div> // """ // ) // } -// 'classObjectTrait{ -// check( -// tw(""" -// @trait Trait{ -// def tt = 2 -// } -// Hello -// @case object moo extends Trait{ -// val omg = "wtf" -// } + } + 'grouping{ + 'negative{ + // The indentation for "normal" text is ignored; we only + // create blocks from the indentation following a scala + // @xxx expression + check( + tw(""" + I am cow hear me moo + I weigh twice as much as you + And I look good on the barbecue + Yoghurt curds cream cheese and butter + Comes from liquids from my udder + I am cow I am cow hear me moooooo + """), + """ + I am cow hear me moo + I weigh twice as much as you + And I look good on the barbecue + Yoghurt curds cream cheese and butter + Comes from liquids from my udder + I am cow I am cow hear me moooooo + """ + ) + } + 'indentation{ + 'simple{ + val world = "World2" + + check( + tw(""" + @h1 + Hello World + @h2 + hello @world + @h3 + Cow + """), + """ + <h1>HelloWorld</h1> + <h2>helloWorld2</h2> + <h3>Cow</h3> + """ + ) + } + 'linearNested{ + check( + tw(""" + @h1 @span @a Hello World + @h2 @span @a hello + @b world + @h3 @i + @div Cow + """), + """ + <h1></h1><span></span><a></a>HelloWorld + <h2></h2><span></span><a></a>hello<b></b>world + <h3></h3><i></i><div></div>Cow + """ + ) + } + 'crasher{ + tw(""" +@html + @head + @meta + @div + @a + @span + """) + } + } + 'curlies{ + 'simple{ + val world = "World2" + + check( + tw("""@div{Hello World}"""), + """<div>HelloWorld</div>""" + ) + } + 'multiline{ + check( + tw(""" + @div{ + Hello + } + """), + """ + <div>Hello</div> + """ + ) + } + } + 'mixed{ + check( + tw(""" + @div{ + Hello + @div + @h1 + WORLD @b{!!!} + lol + @p{ + @h2{Header 2} + } + } + """), + """ + <div> + Hello + <div> + <h1>WORLD<b>!!!</b>lol</h1> + <p><h2>Header2</h2></p> + </div> + </div> + """ + ) + } // -// @moo.toString -// @moo.omg -// @case class Foo(i: Int, s: String, b: Boolean) -// TT is @moo.tt -// @Foo(10, "10", true).toString -// """), -// """ -// Hello -// moo -// wtf -// TT is 2 -// Foo(10, 10, true) -// """ -// ) -// } -// } -// 'parenArgumentLists{ -// 'attributes{ +// 'args{ +// val things = Seq(1, 2, 3) // check( // tw(""" -// @div(id:="my-id"){ omg } -// @div(id:="my-id") -// omg -// """), -// """ -// <divid="my-id">omg</div> -// <divid="my-id">omg</div> -// """ -// ) -// } -//// 'multiline{ -//// -//// check( -//// tw(""" -//// @div( -//// h1("Hello World"), -//// p("I am a ", b{"cow"}) -//// ) -//// """), -//// """ -//// <div> -//// <h1>Hello World</h1> -//// <p>I am a <b>cow</b></p> -//// </div> -//// """ -//// ) -//// } -// } -// 'grouping{ -// 'negative{ -// // The indentation for "normal" text is ignored; we only -// // create blocks from the indentation following a scala -// // @xxx expression -// check( -// tw(""" -// I am cow hear me moo -// I weigh twice as much as you -// And I look good on the barbecue -// Yoghurt curds cream cheese and butter -// Comes from liquids from my udder -// I am cow I am cow hear me moooooo +// @ul +// @things.map { x => +// @li +// @x +// } // """), -// """ -// I am cow hear me moo -// I weigh twice as much as you -// And I look good on the barbecue -// Yoghurt curds cream cheese and butter -// Comes from liquids from my udder -// I am cow I am cow hear me moooooo -// """ -// ) -// } -// 'indentation{ -// 'simple{ -// val world = "World2" -// -// check( -// tw(""" -// @h1 -// Hello World -// @h2 -// hello @world -// @h3 -// Cow -// """), -// """ -// <h1>HelloWorld</h1> -// <h2>helloWorld2</h2> -// <h3>Cow</h3> -// """ -// ) -// } -// 'linearNested{ -// check( -// tw(""" -// @h1 @span @a Hello World -// @h2 @span @a hello -// @b world -// @h3 @i -// @div Cow -// """), -// """ -// <h1></h1><span></span><a></a>HelloWorld -// <h2></h2><span></span><a></a>hello<b></b>world -// <h3></h3><i></i><div></div>Cow -// """ -// ) -// } -// 'crasher{ // tw(""" -//@html -// @head -// @meta -// @div -// @a -// @span -// """) -// } -// } -// 'curlies{ -// 'simple{ -// val world = "World2" +// @ul +// @things.map x => +// @li +// @x // -// check( -// tw("""@div{Hello World}"""), -// """<div>HelloWorld</div>""" -// ) -// } -// 'multiline{ -// check( -// tw(""" -// @div{ -// Hello -// } -// """), -// """ -// <div>Hello</div> -// """ -// ) -// } -// } -// 'mixed{ -// check( -// tw(""" -// @div{ -// Hello -// @div -// @h1 -// WORLD @b{!!!} -// lol -// @p{ -// @h2{Header 2} -// } -// } // """), // """ -// <div> -// Hello -// <div> -// <h1>WORLD<b>!!!</b>lol</h1> -// <p><h2>Header2</h2></p> -// </div> -// </div> +// <ul> +// <li>1</li> +// <li>2</li> +// <li>3</li> +// </ul> // """ // ) // } -//// -//// 'args{ -//// val things = Seq(1, 2, 3) -//// check( -//// tw(""" -//// @ul -//// @things.map { x => -//// @li -//// @x -//// } -//// """), -//// tw(""" -//// @ul -//// @things.map x => -//// @li -//// @x -//// -//// """), -//// """ -//// <ul> -//// <li>1</li> -//// <li>2</li> -//// <li>3</li> -//// </ul> -//// """ -//// ) -//// } -// } -//// -// 'loops { -//// -// * - check( -// tw(""" -// @for(x <- 0 until 3) -// lol -// """), -// tw(""" -// @for(x <- 0 until 3){ -// lol -// } -// """), -// "lollollol" -// ) + } // + 'loops { // -// * - check( -// tw(""" -// @p -// @for(x <- 0 until 2) -// @for(y <- 0 until 2) -// lol@x@y -// """), -// tw( """ -// @p -// @for(x <- 0 until 2){ -// @for(y <- 0 until 2) -// lol@x@y -// } -// """), -// tw(""" -// @p -// @for(x <- 0 until 2) -// @for(y <- 0 until 2){ -// lol@x@y -// } -// """), -// "<p>lol00lol01lol10lol11</p>" -// ) -// check( -// tw(""" -// @p -// @for(x <- 0 until 2) -// @for(y <- 0 until 2) -// lol@x@y -// """), -// "<p>lol00lol01lol10lol11</p>" -// ) -// -// * - check( -// tw( -// """ -// @for(x <- 0 until 2; y <- 0 until 2) -// @div{@x@y} -// -// """), -// """<div>00</div><div>01</div><div>10</div><div>11</div>""" -// ) -// } -// -// 'ifElse{ -// 'basicExamples{ + * - check( + tw(""" + @for(x <- 0 until 3) + lol + """), + tw(""" + @for(x <- 0 until 3){ + lol + } + """), + "lollollol" + ) + + + * - check( + tw(""" + @p + @for(x <- 0 until 2) + @for(y <- 0 until 2) + lol@x@y + """), + tw( """ + @p + @for(x <- 0 until 2){ + @for(y <- 0 until 2) + lol@x@y + } + """), + tw(""" + @p + @for(x <- 0 until 2) + @for(y <- 0 until 2){ + lol@x@y + } + """), + "<p>lol00lol01lol10lol11</p>" + ) + check( + tw(""" + @p + @for(x <- 0 until 2) + @for(y <- 0 until 2) + lol@x@y + """), + "<p>lol00lol01lol10lol11</p>" + ) + + * - check( + tw( + """ + @for(x <- 0 until 2; y <- 0 until 2) + @div{@x@y} + + """), + """<div>00</div><div>01</div><div>10</div><div>11</div>""" + ) + } + + 'ifElse{ + 'basicExamples{ + * - check( + tw(""" + @if(false) + Hello + @else + lols + @p + """), + "lols<p></p>" + ) + + * - check( + tw(""" + @div + @if(true) + Hello + @else + lols + """), + "<div>Hello</div>" + ) + + * - check( + tw(""" + @div + @if(true) + Hello + @else + lols + """), + "<div>Hello</div>" + ) + * - check( + tw(""" + @if(false) + Hello + @else + lols + """), + "lols" + ) + * - check( + tw(""" + @if(false) + Hello + @else + lols + @img + """), + "lols<img/>" + ) + * - check( + tw(""" + @p + @if(true) + Hello + @else + lols + """), + tw(""" + @p + @if(true){ + Hello + }else{ + lols + } + """), + "<p>Hello</p>" + ) + } +// 'funkyExpressions{ // * - check( // tw(""" -// @if(false) -// Hello -// @else -// lols // @p -// """), -// "lols<p></p>" -// ) -// -// * - check( -// tw(""" -// @div -// @if(true) -// Hello +// @if(true == false == (true.==(false))) +// @if(true == false == (true.==(false))) +// Hello1 +// @else +// lols1 // @else -// lols +// @if(true == false == (true.==(false))) +// Hello2 +// @else +// lols2 // """), -// "<div>Hello</div>" -// ) -// -// * - check( -// tw(""" -// @div -// @if(true) -// Hello -// @else -// lols -// """), -// "<div>Hello</div>" -// ) -// * - check( -// tw(""" -// @if(false) -// Hello -// @else -// lols -// """), -// "lols" -// ) -// * - check( -// tw(""" -// @if(false) -// Hello -// @else -// lols -// @img -// """), -// "lols<img/>" +// "<p>Hello1</p>" // ) // * - check( // tw(""" // @p -// @if(true) -// Hello +// @if(true == false != (true.==(false))) +// @if(true == false != (true.==(false))) +// Hello1 +// @else +// lols1 // @else -// lols +// @if(true == false != (true.==(false))) +// Hello2 +// @else +// lols2 // """), -// tw(""" -// @p -// @if(true){ -// Hello -// }else{ -// lols -// } -// """), -// "<p>Hello</p>" +// "<p>lols2</p>" // ) // } -//// 'funkyExpressions{ -//// * - check( -//// tw(""" -//// @p -//// @if(true == false == (true.==(false))) -//// @if(true == false == (true.==(false))) -//// Hello1 -//// @else -//// lols1 -//// @else -//// @if(true == false == (true.==(false))) -//// Hello2 -//// @else -//// lols2 -//// """), -//// "<p>Hello1</p>" -//// ) -//// * - check( -//// tw(""" -//// @p -//// @if(true == false != (true.==(false))) -//// @if(true == false != (true.==(false))) -//// Hello1 -//// @else -//// lols1 -//// @else -//// @if(true == false != (true.==(false))) -//// Hello2 -//// @else -//// lols2 -//// """), -//// "<p>lols2</p>" -//// ) -//// } -// } -// } -// -//} + } + } + +} diff --git a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala index 77afd8c..8535b72 100644 --- a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala @@ -1,373 +1,373 @@ -//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""", -// """ -// twRuntimeErrors("omg @notInScope lol"), -// ^ -// """ -// ) -// -//// 'chained{ -// 'properties { -// * - check( -// twRuntimeErrors("omg @math.lol lol"), -// """object lol is not a member of package math""", -// """ -// twRuntimeErrors("omg @math.lol lol"), -// ^ -// """ -// ) -// -// * - check( -// twRuntimeErrors("omg @math.E.lol lol"), -// """value lol is not a member of Double""", -// """ -// twRuntimeErrors("omg @math.E.lol lol"), -// ^ -// """ -// ) -// * - check( -// twRuntimeErrors("omg @_root_.scala.math.lol lol"), -// """object lol is not a member of package math""", -// """ -// twRuntimeErrors("omg @_root_.scala.math.lol lol"), -// ^ -// """ -// ) +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""", + """ + twRuntimeErrors("omg @notInScope lol"), + ^ + """ + ) + +// 'chained{ + 'properties { + * - check( + twRuntimeErrors("omg @math.lol lol"), + """object lol is not a member of package math""", + """ + twRuntimeErrors("omg @math.lol lol"), + ^ + """ + ) + + * - check( + twRuntimeErrors("omg @math.E.lol lol"), + """value lol is not a member of Double""", + """ + twRuntimeErrors("omg @math.E.lol lol"), + ^ + """ + ) + * - check( + twRuntimeErrors("omg @_root_.scala.math.lol lol"), + """object lol is not a member of package math""", + """ + twRuntimeErrors("omg @_root_.scala.math.lol lol"), + ^ + """ + ) + * - check( + twRuntimeErrors("omg @_root_.scala.gg.lol lol"), + """object gg is not a member of package scala""", + """ + twRuntimeErrors("omg @_root_.scala.gg.lol lol"), + ^ + """ + ) + * - check( + twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), + """object ggnore is not a member of package <root>""", + """ + twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), + ^ + """ + ) + } + 'calls{ + * - check( + twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), + """object QQ is not a member of package scala""", + """ + twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), + "value tdo is not a member of Int", + """ + twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), + "value z is not a member of Int", + """ + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), + "value z is not a member of Int", + """ + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), + "value cow is not a member of Int", + """ + twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.smath.abs.cow.sum.z"), + "object smath is not a member of package scala", + """ + twRuntimeErrors("@scala.smath.abs.cow.sum.z"), + ^ + """ + ) + * - check( + twRuntimeErrors("@scala.math.cos('omg)"), + "type mismatch", + """ + 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)}"), + "missing arguments for method foldLeft", + """ + twRuntimeErrors("@p{@Seq(1, 2, 3).foldLeft(0)}"), + ^ + """ + ) + + * - check( + twRuntimeErrors("@Nil.foldLeft{XY}"), + "missing arguments for method foldLeft", + """ + twRuntimeErrors("@Nil.foldLeft{XY}"), + ^ + """ + ) + // * - check( -// twRuntimeErrors("omg @_root_.scala.gg.lol lol"), -// """object gg is not a member of package scala""", -// """ -// twRuntimeErrors("omg @_root_.scala.gg.lol lol"), -// ^ +// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), +// "type mismatch", +// """ +// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), +// ^ // """ // ) // * - check( -// twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), -// """object ggnore is not a member of package <root>""", +// twRuntimeErrors("@Nil.map{ omg}"), +// "too many arguments for method map", // """ -// twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), -// ^ +// twRuntimeErrors("@Nil.map{ omg}"), +// ^ // """ // ) // } -// 'calls{ -// * - check( -// twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), -// """object QQ is not a member of package scala""", -// """ -// twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), -// ^ -// """ -// ) -// * - check( -// twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), -// "value tdo is not a member of Int", -// """ -// twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), -// ^ -// """ -// ) -// * - check( -// twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), -// "value z is not a member of Int", -// """ -// twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), -// ^ -// """ -// ) + 'callContents{ + * - check( + twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), + "value wtf is not a member of (Int, Int)", + """ + twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), + ^ + """ + ) + + * - check( + twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), + "value wtf is not a member of String", + """ + twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), + ^ + """ + ) + } +// } +// 'ifElse{ +// 'oneLine { // * - check( -// twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), -// "value z is not a member of Int", +// twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), +// "object > is not a member of package math", // """ -// twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), -// ^ +// twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), +// ^ // """ // ) // * - check( -// twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), -// "value cow is not a member of Int", +// twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), +// "Unspecified value parameter y", // """ -// twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), +// twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), // ^ // """ // ) // * - check( -// twRuntimeErrors("@scala.smath.abs.cow.sum.z"), -// "object smath is not a member of package scala", +// twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), +// "too many arguments for method sin: (x: Double)Double", // """ -// twRuntimeErrors("@scala.smath.abs.cow.sum.z"), -// ^ +// twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), +// ^ // """ // ) +// } +// 'multiLine{ // * - check( -// twRuntimeErrors("@scala.math.cos('omg)"), -// "type mismatch", +// twRuntimeErrors(""" +// Ho Ho Ho +// +// @if(math != 10) +// I am a cow +// @else +// You are a cow +// GG +// """), +// "object != is not a member of package math", // """ -// twRuntimeErrors("@scala.math.cos('omg)"), -// ^ +// @if(math != 10) +// ^ // """ // ) // * - check( -// twRuntimeErrors("@scala.math.cos[omg]('omg)"), -// "not found: type omg", +// twRuntimeErrors(""" +// Ho Ho Ho +// +// @if(4 != 10) +// I am a cow @math.lols +// @else +// You are a cow +// GG +// """), +// "object lols is not a member of package math", // """ -// twRuntimeErrors("@scala.math.cos[omg]('omg)"), -// ^ +// I am a cow @math.lols +// ^ // """ // ) // * - check( // twRuntimeErrors(""" -// I am cow hear me moo -// @scala.math.abs(-10).tdo(10).sum.z -// I weigh twice as much as you +// Ho Ho Ho +// +// @if(12 != 10) +// I am a cow +// @else +// @math.E.toString.gog(1) +// GG // """), -// "value tdo is not a member of Int", +// "value gog is not a member of String", // """ -// @scala.math.abs(-10).tdo(10).sum.z -// ^ +// @math.E.toString.gog(1) +// ^ // """ // ) // } -// 'curlies{ -// * - check( -// twRuntimeErrors("@p{@Seq(1, 2, 3).foldLeft(0)}"), -// "missing arguments for method foldLeft", -// """ -// twRuntimeErrors("@p{@Seq(1, 2, 3).foldLeft(0)}"), -// ^ -// """ -// ) -// -// * - check( -// twRuntimeErrors("@Nil.foldLeft{XY}"), -// "missing arguments for method foldLeft", +// } +// 'forLoop{ +// 'oneLine{ +// 'header - check( +// twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), +// """value omglolol is not a member of Int""", // """ -// twRuntimeErrors("@Nil.foldLeft{XY}"), -// ^ +// twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), +// ^ // """ // ) // -//// * - check( -//// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), -//// "type mismatch", -//// """ -//// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), -//// ^ -//// """ -//// ) -//// * - check( -//// twRuntimeErrors("@Nil.map{ omg}"), -//// "too many arguments for method map", -//// """ -//// twRuntimeErrors("@Nil.map{ omg}"), -//// ^ -//// """ -//// ) -//// } -// 'callContents{ -// * - check( -// twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), -// "value wtf is not a member of (Int, Int)", +// 'body - check( +// twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), +// """too many arguments for method +""", // """ -// twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), -// ^ +// twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), +// ^ // """ // ) -// -// * - check( -// twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), -// "value wtf is not a member of String", +// } +// 'multiLine{ +// 'body - check( +// twRuntimeErrors(""" +// omg +// @for(x <- 0 until 10) +// I am cow hear me moo +// I weigh twice as much as @x.kkk +// """), +// """value kkk is not a member of Int""", // """ -// twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), -// ^ +// I weigh twice as much as @x.kkk +// ^ // """ // ) // } -//// } -//// 'ifElse{ -//// 'oneLine { -//// * - check( -//// twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), -//// "object > is not a member of package math", -//// """ -//// twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), -//// ^ -//// """ -//// ) -//// * - check( -//// twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), -//// "Unspecified value parameter y", -//// """ -//// twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), -//// ^ -//// """ -//// ) -//// * - check( -//// twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), -//// "too many arguments for method sin: (x: Double)Double", -//// """ -//// twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), -//// ^ -//// """ -//// ) -//// } -//// 'multiLine{ -//// * - check( -//// twRuntimeErrors(""" -//// Ho Ho Ho -//// -//// @if(math != 10) -//// I am a cow -//// @else -//// You are a cow -//// GG -//// """), -//// "object != is not a member of package math", -//// """ -//// @if(math != 10) -//// ^ -//// """ -//// ) -//// * - check( -//// twRuntimeErrors(""" -//// Ho Ho Ho -//// -//// @if(4 != 10) -//// I am a cow @math.lols -//// @else -//// You are a cow -//// GG -//// """), -//// "object lols is not a member of package math", -//// """ -//// I am a cow @math.lols -//// ^ -//// """ -//// ) -//// * - check( -//// twRuntimeErrors(""" -//// Ho Ho Ho -//// -//// @if(12 != 10) -//// I am a cow -//// @else -//// @math.E.toString.gog(1) -//// GG -//// """), -//// "value gog is not a member of String", -//// """ -//// @math.E.toString.gog(1) -//// ^ -//// """ -//// ) -//// } -//// } -//// 'forLoop{ -//// 'oneLine{ -//// 'header - check( -//// twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), -//// """value omglolol is not a member of Int""", -//// """ -//// twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), -//// ^ -//// """ -//// ) -//// -//// 'body - check( -//// twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), -//// """too many arguments for method +""", -//// """ -//// twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), -//// ^ -//// """ -//// ) -//// } -//// 'multiLine{ -//// 'body - check( -//// twRuntimeErrors(""" -//// omg -//// @for(x <- 0 until 10) -//// I am cow hear me moo -//// I weigh twice as much as @x.kkk -//// """), -//// """value kkk is not a member of Int""", -//// """ -//// I weigh twice as much as @x.kkk -//// ^ -//// """ -//// ) -//// } -//// } -//// 'multiLine{ -//// 'missingVar - check( -//// twRuntimeErrors(""" -//// omg @notInScope lol -//// """), -//// """not found: value notInScope""", -//// """ -//// omg @notInScope lol -//// ^ -//// """ -//// ) -//// 'wrongType - check( -//// twRuntimeErrors(""" -//// omg @{() => ()} lol -//// """), -//// """type mismatch""", -//// """ -//// omg @{() => ()} lol -//// ^ -//// """ -//// ) -//// -//// 'bigExpression - check( -//// twRuntimeErrors(""" -//// @{ -//// val x = 1 + 2 -//// val y = new Object() -//// val z = y * x -//// x -//// } -//// """), -//// "value * is not a member of Object", -//// """ -//// val z = y * x -//// ^ -//// """ -//// ) // } -// } -//} +// 'multiLine{ +// 'missingVar - check( +// twRuntimeErrors(""" +// omg @notInScope lol +// """), +// """not found: value notInScope""", +// """ +// omg @notInScope lol +// ^ +// """ +// ) +// 'wrongType - check( +// twRuntimeErrors(""" +// omg @{() => ()} lol +// """), +// """type mismatch""", +// """ +// omg @{() => ()} lol +// ^ +// """ +// ) +// +// 'bigExpression - check( +// twRuntimeErrors(""" +// @{ +// val x = 1 + 2 +// val y = new Object() +// val z = y * x +// x +// } +// """), +// "value * is not a member of Object", +// """ +// val z = y * x +// ^ +// """ +// ) + } + } +} diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala index a09f8e4..68f05cc 100644 --- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala @@ -16,384 +16,384 @@ object ParserTests extends utest.TestSuite{ assert(parsed == expected) } def tests = TestSuite{ -// 'Trim{ -// def wrap(s: String) = "|" + s + "|" -// * - { -// val trimmed = wrap(stages.Trim.old(""" -// i am cow -// hear me moo -// i weigh twice as much as you -// """)) -// val expected = wrap(""" -// |i am cow -// | hear me moo -// | i weigh twice as much as you -// |""".stripMargin) -// assert(trimmed == expected) -// -// } -// * - { -// val trimmed = wrap(stages.Trim.old( -// """ -// @{"lol" * 3} -// @{ -// val omg = "omg" -// omg * 2 -// } -// """ -// )) -// val expected = wrap( -// """ -// |@{"lol" * 3} -// |@{ -// | val omg = "omg" -// | omg * 2 -// |} -// |""".stripMargin -// ) -// assert(trimmed == expected) -// } -// 'dropTrailingWhitespace - { -// -// val trimmed = wrap(stages.Trim.old( -// Seq( -// " i am a cow ", -// " hear me moo ", -// " i weigh twice as much as you" -// ).mkString("\n") -// )) -// val expected = wrap( -// Seq( -// "i am a cow", -// " hear me moo", -// " i weigh twice as much as you" -// ).mkString("\n") -// ) -// assert(trimmed == expected) -// } -// } -// 'Text { -// * - check("i am a cow", _.Text.run(), Block.Text("i am a cow")) -// * - check("i am a @cow", _.Text.run(), Block.Text("i am a ")) -// * - check("i am a @@cow", _.Text.run(), Block.Text("i am a @cow")) -// * - check("i am a @@@cow", _.Text.run(), Block.Text("i am a @")) -// * - check("i am a @@@@cow", _.Text.run(), Block.Text("i am a @@cow")) -// -// } -// 'Code{ -// 'identifier - check("@gggg ", _.Code.run(), "gggg") -// 'parens - check("@(1 + 1)lolsss\n", _.Code.run(), "(1 + 1)") -// 'curlies - check("@{{1} + (1)} ", _.Code.run(), "{{1} + (1)}") -// 'blocks - check("@{val x = 1; 1} ", _.Code.run(), "{val x = 1; 1}") -// 'weirdBackticks - check("@{`{}}{()@`}\n", _.Code.run(), "{`{}}{()@`}") -// } -// 'MiscCode{ -// 'imports{ -// * - check("@import math.abs", _.Header.run(), "import math.abs") -// * - check("@import math.{abs, sin}", _.Header.run(), "import math.{abs, sin}") -// } -// 'headerblocks{ -// check( -// """@import math.abs -// |@import math.sin -// | -// |hello world -// |""".stripMargin, -// _.HeaderBlock.run(), -// Ast.Header( -// "import math.abs\nimport math.sin", -// Ast.Block( -// Seq(Text("\n", 33), Text("\n", 34), Text("hello world", 35), Text("\n", 46)), -// 33 -// ) -// ) -// ) -// } -// 'caseclass{ -// check( -// """@case class Foo(i: Int, s: String) -// """.stripMargin, -// _.Header.run(), -// "case class Foo(i: Int, s: String)" -// ) -// } -// -// } -// 'Block{ -// * - check("{i am a cow}", _.BraceBlock.run(), Block(Seq(Block.Text("i am a cow", 1)), 1)) -// * - check("{i @am a @cow}", _.BraceBlock.run(), -// Block(Seq( -// Block.Text("i ", 1), -// Chain("am",Seq(), 3), -// Block.Text(" a ", 6), -// Chain("cow",Seq(), 9) -// ), 1) -// ) -// } -// 'Chain{ -// * - check("@omg.bbq[omg].fff[fff](123) ", _.ScalaChain.run(), -// Chain("omg",Seq( -// 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(Text("bbq", 5)), 5), -// Chain.Prop("cow", 9), -// Chain.Args("(moo)", 13), -// Block(Seq(Text("a ", 19), Chain("b", Nil, 21)), 19) -// )) -// ) -// } -// 'ControlFlow{ -// 'for { -// 'for - check( -// "@for(x <- 0 until 3){lol}", -// _.ForLoop.run(), -// For("for(x <- 0 until 3)", Block(Seq(Text("lol", 21)), 21)) -// ) -// 'forBlock - check( -// """ -// |@for(x <- 0 until 3) -// | lol""".stripMargin, -// _.Body.run(), -// Block(Seq( -// Text("\n"), -// For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 21), Text("lol", 24)), 21)) -// )) -// ) -// 'forBlockBraces - check( -// """ -// |@for(x <- 0 until 3){ -// | lol -// |}""".stripMargin, -// _.Body.run(), -// Block(Seq( -// Text("\n"), -// For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 22), Text("lol", 25), Text("\n", 28)), 22)) -// )) -// ) -// } -// 'ifElse { -// 'if - check( -// "@if(true){lol}", -// _.IfElse.run(), -// IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), None) -// ) -// 'ifElse - check( -// "@if(true){lol}else{ omg }", -// _.IfElse.run(), -// IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), Some(Block(Seq(Text(" omg ", 19)), 19))) -// ) -// 'ifBlock - check( -// """ -// |@if(true) -// | omg""".stripMargin, -// _.IfElse.run(), -// IfElse("if(true)", Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), None) -// ) -// 'ifBlockElseBlock - check( -// """ -// |@if(true) -// | omg -// |@else -// | wtf""".stripMargin, -// _.IfElse.run(), -// IfElse( -// "if(true)", -// Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), -// Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) -// ) -// ) -// 'ifBlockElseBraceBlock - check( -// """@if(true){ -// | omg -// |}else{ -// | wtf -// |}""".stripMargin, -// _.IfElse.run(), -// IfElse( -// "if(true)", -// Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), -// Some(Block(Seq(Text("\n ", 23), Text("wtf", 26), Text("\n", 29)), 23)) -// ) -// ) -// 'ifBlockElseBraceBlockNested - { -// val res = Parser(Trim.old( -// """ -// @p -// @if(true){ -// Hello -// }else{ -// lols -// } -// """)) -// val expected = -// Block(Vector( -// Text("\n"), -// Chain("p",Vector(Block(Vector( -// Text("\n ", 3), -// IfElse("if(true)", -// Block(Vector( -// Text("\n ", 16), Text("Hello", 21), Text("\n ", 26) -// ), 16), -// Some(Block(Vector( -// Text("\n ", 35), Text("lols", 40), Text("\n ", 44) -// ), 35)) -// )), 3)), 1), -// Text("\n", 48) -// )) -// assert(res == expected) -// } -// 'ifElseBlock - check( -// """@if(true){ -// | omg -// |}else -// | wtf""".stripMargin, -// _.IfElse.run(), -// IfElse( -// "if(true)", -// Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), -// Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) -// ) -// ) -// } -// -// } -// 'Body{ -// 'indents - check( -// """ -// |@omg -// | @wtf -// | @bbq -// | @lol""".stripMargin, -// _.Body.run(), -// Block(Seq( -// Text("\n"), -// Chain("omg",Seq(Block(Seq( -// Text("\n ", 5), -// Chain("wtf",Seq(Block(Seq( -// Text("\n ", 7), -// Chain("bbq",Seq(Block(Seq( -// Text("\n ", 9), -// Chain("lol",Seq(), 16) -// ), 9)), 12) -// ), 7)), 8) -// ), 5)), 1) -// )) -// ) -// 'dedents - check( -// """ -// |@omg -// | @wtf -// |@bbq""".stripMargin, -// _.Body.run(), -// Block(Seq( -// Text("\n"), -// Chain("omg",Seq(Block( -// Seq( -// Text("\n ", 5), -// Chain("wtf",Seq(), 8) -// ), -// 5 -// )), 1), -// Text("\n", 12), -// Chain("bbq", Seq(), 13) -// )) -// ) -// 'braces - check( -// """ -// |@omg{ -// | @wtf -// |} -// |@bbq""".stripMargin, -// _.Body.run(), -// Block(Seq( -// Text("\n"), -// Chain("omg",Seq(Block( -// Seq( -// Text("\n ", 6), -// Chain("wtf",Seq(), 9), -// Text("\n", 13) -// ), -// 6 -// )), 1), -// Text("\n", 15), -// Chain("bbq", Seq(), 16) -// )) -// ) -// 'dedentText - check( + 'Trim{ + def wrap(s: String) = "|" + s + "|" + * - { + val trimmed = wrap(stages.Trim.old(""" + i am cow + hear me moo + i weigh twice as much as you + """)) + val expected = wrap(""" + |i am cow + | hear me moo + | i weigh twice as much as you + |""".stripMargin) + assert(trimmed == expected) + + } + * - { + val trimmed = wrap(stages.Trim.old( + """ + @{"lol" * 3} + @{ + val omg = "omg" + omg * 2 + } + """ + )) + val expected = wrap( + """ + |@{"lol" * 3} + |@{ + | val omg = "omg" + | omg * 2 + |} + |""".stripMargin + ) + assert(trimmed == expected) + } + 'dropTrailingWhitespace - { + + val trimmed = wrap(stages.Trim.old( + Seq( + " i am a cow ", + " hear me moo ", + " i weigh twice as much as you" + ).mkString("\n") + )) + val expected = wrap( + Seq( + "i am a cow", + " hear me moo", + " i weigh twice as much as you" + ).mkString("\n") + ) + assert(trimmed == expected) + } + } + 'Text { + * - check("i am a cow", _.Text.run(), Block.Text("i am a cow")) + * - check("i am a @cow", _.Text.run(), Block.Text("i am a ")) + * - check("i am a @@cow", _.Text.run(), Block.Text("i am a @cow")) + * - check("i am a @@@cow", _.Text.run(), Block.Text("i am a @")) + * - check("i am a @@@@cow", _.Text.run(), Block.Text("i am a @@cow")) + + } + 'Code{ + 'identifier - check("@gggg ", _.Code.run(), "gggg") + 'parens - check("@(1 + 1)lolsss\n", _.Code.run(), "(1 + 1)") + 'curlies - check("@{{1} + (1)} ", _.Code.run(), "{{1} + (1)}") + 'blocks - check("@{val x = 1; 1} ", _.Code.run(), "{val x = 1; 1}") + 'weirdBackticks - check("@{`{}}{()@`}\n", _.Code.run(), "{`{}}{()@`}") + } + 'MiscCode{ + 'imports{ + * - check("@import math.abs", _.Header.run(), "import math.abs") + * - check("@import math.{abs, sin}", _.Header.run(), "import math.{abs, sin}") + } + 'headerblocks{ + check( + """@import math.abs + |@import math.sin + | + |hello world + |""".stripMargin, + _.HeaderBlock.run(), + Ast.Header( + "import math.abs\nimport math.sin", + Ast.Block( + Seq(Text("\n", 33), Text("\n", 34), Text("hello world", 35), Text("\n", 46)), + 33 + ) + ) + ) + } + 'caseclass{ + check( + """@case class Foo(i: Int, s: String) + """.stripMargin, + _.Header.run(), + "case class Foo(i: Int, s: String)" + ) + } + + } + 'Block{ + * - check("{i am a cow}", _.BraceBlock.run(), Block(Seq(Block.Text("i am a cow", 1)), 1)) + * - check("{i @am a @cow}", _.BraceBlock.run(), + Block(Seq( + Block.Text("i ", 1), + Chain("am",Seq(), 3), + Block.Text(" a ", 6), + Chain("cow",Seq(), 9) + ), 1) + ) + } + 'Chain{ + * - check("@omg.bbq[omg].fff[fff](123) ", _.ScalaChain.run(), + Chain("omg",Seq( + 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(Text("bbq", 5)), 5), + Chain.Prop("cow", 9), + Chain.Args("(moo)", 13), + Block(Seq(Text("a ", 19), Chain("b", Nil, 21)), 19) + )) + ) + } + 'ControlFlow{ + 'for { + 'for - check( + "@for(x <- 0 until 3){lol}", + _.ForLoop.run(), + For("for(x <- 0 until 3)", Block(Seq(Text("lol", 21)), 21)) + ) + 'forBlock - check( + """ + |@for(x <- 0 until 3) + | lol""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 21), Text("lol", 24)), 21)) + )) + ) + 'forBlockBraces - check( + """ + |@for(x <- 0 until 3){ + | lol + |}""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 22), Text("lol", 25), Text("\n", 28)), 22)) + )) + ) + } + 'ifElse { + 'if - check( + "@if(true){lol}", + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), None) + ) + 'ifElse - check( + "@if(true){lol}else{ omg }", + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), Some(Block(Seq(Text(" omg ", 19)), 19))) + ) + 'ifBlock - check( + """ + |@if(true) + | omg""".stripMargin, + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), None) + ) + 'ifBlockElseBlock - check( + """ + |@if(true) + | omg + |@else + | wtf""".stripMargin, + _.IfElse.run(), + IfElse( + "if(true)", + Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), + Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) + ) + ) + 'ifBlockElseBraceBlock - check( + """@if(true){ + | omg + |}else{ + | wtf + |}""".stripMargin, + _.IfElse.run(), + IfElse( + "if(true)", + Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), + Some(Block(Seq(Text("\n ", 23), Text("wtf", 26), Text("\n", 29)), 23)) + ) + ) + 'ifBlockElseBraceBlockNested - { + val res = Parser(Trim.old( + """ + @p + @if(true){ + Hello + }else{ + lols + } + """)) + val expected = + Block(Vector( + Text("\n"), + Chain("p",Vector(Block(Vector( + Text("\n ", 3), + IfElse("if(true)", + Block(Vector( + Text("\n ", 16), Text("Hello", 21), Text("\n ", 26) + ), 16), + Some(Block(Vector( + Text("\n ", 35), Text("lols", 40), Text("\n ", 44) + ), 35)) + )), 3)), 1), + Text("\n", 48) + )) + assert(res == expected) + } + 'ifElseBlock - check( + """@if(true){ + | omg + |}else + | wtf""".stripMargin, + _.IfElse.run(), + IfElse( + "if(true)", + Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), + Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) + ) + ) + } + + } + 'Body{ + 'indents - check( + """ + |@omg + | @wtf + | @bbq + | @lol""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + Chain("omg",Seq(Block(Seq( + Text("\n ", 5), + Chain("wtf",Seq(Block(Seq( + Text("\n ", 7), + Chain("bbq",Seq(Block(Seq( + Text("\n ", 9), + Chain("lol",Seq(), 16) + ), 9)), 12) + ), 7)), 8) + ), 5)), 1) + )) + ) + 'dedents - check( + """ + |@omg + | @wtf + |@bbq""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + Chain("omg",Seq(Block( + Seq( + Text("\n ", 5), + Chain("wtf",Seq(), 8) + ), + 5 + )), 1), + Text("\n", 12), + Chain("bbq", Seq(), 13) + )) + ) + 'braces - check( + """ + |@omg{ + | @wtf + |} + |@bbq""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + Chain("omg",Seq(Block( + Seq( + Text("\n ", 6), + Chain("wtf",Seq(), 9), + Text("\n", 13) + ), + 6 + )), 1), + Text("\n", 15), + Chain("bbq", Seq(), 16) + )) + ) + 'dedentText - check( + """ + |@omg("lol", 1, 2) + | @wtf + |bbq""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + Chain("omg",Seq( + Args("""("lol", 1, 2)""", 5), + Block(Seq( + Text("\n ", 18), + Chain("wtf",Seq(), 21) + ), 18) + ), 1), + Text("\n", 25), + Text("bbq", 26) + )) + ) +// * - check( // """ -// |@omg("lol", 1, 2) -// | @wtf +// |@omg("lol", +// |1, +// | 2 +// | ) +// | wtf // |bbq""".stripMargin, // _.Body.run(), // Block(Seq( -// Text("\n"), // Chain("omg",Seq( -// Args("""("lol", 1, 2)""", 5), +// Args("(\"lol\",\n1,\n 2\n )"), // Block(Seq( -// Text("\n ", 18), -// Chain("wtf",Seq(), 21) -// ), 18) -// ), 1), -// Text("\n", 25), -// Text("bbq", 26) -// )) -// ) -//// * - check( -//// """ -//// |@omg("lol", -//// |1, -//// | 2 -//// | ) -//// | wtf -//// |bbq""".stripMargin, -//// _.Body.run(), -//// Block(Seq( -//// Chain("omg",Seq( -//// Args("(\"lol\",\n1,\n 2\n )"), -//// Block(Seq( -//// Text("\n "), Text("wtf") -//// )) -//// )), -//// Text("\n"), -//// Text("bbq") -//// )) -//// ) -// 'codeBlocks - check( -// """ -// |@{"lol" * 3} -// |@{ -// | val omg = "omg" -// | omg * 2 -// |}""".stripMargin, -// _.Body.run(), -// Block(Seq( +// Text("\n "), Text("wtf") +// )) +// )), // Text("\n"), -// Chain("{\"lol\" * 3}", Seq(), 1), -// Text("\n", 13), -// Chain("""{ -// | val omg = "omg" -// | omg * 2 -// |}""".stripMargin, -// Seq(), -// 14 -// ) +// Text("bbq") // )) // ) -// } - 'Test{ - check( - "@scala.math.abs((1, 2).swap._1)", + 'codeBlocks - check( + """ + |@{"lol" * 3} + |@{ + | val omg = "omg" + | omg * 2 + |}""".stripMargin, _.Body.run(), - "" + Block(Seq( + Text("\n"), + Chain("{\"lol\" * 3}", Seq(), 1), + Text("\n", 13), + Chain("""{ + | val omg = "omg" + | omg * 2 + |}""".stripMargin, + Seq(), + 14 + ) + )) ) } + 'Test{ +// check( +// "@scala.math.abs((1, 2).swap._1.toString())", +// _.Body.run(), +// "" +// ) + } } } |