From e780aa29d89ae99c1e80aab61c0e59205a74e1b2 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Wed, 4 Oct 2023 14:02:44 +0200 Subject: [PATCH] Replace scala-reflect with izumi-reflect --- build.sbt | 2 +- .../slickpg/utils/PlainSQLUtils.scala | 13 ++--- .../slickpg/utils/TypeConverters.scala | 29 +++++----- .../tminglei/slickpg/PgArraySupport.scala | 8 +-- .../tminglei/slickpg/PgCompositeSupport.scala | 56 +++++++++---------- 5 files changed, 52 insertions(+), 56 deletions(-) diff --git a/build.sbt b/build.sbt index 81e816df..3d6d321b 100644 --- a/build.sbt +++ b/build.sbt @@ -64,7 +64,7 @@ lazy val commonSettings = Seq( def mainDependencies(scalaVersion: String) = { Seq ( "org.scala-lang.modules" %% "scala-parser-combinators" % "2.3.0", - "org.scala-lang" % "scala-reflect" % scalaVersion, + "dev.zio" %% "izumi-reflect" % "2.3.8", "com.typesafe.slick" %% "slick" % "3.5.0-M4", "org.postgresql" % "postgresql" % "42.6.0", "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0", diff --git a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala index f11c25bf..fb47d403 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala @@ -2,26 +2,23 @@ package com.github.tminglei.slickpg.utils import slick.util.Logging +import izumi.reflect.{Tag => TTag} import scala.reflect.ClassTag import slick.jdbc.{GetResult, PositionedResult, SetParameter, PositionedParameters} -import scala.reflect.runtime.{universe => u} - object PlainSQLUtils extends Logging { import SimpleArrayUtils._ private[slickpg] var nextArrayConverters = Map.empty[String, PositionedResult => Option[Seq[_]]] /** used to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport */ - def addNextArrayConverter[T](conv: PositionedResult => Option[Seq[T]])(implicit ttag: u.TypeTag[T]) = { - logger.info(s"\u001B[36m >>> adding next array converter for ${u.typeOf[T]} \u001B[0m") - nextArrayConverters.synchronized { - val convKey = u.typeOf[T].toString + def addNextArrayConverter[T](conv: PositionedResult => Option[Seq[T]])(implicit ttag: TTag[T]) = { + logger.info(s"\u001B[36m >>> adding next array converter for ${ttag.tag.shortName} \u001B[0m") + val convKey = ttag.tag.shortName val existed = nextArrayConverters.get(convKey) if (existed.isDefined) logger.warn( - s"\u001B[31m >>> DUPLICATED next array converter for ${u.typeOf[T]}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" + s"\u001B[31m >>> DUPLICATED next array converter for ${ttag.tag.shortName}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" ) nextArrayConverters += (convKey -> conv) - } } /// diff --git a/core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala b/core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala index 0820899b..081b2489 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala @@ -1,14 +1,15 @@ package com.github.tminglei.slickpg package utils +import izumi.reflect.{Tag => TTag} +import izumi.reflect.macrortti.LightTypeTag import slick.util.Logging -import scala.reflect.runtime.{universe => u} import java.sql.{Date, Time, Timestamp} import java.time.{LocalDate, LocalDateTime, LocalTime} import java.util.UUID object TypeConverters extends Logging { - case class ConvConfig(from: u.Type, to: u.Type, var conv: (_ => _)) + case class ConvConfig(from: LightTypeTag, to: LightTypeTag, var conv: (_ => _)) private var convConfigList = List[ConvConfig]() @@ -35,19 +36,17 @@ object TypeConverters extends Logging { register((v: LocalTime) => v.toString) register((v: LocalDateTime) => v.toString) - def register[FROM,TO](convert: (FROM => TO))(implicit from: u.TypeTag[FROM], to: u.TypeTag[TO]) = { - logger.info(s"register converter for ${from.tpe.erasure} => ${to.tpe.erasure}") - convConfigList.synchronized { - find(from.tpe, to.tpe).map(_.conv = convert).orElse({ - convConfigList :+= ConvConfig(from.tpe, to.tpe, convert) - None - }) - } + def register[FROM,TO](convert: (FROM => TO))(implicit from: TTag[FROM], to: TTag[TO]) = { + logger.info(s"register converter for ${from.tag.shortName} => ${to.tag.shortName}") + find(from.tag, to.tag).map(_.conv = convert).orElse({ + convConfigList :+= ConvConfig(from.tag, to.tag, convert) + None + }) } - def converter[FROM,TO](implicit from: u.TypeTag[FROM], to: u.TypeTag[TO]): (FROM => TO) = { - find(from.tpe, to.tpe).map(_.conv.asInstanceOf[(FROM => TO)]) - .getOrElse(throw new IllegalArgumentException(s"Converter NOT FOUND for ${from.tpe} => ${to.tpe}")) + def converter[FROM,TO](implicit from: TTag[FROM], to: TTag[TO]): (FROM => TO) = { + find(from.tag, to.tag).map(_.conv.asInstanceOf[(FROM => TO)]) + .getOrElse(throw new IllegalArgumentException(s"Converter NOT FOUND for ${from.tag} => ${to.tag}")) } /// @@ -58,8 +57,8 @@ object TypeConverters extends Logging { case _ => s } - def find(from: u.Type, to: u.Type): Option[ConvConfig] = { - logger.debug(s"get converter for ${from.erasure} => ${to.erasure}") + def find(from: LightTypeTag, to: LightTypeTag): Option[ConvConfig] = { + logger.debug(s"get converter for ${from.shortName} => ${to.shortName}") convConfigList.find(e => (e.from =:= from && e.to =:= to)).orElse({ if (from <:< to) { Some(ConvConfig(from, to, (v: Any) => v)) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala index 35f6b47c..152d193d 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala @@ -1,9 +1,9 @@ package com.github.tminglei.slickpg +import izumi.reflect.{Tag => TTag} import java.util.UUID import java.sql.{Date, Time, Timestamp} import slick.jdbc.{GetResult, JdbcType, PositionedResult, PostgresProfile, SetParameter} -import scala.reflect.runtime.{universe => u} import scala.reflect.classTag trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes { driver: PostgresProfile => @@ -63,9 +63,9 @@ trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes } implicit class PgArrayPositionedResult(r: PositionedResult) { - def nextArray[T]()(implicit tpe: u.TypeTag[T]): Seq[T] = nextArrayOption[T]().getOrElse(Nil) - def nextArrayOption[T]()(implicit ttag: u.TypeTag[T]): Option[Seq[T]] = { - nextArrayConverters.get(u.typeOf[T].toString).map(_.apply(r)) + def nextArray[T]()(implicit tpe: TTag[T]): Seq[T] = nextArrayOption[T]().getOrElse(Nil) + def nextArrayOption[T]()(implicit ttag: TTag[T]): Option[Seq[T]] = { + nextArrayConverters.get(ttag.tag.shortName).map(_.apply(r)) .getOrElse(simpleNextArray[T](r)).asInstanceOf[Option[Seq[T]]] } } diff --git a/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala index f7dfa5e0..2e1b49a5 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala @@ -1,6 +1,7 @@ package com.github.tminglei.slickpg -import scala.reflect.runtime.{universe => u} +import izumi.reflect.macrortti.LightTypeTag +import izumi.reflect.{Tag => TTag} import scala.reflect.ClassTag import composite.Struct import slick.jdbc.{PositionedResult, PostgresProfile} @@ -11,39 +12,39 @@ trait PgCompositeSupport extends utils.PgCommonJdbcTypes with array.PgArrayJdbcT protected lazy val emptyMembersAsNull = true //--- - def createCompositeJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) new GenericJdbcType[T](sqlTypeName, util.mkCompositeFromString[T], util.mkStringFromComposite[T]) } - def createCompositeArrayJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeArrayJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) new AdvancedArrayJdbcType[T](sqlTypeName, util.mkCompositeSeqFromString[T], util.mkStringFromCompositeSeq[T]) } /// Plain SQL support - def nextComposite[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def nextComposite[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) r.nextStringOption().map(util.mkCompositeFromString[T]) } - def nextCompositeArray[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def nextCompositeArray[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) r.nextStringOption().map(util.mkCompositeSeqFromString[T]) } - def createCompositeSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) } - def createCompositeOptionSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeOptionSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkOptionSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) } - def createCompositeArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkArraySetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) } - def createCompositeOptionArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeOptionArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: TTag[T], tag: ClassTag[T]) = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkArrayOptionSetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) } @@ -53,56 +54,55 @@ class PgCompositeSupportUtils(cl: ClassLoader, emptyMembersAsNull: Boolean) { import utils.PgTokenHelper._ import utils.TypeConverters._ - def mkCompositeFromString[T <: Struct](implicit ev: u.TypeTag[T]): (String => T) = { - val converter = mkTokenConverter(u.typeOf[T]) + def mkCompositeFromString[T <: Struct](implicit ev: TTag[T]): (String => T) = { + val converter = mkTokenConverter(ev.tag) (input: String) => { val root = grouping(Tokenizer.tokenize(input)) converter.fromToken(root).asInstanceOf[T] } } - def mkStringFromComposite[T <: Struct](implicit ev: u.TypeTag[T]): (T => String) = { - val converter = mkTokenConverter(u.typeOf[T]) + def mkStringFromComposite[T <: Struct](implicit ev: TTag[T]): (T => String) = { + val converter = mkTokenConverter(ev.tag) (value: T) => { createString(converter.toToken(value)) } } - def mkCompositeSeqFromString[T <: Struct](implicit ev: u.TypeTag[Seq[T]]): (String => Seq[T]) = { - val converter = mkTokenConverter(u.typeOf[Seq[T]]) + def mkCompositeSeqFromString[T <: Struct](implicit ev: TTag[Seq[T]]): (String => Seq[T]) = { + val converter = mkTokenConverter(ev.tag) (input: String) => { val root = grouping(Tokenizer.tokenize(input)) converter.fromToken(root).asInstanceOf[Seq[T]] } } - def mkStringFromCompositeSeq[T <: Struct](implicit ev: u.TypeTag[Seq[T]]): (Seq[T] => String) = { - val converter = mkTokenConverter(u.typeOf[Seq[T]]) + def mkStringFromCompositeSeq[T <: Struct](implicit ev: TTag[Seq[T]]): (Seq[T] => String) = { + val converter = mkTokenConverter(ev.tag) (vList: Seq[T]) => { createString(converter.toToken(vList)) } } /// - def mkTokenConverter(theType: u.Type, level: Int = -1)(implicit ev: u.TypeTag[String]): TokenConverter = { + def mkTokenConverter(theType: LightTypeTag, level: Int = -1)(implicit ev: TTag[String]): TokenConverter = { theType match { - case tpe if tpe <:< u.typeOf[Struct] => { - val constructor = tpe.decl(u.termNames.CONSTRUCTOR).asMethod - val convList = constructor.paramLists.head.map(_.typeSignature).map(mkTokenConverter(_, level +1)) + case tpe if tpe <:< TTag[Struct].tag => { + val convList = tpe.typeArgs.map(x => mkTokenConverter(x, level +1)) CompositeConverter(tpe, convList) } - case tpe if tpe.typeConstructor =:= u.typeOf[Option[_]].typeConstructor => { - val pType = tpe.asInstanceOf[u.TypeRef].args(0) + case tpe if tpe =:= TTag[Option[_]].tag => { + val pType = tpe.typeArgs(0) OptionConverter(mkTokenConverter(pType, level)) } - case tpe if tpe.typeConstructor <:< u.typeOf[Seq[_]].typeConstructor => { - val eType = tpe.asInstanceOf[u.TypeRef].args(0) + case tpe if tpe <:< TTag[Seq[_]].tag => { + val eType = tpe.typeArgs(0) SeqConverter(mkTokenConverter(eType, level +1)) } case tpe => { - val fromString = find(u.typeOf[String], tpe).map(_.conv.asInstanceOf[(String => Any)]) + val fromString = find(TTag[String].tag, tpe).map(_.conv.asInstanceOf[(String => Any)]) .getOrElse(throw new IllegalArgumentException(s"Converter NOT FOUND for 'String' => '$tpe'")) - val ToString = find(tpe, u.typeOf[String]).map(_.conv.asInstanceOf[(Any => String)]) + val ToString = find(tpe, TTag[String].tag).map(_.conv.asInstanceOf[(Any => String)]) .getOrElse((v: Any) => v.toString) SimpleConverter(fromString, ToString, level) } @@ -122,7 +122,7 @@ class PgCompositeSupportUtils(cl: ClassLoader, emptyMembersAsNull: Boolean) { if (value == null) Null else Chunk(ToString(value)) } - case class CompositeConverter(theType: u.Type, convList: List[TokenConverter]) extends TokenConverter { + case class CompositeConverter(theType: LightTypeTag, convList: List[TokenConverter]) extends TokenConverter { private val constructor = theType.decl(u.termNames.CONSTRUCTOR).asMethod private val fieldList = constructor.paramLists.head.map(t => theType.decl(t.name).asTerm)