summaryrefslogtreecommitdiff
path: root/contrib/twirllib/src/mill/twirllib/TwirlWorker.scala
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/twirllib/src/mill/twirllib/TwirlWorker.scala')
-rw-r--r--contrib/twirllib/src/mill/twirllib/TwirlWorker.scala58
1 files changed, 47 insertions, 11 deletions
diff --git a/contrib/twirllib/src/mill/twirllib/TwirlWorker.scala b/contrib/twirllib/src/mill/twirllib/TwirlWorker.scala
index ce8175a6..b8fe9c66 100644
--- a/contrib/twirllib/src/mill/twirllib/TwirlWorker.scala
+++ b/contrib/twirllib/src/mill/twirllib/TwirlWorker.scala
@@ -20,21 +20,43 @@ class TwirlWorker {
case Some((sig, instance)) if sig == classloaderSig => instance
case _ =>
val cl = new URLClassLoader(twirlClasspath.map(_.toIO.toURI.toURL).toArray, null)
- val twirlCompilerClass = cl.loadClass("play.twirl.compiler.TwirlCompiler")
+
+ // Switched to using the java api because of the hack-ish thing going on later.
+ //
+ // * we'll need to construct a collection of additional imports
+ // * it will need to consider the defaults
+ // * and add the user-provided additional imports
+ // * the default collection in scala api is a Seq[String]
+ // * but it is defined in a different classloader (namely in cl)
+ // * so we can not construct our own Seq and pass it to the method - it will be from our classloader, and not compatible
+ // * the java api has a Collection as the type for this param, for which it is much more doable to append things to it using reflection
+ //
+ // NOTE: I tried creating the cl classloader passing the current classloader as the parent:
+ // val cl = new URLClassLoader(twirlClasspath.map(_.toIO.toURI.toURL).toArray, getClass.getClassLoader)
+ // in that case it was possible to cast the default to a Seq[String], construct our own Seq[String], and pass it to the method invoke- it was compatible.
+ // And the tests passed. But when run in a different mill project, I was getting exceptions like this:
+ // scala.reflect.internal.MissingRequirementError: object scala in compiler mirror not found.
+
+ val twirlCompilerClass = cl.loadClass("play.japi.twirl.compiler.TwirlCompiler")
+
+ // this one is only to get the codec: Codec parameter default value
+ val twirlScalaCompilerClass = cl.loadClass("play.twirl.compiler.TwirlCompiler")
+
val compileMethod = twirlCompilerClass.getMethod("compile",
classOf[java.io.File],
classOf[java.io.File],
classOf[java.io.File],
classOf[java.lang.String],
- cl.loadClass("scala.collection.Seq"),
- cl.loadClass("scala.collection.Seq"),
+ cl.loadClass("java.util.Collection"),
+ cl.loadClass("java.util.List"),
cl.loadClass("scala.io.Codec"),
classOf[Boolean])
- val defaultAdditionalImportsMethod = twirlCompilerClass.getMethod("compile$default$5")
- val defaultConstructorAnnotationsMethod = twirlCompilerClass.getMethod("compile$default$6")
- val defaultCodecMethod = twirlCompilerClass.getMethod("compile$default$7")
- val defaultFlagMethod = twirlCompilerClass.getMethod("compile$default$8")
+ val arrayListClass = cl.loadClass("java.util.ArrayList")
+ val hashSetClass = cl.loadClass("java.util.HashSet")
+
+ val defaultAdditionalImportsMethod = twirlCompilerClass.getField("DEFAULT_IMPORTS")
+ val defaultCodecMethod = twirlScalaCompilerClass.getMethod("compile$default$7")
val instance = new TwirlWorkerApi {
override def compileTwirl(source: File,
@@ -45,14 +67,28 @@ class TwirlWorker {
constructorAnnotations: Seq[String],
codec: Codec,
inclusiveDot: Boolean) {
+ val defaultAdditionalImports = defaultAdditionalImportsMethod.get(null) // unmodifiable collection
+ // copying it into a modifiable hash set and adding all additional imports
+ val allAdditionalImports =
+ hashSetClass
+ .getConstructor(cl.loadClass("java.util.Collection"))
+ .newInstance(defaultAdditionalImports)
+ .asInstanceOf[Object]
+ val hashSetAddMethod =
+ allAdditionalImports
+ .getClass
+ .getMethod("add", classOf[Object])
+ additionalImports.foreach(hashSetAddMethod.invoke(allAdditionalImports, _))
+
val o = compileMethod.invoke(null, source,
sourceDirectory,
generatedDirectory,
formatterType,
- defaultAdditionalImportsMethod.invoke(null),
- defaultConstructorAnnotationsMethod.invoke(null),
+ allAdditionalImports,
+ arrayListClass.newInstance().asInstanceOf[Object], // empty list seems to be the default
defaultCodecMethod.invoke(null),
- defaultFlagMethod.invoke(null))
+ Boolean.box(false)
+ )
}
}
twirlInstanceCache = Some((classloaderSig, instance))
@@ -89,7 +125,7 @@ class TwirlWorker {
sourceDirectories.foreach(compileTwirlDir)
val zincFile = ctx.dest / 'zinc
- val classesDir = ctx.dest / 'html
+ val classesDir = ctx.dest
mill.eval.Result.Success(CompilationResult(zincFile, PathRef(classesDir)))
}