Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate LightTypeTag#longName, add longNameWithPrefix and longNameInternalSymbol instead #343

Merged
merged 1 commit into from
Nov 21, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import izumi.reflect.macrortti.LightTypeTagRef._
trait LTTRenderables extends Serializable with WithRenderableSyntax {

def r_SymName(sym: SymName, hasPrefix: Boolean): String
def prefixSplitter: String = "::"

implicit lazy val r_LightTypeTag: Renderable[LightTypeTagRef] = new Renderable[LightTypeTagRef] {
override def render(value: LightTypeTagRef): String = value match {
Expand Down Expand Up @@ -119,7 +120,7 @@ trait LTTRenderables extends Serializable with WithRenderableSyntax {

value.prefix match {
case Some(p) =>
s"${p.render()}::$rr"
s"${p.render()}$prefixSplitter$rr"
case None =>
rr
}
Expand Down Expand Up @@ -174,7 +175,7 @@ object LTTRenderables {

// omit package names
object Short extends LTTRenderables {
def r_SymName(sym: SymName, @unused hasPrefix: Boolean): String = {
override def r_SymName(sym: SymName, @unused hasPrefix: Boolean): String = {
sym match {
case SymLiteral(c) => c
case _ => sym.name.split('.').last
Expand All @@ -184,8 +185,12 @@ object LTTRenderables {

// print package names
object Long extends LTTRenderables {
def r_SymName(sym: SymName, hasPrefix: Boolean): String = {
if (!hasPrefix) sym.name else Short.r_SymName(sym, hasPrefix)
override def r_SymName(sym: SymName, hasPrefix: Boolean): String = {
if (hasPrefix) {
Short.r_SymName(sym, hasPrefix)
} else {
sym.name
}
}

private[macrortti] def renderDb(db: Map[_ <: AbstractReference, Set[_ <: AbstractReference]]): String = {
Expand All @@ -196,4 +201,11 @@ object LTTRenderables {
}
}

object LongPrefixDot extends LTTRenderables {
override def r_SymName(sym: SymName, hasPrefix: Boolean): String = {
Long.r_SymName(sym, hasPrefix)
}
override def prefixSplitter: String = "."
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ abstract class LightTypeTag private[reflect] (
ref.toString
}

/** Fully-qualified rendering of a type, including packages and prefix types.
/**
* Fully-qualified rendering of a type, including packages and prefix types.
* Use [[toString]] for a rendering that omits package names
*/
def repr: String = {
Expand All @@ -171,7 +172,21 @@ abstract class LightTypeTag private[reflect] (
ref.shortName
}

/** Class or type-constructor name of this type, WITH package name, but without prefix names */
/** Class or type-constructor name of this type, with package and prefix names */
def longNameWithPrefix: String = {
ref.longNameWithPrefix
}

/** Internal symbol name of type-constructor of this type, with package and containing definition names */
def longNameInternalSymbol: String = {
ref.longNameInternalSymbol
}

@deprecated(
"Produces Scala version dependent output, with incorrect prefixes for types with value prefixes. Use `longNameWithPrefix` instead, or `longNameInternalSymbol` for old behavior",
"2.2.2"
)
/** @deprecated Produces Scala version dependent output, with incorrect prefixes for types with value prefixes. Use `longNameWithPrefix` instead, or `longNameInternalSymbol` for old behavior */
def longName: String = {
ref.longName
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ sealed trait LightTypeTagRef extends Serializable {
def appliedNamedReference(reference: AppliedNamedReference) = {
reference match {
case LightTypeTagRef.NameReference(_, _, _) => reference
case LightTypeTagRef.FullReference(ref, parameters @ _, prefix) => NameReference(SymTypeName(ref), Boundaries.Empty, prefix)
case r @ LightTypeTagRef.FullReference(_, parameters @ _, prefix) => NameReference(r.symName, Boundaries.Empty, prefix)
}
}

def appliedReference(reference: AppliedReference): AppliedReference = {
reference match {
case reference: AppliedNamedReference => appliedNamedReference(reference)
case reference: AppliedNamedReference =>
appliedNamedReference(reference)
case LightTypeTagRef.IntersectionReference(refs) =>
LightTypeTagRef.maybeIntersection(refs.map(appliedReference))
case LightTypeTagRef.UnionReference(refs) =>
Expand Down Expand Up @@ -106,11 +107,23 @@ sealed trait LightTypeTagRef extends Serializable {
}

final def shortName: String = {
getName(LTTRenderables.Short.r_SymName(_, hasPrefix = false), this)
getName(r => LTTRenderables.Short.r_SymName(r.symName, hasPrefix = false))
}

final def longNameWithPrefix: String = {
getName(r => LTTRenderables.LongPrefixDot.r_NameRefRenderer.render(NameReference(r.symName, Boundaries.Empty, r.prefix)))
}

final def longNameInternalSymbol: String = {
getName(r => LTTRenderables.Long.r_SymName(r.symName, hasPrefix = false))
}

@deprecated(
"Produces Scala version dependent output, with incorrect prefixes for types with value prefixes. Use `longNameWithPrefix` instead, or `longNameInternalSymbol` for old behavior",
"2.2.2"
)
final def longName: String = {
getName(LTTRenderables.Long.r_SymName(_, hasPrefix = false), this)
longNameInternalSymbol
}

final def getPrefix: Option[LightTypeTagRef] = {
Expand Down Expand Up @@ -164,6 +177,7 @@ sealed trait LightTypeTagRef extends Serializable {
}
}

/** decompose intersection type */
final def decompose: Set[AppliedReference] = {
this match {
case IntersectionReference(refs) =>
Expand Down Expand Up @@ -217,18 +231,23 @@ sealed trait LightTypeTagRef extends Serializable {
}
}

@tailrec
@inline
private[this] final def getName(render: SymName => String, self: LightTypeTagRef): String = {
self match {
case Lambda(_, output) => getName(render, output)
case NameReference(ref, _, _) => render(ref)
case FullReference(ref, _, _) => render(SymTypeName(ref))
case IntersectionReference(refs) => refs.map(_.shortName).mkString(" & ")
case UnionReference(refs) => refs.map(_.shortName).mkString(" | ")
case Refinement(reference, _) => getName(render, reference)
private[this] final def getName(render: AppliedNamedReference => String): String = {
@tailrec
@inline
def go(r: LightTypeTagRef): String = r match {
case Lambda(_, output) => go(output)
case ref: NameReference => render(ref)
case ref: FullReference => render(ref)
case IntersectionReference(refs) => refs.map(goDeep).mkString(" & ")
case UnionReference(refs) => refs.map(goDeep).mkString(" | ")
case Refinement(reference, _) => go(reference)
case WildcardReference(_) => "?"
}

def goDeep(r: LightTypeTagRef): String = go(r)

go(this)
}

}
Expand Down Expand Up @@ -338,6 +357,8 @@ object LightTypeTagRef {

sealed trait AppliedNamedReference extends AppliedReference {
def asName: NameReference
def symName: SymName
def prefix: Option[AppliedReference]
}

final case class NameReference(
Expand All @@ -348,6 +369,7 @@ object LightTypeTagRef {
override lazy val hashCode: Int = scala.runtime.ScalaRunTime._hashCode(this)

override def asName: NameReference = this
override def symName: SymName = ref
}
object NameReference {
def apply(tpeName: String): NameReference = NameReference(SymTypeName(tpeName))
Expand All @@ -360,7 +382,8 @@ object LightTypeTagRef {
) extends AppliedNamedReference {
override lazy val hashCode: Int = scala.runtime.ScalaRunTime._hashCode(this)

override def asName: NameReference = NameReference(SymTypeName(ref), prefix = prefix)
override def asName: NameReference = NameReference(symName, prefix = prefix)
override def symName: SymName = SymTypeName(ref)
}

final case class TypeParam(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,17 @@ abstract class SharedLightTypeTagTest extends TagAssertions {
assertDebugSame(list_, immutableList_)
}

"no redundant $ in object names" in {
val ltt = LTT[TestModel.BasicCases.BasicCase2.TestImpl0Good]
assert(!ltt.debug().contains("BasicCase2$"))
assert(!ltt.debug().contains("BasicCases$"))
assert(!ltt.repr.contains("BasicCase2$"))
assert(!ltt.repr.contains("BasicCases$"))
assert(!ltt.toString.contains("BasicCase2$"))
assert(!ltt.toString.contains("BasicCases$"))
assert(ltt.longNameWithPrefix == "izumi.reflect.test.TestModel.BasicCases.BasicCase2.TestImpl0Good")
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ trait ZY extends Assertions {
type A = List[Option[Int]]
val x: String = "5"
object y
trait Y

val tagT = intercept[TestFailedException](assertCompiles("izumi.reflect.Tag[T]"))
val tagU = intercept[TestFailedException](assertCompiles("izumi.reflect.Tag[U]"))
Expand Down Expand Up @@ -637,6 +638,8 @@ abstract class SharedTagTest extends AnyWordSpec with XY[String] with TagAsserti

assert(Tag[ZY#T].closestClass eq classOf[Any])
assert(!Tag[ZY#T].hasPreciseClass)

assert(Tag[ZY#Y].hasPreciseClass)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,10 @@ object TestModel {
}
}

object BasicCases {
object BasicCase2 {
class TestImpl0Good
}
}

}