Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
43 changes: 40 additions & 3 deletions test-tests/shared/src/test/scala/zio/test/ShowExpressionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ object ShowExpressionSpec extends ZIOBaseSpec {
val fooVal = "foo"
case class SomeData(foo: String, more: Seq[Nested], nested: Nested)
case class Nested(bar: Int)
class SomeClass(val str: String = "")

override def spec: ZSpec[Any, Any] = suite("ShowExprSpec")(
override def spec: ZSpec[Annotations, Any] = suite("ShowExprSpec")(
test("Some(1)", showExpression(Some(1)), "Some(1)"),
test("Some(Right(1))", showExpression(Some(Right(1))), "Some(Right(1))"),
test("class member val", showExpression(fooVal), "fooVal"),
Expand All @@ -17,8 +18,44 @@ object ShowExpressionSpec extends ZIOBaseSpec {
showExpression(SomeData("foo barvaz", Seq(Nested(1), Nested(2)), Nested(3))),
"SomeData(\"foo barvaz\", Seq(Nested(1), Nested(2)), Nested(3))"
),
test("multiline string literal", showExpression("foo\nbar\n\nbaz"), "\"foo\\nbar\\n\\nbaz\"")
)
test("multiline string literal", showExpression("foo\nbar\n\nbaz"), "\"foo\\nbar\\n\\nbaz\""),
test("throw new + upcast", showExpression((throw new RuntimeException): String), "throw new RuntimeException()"),
test(
"match clause",
showExpression(fooVal match { case "foo" => fooVal; case _ => new SomeClass("bar") }),
"""fooVal match {
| case "foo" => fooVal
| case _ => new SomeClass("bar")
|}""".stripMargin
),
test(
"if else",
showExpression(if (fooVal == "foo") Nested(1) else new SomeClass("bar")),
"""if (fooVal.==("foo"))
| Nested(1)
|else
| new SomeClass("bar")""".stripMargin
),
test("method with default arg", showExpression(methodWithDefaultArgs()), "methodWithDefaultArgs()"),
test("constructor with default arg", showExpression(new SomeClass()), "new SomeClass()"),
test(
"single arg anon function with underscores",
showExpression(Option("").filterNot(_.isEmpty)),
"Option(\"\").filterNot((_.isEmpty()))"
),
test(
"two arg anon function with underscores",
showExpression(List(1, 2, 3).reduce(_ + _)),
"List(1, 2, 3).reduce((_.+(_)))"
),
test(
"two arg anon function with named args",
showExpression(List(1, 2, 3).reduce((a, b) => a + b)),
"List(1, 2, 3).reduce(((a, b) => a.+(b)))"
)
) @@ TestAspect.exceptDotty

def methodWithDefaultArgs(arg: String = "") = arg

def test(desc: String, actual: String, expected: String): ZSpec[Any, Nothing] =
zio.test.test(desc) {
Expand Down
74 changes: 64 additions & 10 deletions test/shared/src/main/scala-2.x/zio/test/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,48 +80,102 @@ private[test] object CleanCodePrinter {
private val magicQuote = "-- $%^*"
private val startQuote = s"`$magicQuote"
private val endQuote = s"$magicQuote`"
private val magicArg = "x$$$$123"

def show(c: blackbox.Context)(expr: c.Tree): String = {
import c.universe._
postProcess(showCode(clean(c)(expr)))
postProcess(showCode(clean(c)(expr, CleanContext())))
}

private def postProcess(code: String): String =
code
.replace(startQuote, "\"")
.replace(endQuote, "\"")
.replace(s"($magicArg) => ", "")

private def clean(c: blackbox.Context)(expr: c.Tree): c.Tree = {
private case class CleanContext(funcSyntheticArgs: Set[String] = Set.empty) {
def withFuncSyntheticArgs(args: Set[String]): CleanContext = copy(funcSyntheticArgs = args)
}

private def clean(c: blackbox.Context)(expr: c.Tree, ctx: CleanContext): c.Tree = {
import c.universe._
object PackageSelects {
def unapply(tree: c.Tree): Option[String] = packageSelects(c)(tree)
}
expr match {
// remove type parameters from methods: foo[Int](args) => foo(args)
case Apply(TypeApply(t, _), args) => Apply(clean(c)(t), args.map(clean(c)(_)))
case Apply(t, args) => Apply(clean(c)(t), args.map(clean(c)(_)))
case Apply(TypeApply(t, _), args) => Apply(clean(c)(t, ctx), cleanArgs(c)(args, ctx))
case Apply(t, args) => Apply(clean(c)(t, ctx), cleanArgs(c)(args, ctx))
// foo.apply => foo
case Select(PackageSelects(n), TermName("apply")) => Ident(TermName(cleanTupleTerm(n)))
case Select(This(_), tn) => Ident(tn)
case Select(left, TermName("apply")) => clean(c)(left)
case PackageSelects(n) => Ident(TermName(cleanTupleTerm(n)))
case Select(t, n) => Select(clean(c)(t), n)
case Select(This(_), tn) => Ident(tn)
case Select(left, TermName("apply")) => clean(c)(left, ctx)
case Select(t, n) => Select(clean(c)(t, ctx), n)
case Ident(TermName(n)) => Ident(TermName(nameOrUnderscoreArg(n, ctx)))

case l @ Literal(Constant(s: String)) =>
if (s.contains("\n")) Ident(TermName(s"$magicQuote${s.replace("\n", "\\n")}$magicQuote"))
else l
case Typed(tree, _) => clean(c)(tree, ctx)
case Throw(tree) => Throw(clean(c)(tree, ctx))
case New(tree) => New(clean(c)(tree, ctx))
case CaseDef(t1, t2, t3) => CaseDef(clean(c)(t1, ctx), clean(c)(t2, ctx), clean(c)(t3, ctx))
case Match(tree, cases) =>
Match(
clean(c)(tree, ctx),
cases.map { case CaseDef(t1, t2, t3) => CaseDef(clean(c)(t1, ctx), clean(c)(t2, ctx), clean(c)(t3, ctx)) }
)
case Block(trees, tree) => Block(trees.map(clean(c)(_, ctx)), clean(c)(tree, ctx))
case If(t1, t2, t3) => If(clean(c)(t1, ctx), clean(c)(t2, ctx), clean(c)(t3, ctx))
case Bind(n, t) => Bind(n, clean(c)(t, ctx))
case Function(vals, tree) =>
val (synthetic, nonSynthetic) = vals.partition(_.mods.hasFlag(Flag.SYNTHETIC))
val newArgs =
if (nonSynthetic.isEmpty) List(ValDef(Modifiers(Flag.PARAM), TermName(magicArg), EmptyTree, EmptyTree))
else cleanValDefs(c)(nonSynthetic)
Function(
newArgs,
clean(c)(
tree,
ctx.withFuncSyntheticArgs(synthetic.collect { case ValDef(_, TermName(name), _, _) =>
name
}.toSet)
)
)
case t => t
}
}

private def cleanTupleTerm(n: String) =
if (n.matches("Tuple\\d+")) "" else n

private def cleanValDefs(c: blackbox.Context)(vals: List[c.universe.ValDef]) = {
import c.universe._
vals.map { case ValDef(mods, name, _, _) =>
ValDef(mods, name, EmptyTree, EmptyTree)
}
}

private def nameOrUnderscoreArg(n: String, ctx: CleanContext) =
if (ctx.funcSyntheticArgs(n)) "_"
else n

private def cleanArgs(c: blackbox.Context)(args: List[c.Tree], ctx: CleanContext): List[c.Tree] = {
import c.universe._
args.map(clean(c)(_, ctx)).filter {
case Ident(TermName(name)) => !name.matches(".*\\$default\\$\\d+$")
case Select(_, TermName(name)) => !name.matches(".*\\$default\\$\\d+$")
case _ => true
}
}

private def packageSelects(c: blackbox.Context)(select: c.universe.Tree): Option[String] = {
import c.universe._
select match {
case Select(nested @ Select(_, _), TermName(name)) => packageSelects(c)(nested).map(_ => name)
case Select(id @ Ident(_), TermName(what)) if id.symbol.isPackage => Some(what)
case _ => None
case Select(id @ Ident(_), n: Name) if id.symbol.isPackage => Some(n.decodedName.toString)
case Select(nested @ Select(_, _), n: Name) => packageSelects(c)(nested).map(_ => n.decodedName.toString)
case _ => None
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ object CompileVariants {
def assertMProxy[R, E, A](effect: ZIO[R, E, A], sourceLocation: String)
(assertion: AssertionM[A]): ZIO[R, E, TestResult] =
zio.test.assertMImpl(effect, Some(sourceLocation))(assertion)
}
}