From 71287329e7751d69fd700d9ebcaff0fe0f664bed Mon Sep 17 00:00:00 2001 From: Aggelos Biboudis Date: Wed, 8 Jan 2020 12:00:45 +0100 Subject: [PATCH] Fix #7853: Add regression test --- tests/pos-macros/i7853/JsonEncoder_1.scala | 50 +++++++++++++++++++ .../i7853/SummonJsonEncoderTest_2.scala | 24 +++++++++ tests/pos-macros/i7853/Test_3.scala | 11 ++++ 3 files changed, 85 insertions(+) create mode 100644 tests/pos-macros/i7853/JsonEncoder_1.scala create mode 100644 tests/pos-macros/i7853/SummonJsonEncoderTest_2.scala create mode 100644 tests/pos-macros/i7853/Test_3.scala diff --git a/tests/pos-macros/i7853/JsonEncoder_1.scala b/tests/pos-macros/i7853/JsonEncoder_1.scala new file mode 100644 index 000000000000..414a6ff72678 --- /dev/null +++ b/tests/pos-macros/i7853/JsonEncoder_1.scala @@ -0,0 +1,50 @@ +import scala.deriving._ +import scala.compiletime.erasedValue + +trait JsonEncoder[T] { + def encode(elem: T): String +} + +object JsonEncoder { + import scala.compiletime.{erasedValue, summonFrom} + import compiletime._ + import scala.deriving._ + + inline def encodeElem[T](elem: T): String = summonFrom { + case encoder: JsonEncoder[T] => encoder.encode(elem) + } + + inline def encodeElems[Elems <: Tuple](idx: Int)(value: Any): List[String] = + inline erasedValue[Elems] match { + case _: (elem *: elems1) => + encodeElem[elem](productElement[elem](value, idx)) :: encodeElems[elems1](idx + 1)(value) + case _ => Nil + } + + inline def derived[T](implicit ev: Mirror.Of[T]): JsonEncoder[T] = new JsonEncoder[T] { + def encode(value: T): String = + inline ev match { + case m: Mirror.SumOf[T] => + "not supporting this case yet" + case m: Mirror.ProductOf[T] => + val elems = encodeElems[m.MirroredElemTypes](0)(value) + val labels = value.asInstanceOf[Product].productElementNames + val keyValues = labels.zip(elems).map((k, v) => s"$k: $v") + "{" + (keyValues).mkString(", ") + "}" + case other => + throw new RuntimeException("mirror was an invalid value: " + other) + } + } + + given listEncoder[T]: (encoder: JsonEncoder[T]) => JsonEncoder[List[T]] { + def encode(list: List[T]) = s"[${ list.map(v => encoder.encode(v)).mkString(", ") }]" + } + + given intEncoder: JsonEncoder[Int] { + def encode(value: Int) = value + "" + } + + given stringEncoder: JsonEncoder[String] { + def encode(value: String) = value + } +} \ No newline at end of file diff --git a/tests/pos-macros/i7853/SummonJsonEncoderTest_2.scala b/tests/pos-macros/i7853/SummonJsonEncoderTest_2.scala new file mode 100644 index 000000000000..1c4930b3d32f --- /dev/null +++ b/tests/pos-macros/i7853/SummonJsonEncoderTest_2.scala @@ -0,0 +1,24 @@ +import scala.deriving._ +import scala.quoted._ +import scala.quoted.matching._ +import scala.compiletime.{erasedValue, summonFrom} +import JsonEncoder.{given, _} + +object SummonJsonEncoderTest { + + inline def encodeAndMessAroundType[T](value: =>T): String = ${ encodeAndMessAroundTypeImpl('value) } + + def encodeAndMessAroundTypeImpl[T: Type](value: Expr[T])(given qctx: QuoteContext): Expr[String] = { + import qctx.tasty._ + + val mirrorExpr = summonExpr[Mirror.Of[T]] match { + case Some(mirror) => mirror + } + + '{ + given JsonEncoder[T] = JsonEncoder.derived($mirrorExpr) + val encoder = summon[JsonEncoder[T]] + encoder.encode($value) + } + } +} \ No newline at end of file diff --git a/tests/pos-macros/i7853/Test_3.scala b/tests/pos-macros/i7853/Test_3.scala new file mode 100644 index 000000000000..9d86b89187b4 --- /dev/null +++ b/tests/pos-macros/i7853/Test_3.scala @@ -0,0 +1,11 @@ +import SummonJsonEncoderTest._ + +case class PersonSimple(name:String, age:Int) + +object Test { + val stuff = PersonSimple("Joe", 123) + + def main(args: Array[String]):Unit = { + println(SummonJsonEncoderTest.encodeAndMessAroundType(stuff) ) + } +} \ No newline at end of file