From cd0c3ba10421fa4db719296597891816ac64cb24 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Fri, 8 Mar 2024 14:58:01 +0100 Subject: [PATCH 1/6] Support 22+ template parameters in Scala 3 (cherry picked from commit a445c558dd8f7c4e3ed5795e9f2616b616709390) --- .../main/scala/play/twirl/api/Template.scala | 185 ------------------ .../play/twirl/compiler/TwirlCompiler.scala | 21 +- 2 files changed, 5 insertions(+), 201 deletions(-) delete mode 100644 api/shared/src/main/scala/play/twirl/api/Template.scala diff --git a/api/shared/src/main/scala/play/twirl/api/Template.scala b/api/shared/src/main/scala/play/twirl/api/Template.scala deleted file mode 100644 index 3992fd72..00000000 --- a/api/shared/src/main/scala/play/twirl/api/Template.scala +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. - */ - -package play.twirl.api - -trait Template0[Result] { - def render(): Result -} - -trait Template1[A, Result] { - def render(a: A): Result -} - -trait Template2[A, B, Result] { - def render(a: A, b: B): Result -} - -trait Template3[A, B, C, Result] { - def render(a: A, b: B, c: C): Result -} - -trait Template4[A, B, C, D, Result] { - def render(a: A, b: B, c: C, d: D): Result -} - -trait Template5[A, B, C, D, E, Result] { - def render(a: A, b: B, c: C, d: D, e: E): Result -} - -trait Template6[A, B, C, D, E, F, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F): Result -} - -trait Template7[A, B, C, D, E, F, G, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Result -} - -trait Template8[A, B, C, D, E, F, G, H, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): Result -} - -trait Template9[A, B, C, D, E, F, G, H, I, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): Result -} - -trait Template10[A, B, C, D, E, F, G, H, I, J, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): Result -} - -trait Template11[A, B, C, D, E, F, G, H, I, J, K, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K): Result -} - -trait Template12[A, B, C, D, E, F, G, H, I, J, K, L, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L): Result -} - -trait Template13[A, B, C, D, E, F, G, H, I, J, K, L, M, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M): Result -} - -trait Template14[A, B, C, D, E, F, G, H, I, J, K, L, M, N, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N): Result -} - -trait Template15[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O): Result -} - -trait Template16[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P): Result -} - -trait Template17[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q) - : Result -} - -trait Template18[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Result] { - def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q, r: R) - : Result -} - -trait Template19[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Result] { - def render( - a: A, - b: B, - c: C, - d: D, - e: E, - f: F, - g: G, - h: H, - i: I, - j: J, - k: K, - l: L, - m: M, - n: N, - o: O, - p: P, - q: Q, - r: R, - s: S - ): Result -} - -trait Template20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Result] { - def render( - a: A, - b: B, - c: C, - d: D, - e: E, - f: F, - g: G, - h: H, - i: I, - j: J, - k: K, - l: L, - m: M, - n: N, - o: O, - p: P, - q: Q, - r: R, - s: S, - t: T - ): Result -} - -trait Template21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, Result] { - def render( - a: A, - b: B, - c: C, - d: D, - e: E, - f: F, - g: G, - h: H, - i: I, - j: J, - k: K, - l: L, - m: M, - n: N, - o: O, - p: P, - q: Q, - r: R, - s: S, - t: T, - u: U - ): Result -} - -trait Template22[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, Result] { - def render( - a: A, - b: B, - c: C, - d: D, - e: E, - f: F, - g: G, - h: H, - i: I, - j: J, - k: K, - l: L, - m: M, - n: N, - o: O, - p: P, - q: Q, - r: R, - s: S, - t: T, - u: U, - v: V - ): Result -} diff --git a/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala b/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala index c9c3969e..6ee86b93 100644 --- a/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala +++ b/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala @@ -556,7 +556,7 @@ object TwirlCompiler { additionalImports: collection.Seq[String], constructorAnnotations: collection.Seq[String] ): collection.Seq[Any] = { - val (renderCall, f, templateType) = + val (renderCall, f) = TemplateAsFunctionCompiler.getFunctionMapping(root.params.str, resultType, scalaCompat) // Get the imports that we need to include, filtering out empty imports @@ -574,7 +574,7 @@ class """ :+ name :+ " " :+ constructorAnnotations :+ " " :+ Source(constructor. package """ :+ packageName :+ """ """ :+ imports :+ """ -""" :+ classDeclaration :+ """ extends _root_.play.twirl.api.BaseScalaTemplate[""" :+ resultType :+ """,_root_.play.twirl.api.Format[""" :+ resultType :+ """]](""" :+ formatterType :+ """) with """ :+ templateType :+ """ { +""" :+ classDeclaration :+ """ extends _root_.play.twirl.api.BaseScalaTemplate[""" :+ resultType :+ """,_root_.play.twirl.api.Format[""" :+ resultType :+ """]](""" :+ formatterType :+ """) { /*""" :+ root.comment.map(_.msg).getOrElse("") :+ """*/ def apply""" :+ Source(root.params.str, root.params.pos) :+ """:""" :+ resultType :+ """ = { @@ -675,14 +675,14 @@ package """ :+ packageName :+ """ def getFunctionMapping( signature: String, returnType: String, - ): (String, String, String) = + ): (String, String) = getFunctionMapping(signature, returnType, ScalaCompat(None)) private[compiler] def getFunctionMapping( signature: String, returnType: String, sc: ScalaCompat - ): (String, String, String) = { + ): (String, String) = { val params: List[List[Term.Param]] = try { @@ -732,17 +732,6 @@ package """ :+ packageName :+ """ .mkString ) - val templateType = "_root_.play.twirl.api.Template%s[%s%s]".format( - params.flatten.size, - params.flatten - .map { - case ByNameParam(_, paramType) => paramType - case p => filterType(p) - } - .mkString(","), - (if (params.flatten.isEmpty) "" else ",") + returnType - ) - val f = "def f:%s = %s => apply%s".format( functionType, params.map(group => "(" + group.map(_.name.toString).mkString(",") + ")").mkString(" => "), @@ -760,7 +749,7 @@ package """ :+ packageName :+ """ .mkString ) - (renderCall, f, templateType) + (renderCall, f) } } From b2b828d5534f2ee669abf81f2bcad0166fd4d106 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Fri, 8 Mar 2024 15:07:22 +0100 Subject: [PATCH 2/6] MiMa filters (cherry picked from commit 19086489f6ec20ad24a50a0635c6d79cd08e1d96) # Conflicts: # build.sbt --- build.sbt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/build.sbt b/build.sbt index 453ca770..6d9fd50c 100644 --- a/build.sbt +++ b/build.sbt @@ -1,11 +1,16 @@ // Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. import Dependencies._ +<<<<<<< HEAD import com.typesafe.tools.mima.core.DirectMissingMethodProblem import com.typesafe.tools.mima.core.IncompatibleMethTypeProblem import com.typesafe.tools.mima.core.MissingClassProblem import com.typesafe.tools.mima.core.Problem +======= +import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem +import com.typesafe.tools.mima.core.MissingClassProblem +>>>>>>> 1908648 (MiMa filters) import com.typesafe.tools.mima.core.ProblemFilters import sbtcrossproject.CrossPlugin.autoImport.crossProject import org.scalajs.jsenv.nodejs.NodeJSEnv @@ -24,6 +29,32 @@ val previousVersion: Option[String] = Some("1.6.0") val mimaSettings = Seq( mimaPreviousArtifacts := previousVersion.map(organization.value %% moduleName.value % _).toSet, mimaBinaryIssueFilters ++= Seq( + ProblemFilters.exclude[IncompatibleResultTypeProblem]( + "play.twirl.compiler.TwirlCompiler#TemplateAsFunctionCompiler.getFunctionMapping" + ), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template0"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template1"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template10"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template11"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template12"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template13"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template14"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template15"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template16"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template17"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template18"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template19"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template2"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template20"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template21"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template22"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template3"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template4"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template5"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template6"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template7"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template8"), + ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template9"), ) ) From f7c7c58f05bfaa4f3370b163b89b0f6f03c7d629 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 12 Mar 2024 00:02:53 +0100 Subject: [PATCH 3/6] Re-add Template traits so existing error pages in Play don't break (cherry picked from commit e9e3dd46026e0a7bca3b9b242cd53e2ceb7d96c8) # Conflicts: # build.sbt --- .../main/scala/play/twirl/api/Template.scala | 185 ++++++++++++++++++ build.sbt | 28 +-- 2 files changed, 190 insertions(+), 23 deletions(-) create mode 100644 api/shared/src/main/scala/play/twirl/api/Template.scala diff --git a/api/shared/src/main/scala/play/twirl/api/Template.scala b/api/shared/src/main/scala/play/twirl/api/Template.scala new file mode 100644 index 00000000..3992fd72 --- /dev/null +++ b/api/shared/src/main/scala/play/twirl/api/Template.scala @@ -0,0 +1,185 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package play.twirl.api + +trait Template0[Result] { + def render(): Result +} + +trait Template1[A, Result] { + def render(a: A): Result +} + +trait Template2[A, B, Result] { + def render(a: A, b: B): Result +} + +trait Template3[A, B, C, Result] { + def render(a: A, b: B, c: C): Result +} + +trait Template4[A, B, C, D, Result] { + def render(a: A, b: B, c: C, d: D): Result +} + +trait Template5[A, B, C, D, E, Result] { + def render(a: A, b: B, c: C, d: D, e: E): Result +} + +trait Template6[A, B, C, D, E, F, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F): Result +} + +trait Template7[A, B, C, D, E, F, G, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Result +} + +trait Template8[A, B, C, D, E, F, G, H, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): Result +} + +trait Template9[A, B, C, D, E, F, G, H, I, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): Result +} + +trait Template10[A, B, C, D, E, F, G, H, I, J, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): Result +} + +trait Template11[A, B, C, D, E, F, G, H, I, J, K, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K): Result +} + +trait Template12[A, B, C, D, E, F, G, H, I, J, K, L, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L): Result +} + +trait Template13[A, B, C, D, E, F, G, H, I, J, K, L, M, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M): Result +} + +trait Template14[A, B, C, D, E, F, G, H, I, J, K, L, M, N, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N): Result +} + +trait Template15[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O): Result +} + +trait Template16[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P): Result +} + +trait Template17[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q) + : Result +} + +trait Template18[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Result] { + def render(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q, r: R) + : Result +} + +trait Template19[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Result] { + def render( + a: A, + b: B, + c: C, + d: D, + e: E, + f: F, + g: G, + h: H, + i: I, + j: J, + k: K, + l: L, + m: M, + n: N, + o: O, + p: P, + q: Q, + r: R, + s: S + ): Result +} + +trait Template20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Result] { + def render( + a: A, + b: B, + c: C, + d: D, + e: E, + f: F, + g: G, + h: H, + i: I, + j: J, + k: K, + l: L, + m: M, + n: N, + o: O, + p: P, + q: Q, + r: R, + s: S, + t: T + ): Result +} + +trait Template21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, Result] { + def render( + a: A, + b: B, + c: C, + d: D, + e: E, + f: F, + g: G, + h: H, + i: I, + j: J, + k: K, + l: L, + m: M, + n: N, + o: O, + p: P, + q: Q, + r: R, + s: S, + t: T, + u: U + ): Result +} + +trait Template22[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, Result] { + def render( + a: A, + b: B, + c: C, + d: D, + e: E, + f: F, + g: G, + h: H, + i: I, + j: J, + k: K, + l: L, + m: M, + n: N, + o: O, + p: P, + q: Q, + r: R, + s: S, + t: T, + u: U, + v: V + ): Result +} diff --git a/build.sbt b/build.sbt index 6d9fd50c..af58848a 100644 --- a/build.sbt +++ b/build.sbt @@ -2,6 +2,7 @@ import Dependencies._ <<<<<<< HEAD +<<<<<<< HEAD import com.typesafe.tools.mima.core.DirectMissingMethodProblem import com.typesafe.tools.mima.core.IncompatibleMethTypeProblem @@ -11,6 +12,10 @@ import com.typesafe.tools.mima.core.Problem import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem import com.typesafe.tools.mima.core.MissingClassProblem >>>>>>> 1908648 (MiMa filters) +======= + +import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem +>>>>>>> e9e3dd4 (Re-add Template traits so existing error pages in Play don't break) import com.typesafe.tools.mima.core.ProblemFilters import sbtcrossproject.CrossPlugin.autoImport.crossProject import org.scalajs.jsenv.nodejs.NodeJSEnv @@ -32,29 +37,6 @@ val mimaSettings = Seq( ProblemFilters.exclude[IncompatibleResultTypeProblem]( "play.twirl.compiler.TwirlCompiler#TemplateAsFunctionCompiler.getFunctionMapping" ), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template0"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template1"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template10"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template11"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template12"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template13"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template14"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template15"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template16"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template17"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template18"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template19"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template2"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template20"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template21"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template22"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template3"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template4"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template5"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template6"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template7"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template8"), - ProblemFilters.exclude[MissingClassProblem]("play.twirl.api.Template9"), ) ) From aaea4e3e0a22c843330077f97b2f074ef42eeb9c Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 12 Mar 2024 10:14:50 +0100 Subject: [PATCH 4/6] Do not add Template traits when generating Scala 3 code (cherry picked from commit 75eec7cf46e23f0d10fa0a7f24d2f9b44c6c9738) # Conflicts: # build.sbt --- build.sbt | 6 ++--- .../play/twirl/compiler/TwirlCompiler.scala | 26 +++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/build.sbt b/build.sbt index af58848a..ee714c19 100644 --- a/build.sbt +++ b/build.sbt @@ -14,9 +14,12 @@ import com.typesafe.tools.mima.core.MissingClassProblem >>>>>>> 1908648 (MiMa filters) ======= +<<<<<<< HEAD import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem >>>>>>> e9e3dd4 (Re-add Template traits so existing error pages in Play don't break) import com.typesafe.tools.mima.core.ProblemFilters +======= +>>>>>>> 75eec7c (Do not add Template traits when generating Scala 3 code) import sbtcrossproject.CrossPlugin.autoImport.crossProject import org.scalajs.jsenv.nodejs.NodeJSEnv @@ -34,9 +37,6 @@ val previousVersion: Option[String] = Some("1.6.0") val mimaSettings = Seq( mimaPreviousArtifacts := previousVersion.map(organization.value %% moduleName.value % _).toSet, mimaBinaryIssueFilters ++= Seq( - ProblemFilters.exclude[IncompatibleResultTypeProblem]( - "play.twirl.compiler.TwirlCompiler#TemplateAsFunctionCompiler.getFunctionMapping" - ), ) ) diff --git a/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala b/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala index 6ee86b93..20f46d3d 100644 --- a/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala +++ b/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala @@ -166,6 +166,8 @@ object TwirlCompiler { private[compiler] class ScalaCompat(emitScala3Sources: Boolean) { val varargSplicesSyntax: String = if (emitScala3Sources) "*" else ": _*" + def valueOrEmptyIfScala3(value: => String): String = + if (emitScala3Sources) "" else value } private[compiler] object ScalaCompat { @@ -556,7 +558,7 @@ object TwirlCompiler { additionalImports: collection.Seq[String], constructorAnnotations: collection.Seq[String] ): collection.Seq[Any] = { - val (renderCall, f) = + val (renderCall, f, templateType) = TemplateAsFunctionCompiler.getFunctionMapping(root.params.str, resultType, scalaCompat) // Get the imports that we need to include, filtering out empty imports @@ -574,7 +576,8 @@ class """ :+ name :+ " " :+ constructorAnnotations :+ " " :+ Source(constructor. package """ :+ packageName :+ """ """ :+ imports :+ """ -""" :+ classDeclaration :+ """ extends _root_.play.twirl.api.BaseScalaTemplate[""" :+ resultType :+ """,_root_.play.twirl.api.Format[""" :+ resultType :+ """]](""" :+ formatterType :+ """) { +""" :+ classDeclaration :+ """ extends _root_.play.twirl.api.BaseScalaTemplate[""" :+ resultType :+ """,_root_.play.twirl.api.Format[""" :+ resultType :+ """]](""" :+ formatterType :+ """)""" :+ scalaCompat + .valueOrEmptyIfScala3(s" with $templateType") :+ """ { /*""" :+ root.comment.map(_.msg).getOrElse("") :+ """*/ def apply""" :+ Source(root.params.str, root.params.pos) :+ """:""" :+ resultType :+ """ = { @@ -675,14 +678,14 @@ package """ :+ packageName :+ """ def getFunctionMapping( signature: String, returnType: String, - ): (String, String) = + ): (String, String, String) = getFunctionMapping(signature, returnType, ScalaCompat(None)) private[compiler] def getFunctionMapping( signature: String, returnType: String, sc: ScalaCompat - ): (String, String) = { + ): (String, String, String) = { val params: List[List[Term.Param]] = try { @@ -732,6 +735,19 @@ package """ :+ packageName :+ """ .mkString ) + val templateType = sc.valueOrEmptyIfScala3( + "_root_.play.twirl.api.Template%s[%s%s]".format( + params.flatten.size, + params.flatten + .map { + case ByNameParam(_, paramType) => paramType + case p => filterType(p) + } + .mkString(","), + (if (params.flatten.isEmpty) "" else ",") + returnType + ) + ) + val f = "def f:%s = %s => apply%s".format( functionType, params.map(group => "(" + group.map(_.name.toString).mkString(",") + ")").mkString(" => "), @@ -749,7 +765,7 @@ package """ :+ packageName :+ """ .mkString ) - (renderCall, f) + (renderCall, f, templateType) } } From 3934524e48c683c38490944611e68ce688473c04 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 12 Mar 2024 10:40:10 +0100 Subject: [PATCH 5/6] Test 22+ template paramaters in Scala 3 (cherry picked from commit 491b9afec89a8294801fdf287879921c3cd1cc66) --- .../twirl/compile-scala3/src/test/scala/test/Test.scala | 6 ++++++ .../src/test/twirl/test/manyargstemplate.scala.html | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/twirl/test/manyargstemplate.scala.html diff --git a/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/scala/test/Test.scala b/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/scala/test/Test.scala index d9db0c9f..b301587b 100644 --- a/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/scala/test/Test.scala +++ b/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/scala/test/Test.scala @@ -10,4 +10,10 @@ object Test extends App { test(a.b.html.c.render("world"), "Hello, world.\n") test(html.template.render("42"), "Answer: 42\n") + + test( + html.manyargstemplate.render( + "1", "2", "3", "5", "4", "7", "6", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"), + "26 args: 1 2 3 5 4 7 6 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26\n" + ) } diff --git a/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/twirl/test/manyargstemplate.scala.html b/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/twirl/test/manyargstemplate.scala.html new file mode 100644 index 00000000..58ed92ea --- /dev/null +++ b/sbt-twirl/src/sbt-test/twirl/compile-scala3/src/test/twirl/test/manyargstemplate.scala.html @@ -0,0 +1,6 @@ +@**************************************************************************************************************************************************** + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. * + ****************************************************************************************************************************************************@ + +@(a: String, b: String, c: String, d: String, e: String, f: String, g: String, h: String, i: String, j: String, k: String, l: String, m: String, n: String, o: String, p: String, q: String, r: String, s: String, t: String, u: String, v: String, w: String, x: String, y: String, z: String) +26 args: @a @b @c @d @e @f @g @h @i @j @k @l @m @n @o @p @q @r @s @t @u @v @w @x @y @z From d3af09916426904e5300a9bbb490893644d8cee5 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 12 Mar 2024 11:03:31 +0100 Subject: [PATCH 6/6] Resolve conflicts --- build.sbt | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/build.sbt b/build.sbt index ee714c19..453ca770 100644 --- a/build.sbt +++ b/build.sbt @@ -1,25 +1,12 @@ // Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. import Dependencies._ -<<<<<<< HEAD -<<<<<<< HEAD import com.typesafe.tools.mima.core.DirectMissingMethodProblem import com.typesafe.tools.mima.core.IncompatibleMethTypeProblem import com.typesafe.tools.mima.core.MissingClassProblem import com.typesafe.tools.mima.core.Problem -======= -import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem -import com.typesafe.tools.mima.core.MissingClassProblem ->>>>>>> 1908648 (MiMa filters) -======= - -<<<<<<< HEAD -import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem ->>>>>>> e9e3dd4 (Re-add Template traits so existing error pages in Play don't break) import com.typesafe.tools.mima.core.ProblemFilters -======= ->>>>>>> 75eec7c (Do not add Template traits when generating Scala 3 code) import sbtcrossproject.CrossPlugin.autoImport.crossProject import org.scalajs.jsenv.nodejs.NodeJSEnv