diff --git a/smt-common/src/main/scala/org/bitlap/common/TransformableSyntax.scala b/smt-common/src/main/scala/org/bitlap/common/TransformableSyntax.scala new file mode 100644 index 00000000..8d4b3d8a --- /dev/null +++ b/smt-common/src/main/scala/org/bitlap/common/TransformableSyntax.scala @@ -0,0 +1,16 @@ +package org.bitlap.common +import org.bitlap.common.internal.TransformerMacro + +/** @author + * 梦境迷离 + * @version 1.0,2022/7/29 + */ +trait TransformableSyntax[From <: Product, To <: Product] { self => + + val transformer: Transformer[From, To] + + def Syntax: Transformable[From, To] = macro TransformerMacro.applyImpl[From, To] + + implicit val _self: TransformableSyntax[From, To] = self + +} diff --git a/smt-common/src/main/scala/org/bitlap/common/package.scala b/smt-common/src/main/scala/org/bitlap/common/package.scala index 86685e3a..8b20fc15 100644 --- a/smt-common/src/main/scala/org/bitlap/common/package.scala +++ b/smt-common/src/main/scala/org/bitlap/common/package.scala @@ -72,4 +72,9 @@ package object common { implicit final class TransformerOps[F](private val from: F) extends AnyVal { final def transform[T](implicit transformer: Transformer[F, T]): T = transformer.transform(from) } + + implicit final class TransformableSyntaxOps[F <: Product](private val from: F) extends AnyVal { + final def transformCaseClass[T <: Product](implicit transformableSyntax: TransformableSyntax[F, T]): T = + transformableSyntax.transformer.transform(from) + } } diff --git a/smt-common/src/test/scala/org/bitlap/common/TransformableTest.scala b/smt-common/src/test/scala/org/bitlap/common/TransformableTest.scala index 4d30603f..cdcfebd9 100644 --- a/smt-common/src/test/scala/org/bitlap/common/TransformableTest.scala +++ b/smt-common/src/test/scala/org/bitlap/common/TransformableTest.scala @@ -508,4 +508,53 @@ class TransformableTest extends AnyFlatSpec with Matchers { | a.transform[A2](b1) |""".stripMargin shouldNot compile } + + "TransformableTest extends TransformableOps" should "compile ok" in { + case class A1(a: Option[String], b: Boolean) + + object A1 extends TransformableSyntax[A1, A2] { + override val transformer: Transformer[A1, A2] = + Syntax + .setName(_.a, _.b) + .setName(_.b, _.c) + .setType[Boolean, String](_.b, _.toString) + .setDefaultValue(_.b, None) + .instance + } + + case class A2( + b: Option[String], + c: String, + e: Option[String] = Some("option") + ) + + val a = A1(Some("hello a"), false) + a.transformCaseClass[A2].toString shouldEqual "A2(Some(hello a),false,Some(option))" + } + + "TransformableTest extends TransformableOps" should "ok" in { + case class A1(d: Option[String]) + + object A1 extends TransformableSyntax[A1, A2] { + override val transformer: Transformer[A1, A2] = + Syntax + .setDefaultValue(_.f, Option("1")) + .disableCollectionDefaultsToEmpty // use default value, not None + .disableOptionDefaultsToNone // use default value, not Empty + .instance + + } + case class A2( + d: Option[String], + e: Option[String] = Some("option"), + f: Option[String] = None, + h: List[String] = List("list"), + i: List[String] = List.empty + ) + + val a = A1(Some("hello a")) + + a.transformCaseClass[A2].toString shouldEqual "A2(Some(hello a),Some(option),Some(1),List(list),List())" + + } }