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

Support non-trivial lambdas in Scala-style rendering format #490

Draft
wants to merge 14 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,36 @@ abstract class LightTypeTag private[reflect] (
* Fully-qualified rendering of a type, including packages and prefix types.
* Traditional Scala notation for lambdas, e.g. scala.util.Either[+scala.Int,+_]
*/
def scalaStyledName: String = {
ref.scalaStyledName
def scalaStyledName: String = {
ref match {
case lambda: LightTypeTagRef.Lambda =>
val lambdaOutput = lambda.output match {
// Case for a trivial lambda, where args are in the declared order and match input parameters
case LightTypeTagRef.FullReference(_, args, _) if args.size == lambda.input.size =>
val isTrivial = lambda.input.indices.forall(i => args(i) == lambda.input(i))
if (isTrivial) {
// Trivial lambda: render as `Either[_, _]`
s"${lambda.output.shortName}[${lambda.input.map(_ => "_").mkString(", ")}]"
} else {
// Non-trivial reordering of lambda parameters: render with explicit lambda notation
s"[${lambda.input.mkString(", ")}] =>> ${lambda.output.shortName}"
}

// Case for nested or more complex lambda cases (non-trivial)
case _ =>
s"[${lambda.input.mkString(", ")}] =>> ${lambda.output.shortName}"
}
lambdaOutput

// General case for parameterized types without lambda
= case LightTypeTagRef.FullReference(_, args, _) if args.nonEmpty =>
// Render parameterized types with `_` placeholders if they have arguments
s"${ref.shortName}[${args.map(_ => "_").mkString(", ")}]"

= case _ =>
ref.shortName
}
}

@deprecated(
"Produces Scala version dependent output, with incorrect prefixes for types with value prefixes. Use `longNameWithPrefix` instead, or `longNameInternalSymbol` for old behavior",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ class LightTypeTagTest extends SharedLightTypeTagTest {
info(list_.debug())
assert(!list_.debug().contains("→ izumi.reflect.test.LightTypeTagProgressionTest.Test0[+izumi.reflect.test.LightTypeTagProgressionTest.L[=?]]"))
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,28 @@ class LightTypeTagTest extends SharedLightTypeTagTest {
}

}

"LightTypeTag#scalaStyledName" should {

"correctly render trivial lambda applications with _ placeholders" in {
type SimpleLambda[A, B] = Either[A, B]
val tag = LTT[SimpleLambda[_, _]]
assert(tag.scalaStyledName == "Either[_, _]")
}

"correctly render non-trivial lambda applications with parameter reordering" in {
type ReorderedLambda[A, B] = Either[B, A]
val tag = LTT[ReorderedLambda[_, _]]
assert(tag.scalaStyledName == "[A, B] =>> Either[B, A]")
}

"correctly render nested lambdas" in {
type NestedLambda[A] = [B] =>> Either[A, B]
val tag = LTT[NestedLambda[Int][String]]
assert(tag.scalaStyledName == "[A] =>> [B] =>> Either[A, B]")
}
}

}

type LightTypeTagTestT <: String
Loading