diff --git a/izumi-reflect/izumi-reflect/src/main/scala/izumi/reflect/macrortti/LightTypeTag.scala b/izumi-reflect/izumi-reflect/src/main/scala/izumi/reflect/macrortti/LightTypeTag.scala index d9845100..72e3e24e 100644 --- a/izumi-reflect/izumi-reflect/src/main/scala/izumi/reflect/macrortti/LightTypeTag.scala +++ b/izumi-reflect/izumi-reflect/src/main/scala/izumi/reflect/macrortti/LightTypeTag.scala @@ -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", diff --git a/izumi-reflect/izumi-reflect/src/test/scala-2/izumi/reflect/test/LightTypeTagTest.scala b/izumi-reflect/izumi-reflect/src/test/scala-2/izumi/reflect/test/LightTypeTagTest.scala index f943ef27..f39be81b 100644 --- a/izumi-reflect/izumi-reflect/src/test/scala-2/izumi/reflect/test/LightTypeTagTest.scala +++ b/izumi-reflect/izumi-reflect/src/test/scala-2/izumi/reflect/test/LightTypeTagTest.scala @@ -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[=?]]")) } - + } } diff --git a/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/LightTypeTagTest.scala b/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/LightTypeTagTest.scala index 166aefd8..e1134ddb 100644 --- a/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/LightTypeTagTest.scala +++ b/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/LightTypeTagTest.scala @@ -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