Port StringTypeTag

This commit is contained in:
Eugene Yokota 2021-12-13 02:07:13 -05:00
parent 8d5355d274
commit c724e83fd1
4 changed files with 47 additions and 84 deletions

View File

@ -1,27 +0,0 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util.appmacro
import scala.reflect.macros.blackbox
object StringTypeTag {
def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
import c.universe._
val tpe = weakTypeOf[A]
def typeToString(tpe: Type): String = tpe match {
case TypeRef(_, sym, args) if args.nonEmpty =>
val typeCon = tpe.typeSymbol.fullName
val typeArgs = args map typeToString
s"""$typeCon[${typeArgs.mkString(",")}]"""
case _ => tpe.toString
}
val key = Literal(Constant(typeToString(tpe)))
q"new sbt.internal.util.StringTypeTag[$tpe]($key)"
}
}

View File

@ -0,0 +1,29 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util.appmacro
final class StringTypeTag[A](val key: String):
override def toString(): String = key
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
case x: StringTypeTag[_] => (this.key == x.key)
case _ => false
})
override def hashCode: Int = key.##
end StringTypeTag
object StringTypeTag:
inline given apply[A]: StringTypeTag[A] = ${ applyImpl[A] }
def manually[A](key: String): StringTypeTag[A] = new StringTypeTag(key)
import scala.quoted.*
private def applyImpl[A: Type](using qctx: Quotes): Expr[StringTypeTag[A]] =
import qctx.reflect._
val tpe = TypeRepr.of[A]
'{ new StringTypeTag[A](${ Expr(tpe.dealias.show) }) }
end StringTypeTag

View File

@ -0,0 +1,18 @@
package sbt.internal
import sbt.internal.util.appmacro.*
import verify.*
object StringTypeTagTest extends BasicTestSuite:
test("String") {
assert(StringTypeTag[String].toString == "java.lang.String")
}
test("Int") {
assert(StringTypeTag[Int].toString == "scala.Int")
}
test("List[Int]") {
assert(StringTypeTag[List[Int]].toString == "scala.collection.immutable.List[scala.Int]")
}
end StringTypeTagTest

View File

@ -1,57 +0,0 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
import scala.language.experimental.macros
import scala.reflect.runtime.universe._
/** This is used to carry type information in JSON. */
final case class StringTypeTag[A](key: String) {
override def toString: String = key
}
object StringTypeTag {
/** Generates a StringTypeTag for any type at compile time. */
implicit def fast[A]: StringTypeTag[A] = macro appmacro.StringTypeTag.impl[A]
@deprecated("Prefer macro generated StringTypeTag", "1.4.0")
def apply[A: TypeTag]: StringTypeTag[A] =
synchronized {
def doApply: StringTypeTag[A] = {
val tag = implicitly[TypeTag[A]]
val tpe = tag.tpe
val k = typeToString(tpe)
// println(tpe.getClass.toString + " " + k)
StringTypeTag[A](k)
}
def retry(n: Int): StringTypeTag[A] =
try {
doApply
} catch {
case e: NullPointerException =>
if (n < 1) throw new RuntimeException("NPE in StringTypeTag", e)
else {
Thread.sleep(1)
retry(n - 1)
}
}
retry(3)
}
@deprecated("Prefer macro generated StringTypeTag", "1.4.0")
def typeToString(tpe: Type): String =
tpe match {
case TypeRef(_, sym, args) =>
if (args.nonEmpty) {
val typeCon = tpe.typeSymbol.fullName
val typeArgs = args map typeToString
s"""$typeCon[${typeArgs.mkString(",")}]"""
} else tpe.toString
case _ => tpe.toString
}
}