From c0b06c5e3f3caa60736794143f278c2af5cbe9fb Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 1 Nov 2014 10:15:13 -0700 Subject: scalatex tests pass --- scalatexApi/src/main/scala/scalatex/package.scala | 42 +++++-- .../src/main/scala/scalatex/stages/Compiler.scala | 1 + .../main/scala/scalatex/stages/IndentHandler.scala | 16 ++- .../src/test/scala/scalatex/BasicTests.scala | 47 ++++---- .../src/test/scala/scalatex/ErrorTests.scala | 132 ++++++++++----------- 5 files changed, 134 insertions(+), 104 deletions(-) (limited to 'scalatexApi/src') diff --git a/scalatexApi/src/main/scala/scalatex/package.scala b/scalatexApi/src/main/scala/scalatex/package.scala index 5732411..d86976e 100644 --- a/scalatexApi/src/main/scala/scalatex/package.scala +++ b/scalatexApi/src/main/scala/scalatex/package.scala @@ -15,11 +15,13 @@ package object scalatex { def twf(filename: String): Frag = macro Internals.applyMacroFile object Internals { + def twRuntimeErrors(expr: String): Frag = macro applyMacroRuntimeErrors def twDebug(expr: String): Frag = macro applyMacroDebug - def applyMacro(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, false) + def applyMacro(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, false, false) + def applyMacroDebug(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, false, true) - def applyMacroDebug(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, true) + def applyMacroRuntimeErrors(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, true, false) def applyMacroFile(c: Context)(filename: c.Expr[String]): c.Expr[Frag] = { import c.universe._ @@ -34,34 +36,46 @@ package object scalatex { txt.toCharArray ) - compileThing(c)(txt, sourceFile, 0, false) + compileThing(c)(txt, sourceFile, 0, false, false) } case class DebugFailure(msg: String, pos: String) extends Exception(msg) - private[this] def applyMacroFull(c: Context)(expr: c.Expr[String], runtimeErrors: Boolean): c.Expr[Frag] = { + private[this] def applyMacroFull(c: Context) + (expr: c.Expr[String], + runtimeErrors: Boolean, + debug: Boolean) + : c.Expr[Frag] = { import c.universe._ val s = expr.tree - .asInstanceOf[Literal] - .value - .value - .asInstanceOf[String] + .asInstanceOf[Literal] + .value + .value + .asInstanceOf[String] val stringStart = expr.tree .pos .lineContent .drop(expr.tree.pos.column) .take(2) + val indented = s |> stages.IndentHandler + if (debug) println(indented) compileThing(c)( - s |> stages.IndentHandler, + indented, expr.tree.pos.source, expr.tree.pos.point + (if (stringStart == "\"\"") 1 else -1), - runtimeErrors + runtimeErrors, + debug ) } } - def compileThing(c: Context)(s: String, source: SourceFile, point: Int, runtimeErrors: Boolean) = { + def compileThing(c: Context) + (s: String, + source: SourceFile, + point: Int, + runtimeErrors: Boolean, + debug: Boolean) = { import c.universe._ def compile(s: String): c.Tree = { val realPos = new OffsetPosition(source, point).asInstanceOf[c.universe.Position] @@ -71,13 +85,15 @@ package object scalatex { import c.Position try { - c.Expr(c.typeCheck(compile(s))) + val compiled = compile(s) + if (debug) println(compiled) + c.Expr[Frag](c.typeCheck(compiled)) } catch { case e@TypecheckException(pos: Position, msg) => if (!runtimeErrors) c.abort(pos, msg) else { val posMsg = pos.lineContent + "\n" + (" " * pos.column) + "^" - c.Expr( q"""throw twist.Internals.DebugFailure($msg, $posMsg)""") + c.Expr( q"""throw scalatex.Internals.DebugFailure($msg, $posMsg)""") } } diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala index 85bb0f0..fcbe08b 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala @@ -75,6 +75,7 @@ object Compiler{ q"if($cond){ Seq[$fragType](..$b1): $fragType } else { Seq[$fragType](..$b2): $fragType }" case xx @ WN.ScalaExp(WN.Simple(first, _) +: rest, offset) => + val firstTree = c.parse(first) firstTree.foreach{x => diff --git a/scalatexApi/src/main/scala/scalatex/stages/IndentHandler.scala b/scalatexApi/src/main/scala/scalatex/stages/IndentHandler.scala index 180d134..697ccc3 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/IndentHandler.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/IndentHandler.scala @@ -49,8 +49,15 @@ object IndentHandler extends (String => String){ // println(spaces, current) val declRemainder = successRemainder(Parser.parse(current.trim, _.templateDeclaration())) - - val exprRemainder = successRemainder(Parser.parse(current.trim, _.expression())).filter(_ == current.trim) +// println("::::::" + current.trim) +// println(successRemainder(Parser.parse(current.trim, _.expression()))) + val exprRemainder = successRemainder(Parser.parse(current.trim, _.expression())).filter { + // Either it takes up the entire line or the line ends with a =>, in which case + // we assume the guy wanted to pass a lambda + x => +// println(x) + x == current.trim || current.trim.endsWith("=>") + } /** @@ -81,14 +88,13 @@ object IndentHandler extends (String => String){ val newFirst = if (!before.startsWith("@else")) before else before.dropRight("@else".length)+ "} else" - + println(before, after, delta) if (delta > 0 && noBraceLine(after)) newFirst + "{" + after else if (delta <= 0 && noBraceLine(after) && after.trim != "") newFirst + "{" + after + "}" * (1 - elseCorrection) else current - - } + val closing = "}" * (-delta - elseCorrection) val newStack = diff --git a/scalatexApi/src/test/scala/scalatex/BasicTests.scala b/scalatexApi/src/test/scala/scalatex/BasicTests.scala index 0488ef6..f432e51 100644 --- a/scalatexApi/src/test/scala/scalatex/BasicTests.scala +++ b/scalatexApi/src/test/scala/scalatex/BasicTests.scala @@ -74,7 +74,6 @@ object BasicTests extends TestSuite{ 'attributes{ check( tw(""" - @div(id:="my-id") omg @div(id:="my-id"){ omg } @div(id:="my-id") omg @@ -82,7 +81,6 @@ object BasicTests extends TestSuite{ """ omg omg - omg """ ) } @@ -134,11 +132,12 @@ object BasicTests extends TestSuite{ check( tw(""" - @h1 Hello World - @h2 hello - @world + @h1 + Hello World + @h2 + hello @world @h3 - Cow + Cow """), """

HelloWorld

@@ -157,9 +156,9 @@ object BasicTests extends TestSuite{ @div Cow """), """ -

HelloWorld

-

helloworld

-

Cow

+

HelloWorld +

helloworld +

Cow """ ) } @@ -213,7 +212,7 @@ object BasicTests extends TestSuite{
Hello
-

WORLD!!!lol

+

WORLD!!!lol

Header2

@@ -227,13 +226,15 @@ object BasicTests extends TestSuite{ tw(""" @ul @things.map { x => - @li @x + @li + @x } """), - tw(""" + Internals.twDebug(""" @ul - @things.map x => - @li @x + @things.map x => + @li + @x """), """ @@ -319,7 +320,8 @@ object BasicTests extends TestSuite{ tw(""" @if(false) Hello - @else lols + @else + lols @p """), "lols

" @@ -330,7 +332,8 @@ object BasicTests extends TestSuite{ @div @if(true) Hello - @else lols + @else + lols """), "
Hello
" ) @@ -338,15 +341,19 @@ object BasicTests extends TestSuite{ * - check( tw(""" @div - @if(true) Hello - @else lols + @if(true) + Hello + @else + lols """), "
Hello
" ) * - check( tw(""" - @if(false) Hello - @else lols + @if(false) + Hello + @else + lols """), "lols" ) diff --git a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala index a122dd2..f9e9308 100644 --- a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala @@ -3,7 +3,7 @@ package scalatex import utest._ import scalatex.stages._ import scalatags.Text.all._ -import scalatex.Internals.{DebugFailure, twDebug} +import scalatex.Internals.{DebugFailure, twRuntimeErrors} /** * Created by haoyi on 7/14/14. @@ -31,109 +31,109 @@ object ErrorTests extends TestSuite{ 'simple - check( - twDebug("omg @notInScope lol"), + twRuntimeErrors("omg @notInScope lol"), """not found: value notInScope""", """ - twDebug("omg @notInScope lol"), - ^ + twRuntimeErrors("omg @notInScope lol"), + ^ """ ) 'chained{ 'properties { * - check( - twDebug("omg @math.lol lol"), + twRuntimeErrors("omg @math.lol lol"), """object lol is not a member of package math""", """ - twDebug("omg @math.lol lol"), - ^ + twRuntimeErrors("omg @math.lol lol"), + ^ """ ) * - check( - twDebug("omg @math.E.lol lol"), + twRuntimeErrors("omg @math.E.lol lol"), """value lol is not a member of Double""", """ - twDebug("omg @math.E.lol lol"), - ^ + twRuntimeErrors("omg @math.E.lol lol"), + ^ """ ) * - check( - twDebug("omg @_root_.scala.math.lol lol"), + twRuntimeErrors("omg @_root_.scala.math.lol lol"), """object lol is not a member of package math""", """ - twDebug("omg @_root_.scala.math.lol lol"), - ^ + twRuntimeErrors("omg @_root_.scala.math.lol lol"), + ^ """ ) * - check( - twDebug("omg @_root_.scala.gg.lol lol"), + twRuntimeErrors("omg @_root_.scala.gg.lol lol"), """object gg is not a member of package scala""", """ - twDebug("omg @_root_.scala.gg.lol lol"), - ^ + twRuntimeErrors("omg @_root_.scala.gg.lol lol"), + ^ """ ) * - check( - twDebug("omg @_root_.ggnore.math.lol lol"), + twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), """object ggnore is not a member of package """, """ - twDebug("omg @_root_.ggnore.math.lol lol"), - ^ + twRuntimeErrors("omg @_root_.ggnore.math.lol lol"), + ^ """ ) } 'calls{ * - check( - twDebug("@scala.QQ.abs(-10).tdo(10).sum.z"), + twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), """object QQ is not a member of package scala""", """ - twDebug("@scala.QQ.abs(-10).tdo(10).sum.z"), - ^ + twRuntimeErrors("@scala.QQ.abs(-10).tdo(10).sum.z"), + ^ """ ) * - check( - twDebug("@scala.math.abs(-10).tdo(10).sum.z"), + twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), "value tdo is not a member of Int", """ - twDebug("@scala.math.abs(-10).tdo(10).sum.z"), - ^ + twRuntimeErrors("@scala.math.abs(-10).tdo(10).sum.z"), + ^ """ ) * - check( - twDebug("@scala.math.abs(-10).to(10).sum.z"), + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), "value z is not a member of Int", """ - twDebug("@scala.math.abs(-10).to(10).sum.z"), - ^ + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z"), + ^ """ ) * - check( - twDebug("@scala.math.abs(-10).to(10).sum.z()"), + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), "value z is not a member of Int", """ - twDebug("@scala.math.abs(-10).to(10).sum.z()"), - ^ + twRuntimeErrors("@scala.math.abs(-10).to(10).sum.z()"), + ^ """ ) * - check( - twDebug("@scala.math.abs(-10).cow.sum.z"), + twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), "value cow is not a member of Int", """ - twDebug("@scala.math.abs(-10).cow.sum.z"), - ^ + twRuntimeErrors("@scala.math.abs(-10).cow.sum.z"), + ^ """ ) * - check( - twDebug("@scala.smath.abs.cow.sum.z"), + twRuntimeErrors("@scala.smath.abs.cow.sum.z"), "object smath is not a member of package scala", """ - twDebug("@scala.smath.abs.cow.sum.z"), - ^ + twRuntimeErrors("@scala.smath.abs.cow.sum.z"), + ^ """ ) * - check( - twDebug(""" + twRuntimeErrors(""" I am cow hear me moo @scala.math.abs(-10).tdo(10).sum.z I weigh twice as much as you @@ -147,20 +147,20 @@ object ErrorTests extends TestSuite{ } 'callContents{ * - check( - twDebug("@scala.math.abs((1, 2).wtf)"), + twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), "value wtf is not a member of (Int, Int)", """ - twDebug("@scala.math.abs((1, 2).wtf)"), - ^ + twRuntimeErrors("@scala.math.abs((1, 2).wtf)"), + ^ """ ) * - check( - twDebug("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), + twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), "value wtf is not a member of String", """ - twDebug("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), - ^ + twRuntimeErrors("@scala.math.abs((1, 2).swap._1.toString().map(_.toString.wtf))"), + ^ """ ) } @@ -168,33 +168,33 @@ object ErrorTests extends TestSuite{ 'ifElse{ 'oneLine { * - check( - twDebug("@if(math > 10){ 1 }else{ 2 }"), + twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), "object > is not a member of package math", """ - twDebug("@if(math > 10){ 1 }else{ 2 }"), - ^ + twRuntimeErrors("@if(math > 10){ 1 }else{ 2 }"), + ^ """ ) * - check( - twDebug("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), + twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), "Unspecified value parameter y", """ - twDebug("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), - ^ + twRuntimeErrors("@if(true){ (@math.pow(10)) * 10 }else{ 2 }"), + ^ """ ) * - check( - twDebug("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), + twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), "too many arguments for method sin: (x: Double)Double", """ - twDebug("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), - ^ + twRuntimeErrors("@if(true){ * 10 }else{ @math.sin(3, 4, 5) }"), + ^ """ ) } 'multiLine{ * - check( - twDebug(""" + twRuntimeErrors(""" Ho Ho Ho @if(math != 10) @@ -210,7 +210,7 @@ object ErrorTests extends TestSuite{ """ ) * - check( - twDebug(""" + twRuntimeErrors(""" Ho Ho Ho @if(4 != 10) @@ -226,7 +226,7 @@ object ErrorTests extends TestSuite{ """ ) * - check( - twDebug(""" + twRuntimeErrors(""" Ho Ho Ho @if(12 != 10) @@ -246,26 +246,26 @@ object ErrorTests extends TestSuite{ 'forLoop{ 'oneLine{ 'header - check( - twDebug("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), + twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), """value omglolol is not a member of Int""", """ - twDebug("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), - ^ + twRuntimeErrors("omg @for(x <- (0 + 1 + 2) omglolol (10 + 11 + 2)){ hello }"), + ^ """ ) 'body - check( - twDebug("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), + twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), """too many arguments for method +""", """ - twDebug("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), - ^ + twRuntimeErrors("omg @for(x <- 0 until 10){ @((x, 2) + (1, 2)) }"), + ^ """ ) } 'multiLine{ 'body - check( - twDebug(""" + twRuntimeErrors(""" omg @for(x <- 0 until 10) I am cow hear me moo @@ -281,7 +281,7 @@ object ErrorTests extends TestSuite{ } 'multiLine{ 'missingVar - check( - twDebug(""" + twRuntimeErrors(""" omg @notInScope lol """), """not found: value notInScope""", @@ -291,7 +291,7 @@ object ErrorTests extends TestSuite{ """ ) 'wrongType - check( - twDebug(""" + twRuntimeErrors(""" omg @{() => ()} lol """), """type mismatch""", @@ -302,7 +302,7 @@ object ErrorTests extends TestSuite{ ) 'bigExpression - check( - twDebug(""" + twRuntimeErrors(""" @{ val x = 1 + 2 val y = new Object() -- cgit v1.2.3