pfn / kotlin-plugin

Build kotlin code using sbt
MIT License
136 stars 35 forks source link

Kotlin Controllers are not able to resolve Twirl templates #15

Open adrianpowell opened 7 years ago

adrianpowell commented 7 years ago

I started with a very simple Play application which has a Controller in Kotlin that references a Twirl template. The Twirl needs to be complied before the Kotlin so that the generated class is visible, but the Kotlin appears to be compiled first resulting in errors:

[info] Compiling 2 Kotlin sources
[error] /Users/apowell/dev/kotlin-play-poc/app/controllers/HomeController.kt: 6, 19: Unresolved reference: index
[error] /Users/apowell/dev/kotlin-play-poc/app/controllers/HomeController.kt: 11, 27: Unresolved reference: index
[error] Compilation failed. See log for more details
[error] (compile:kotlinCompile) Compilation failed. See log for more details

My Controller is:

package controllers

import play.mvc.Controller
import play.mvc.Result
import play.mvc.Results
import views.html.index

class HomeController : Controller() {

    fun home(): Result {
        return Results.ok(index.apply("Your new application is ready"))
    }
}

If I remove the reference to the Twirl template (eg: return Results.ok("Kotlin controller is working")) then the compilation is successful, Java controllers can reference this template and the application runs.

Is there a way to force the Twirl/scala compilation to happen first?

pfn commented 7 years ago

kotlin cannot compile before scala in this plugin. This is due to mix-mode scala+java+kotlin support.

If twirl compiles directly to classes, you can make kotlinCompile depend on twirl:

kotlinCompile in Compile := ((kotlinCompile in Compile) dependsOn theTwirlTaskIDontKnowWhatItIs).value

adrianpowell commented 7 years ago

I'll see if I can find out the name of that task, thanks for the pointer.

adrianpowell commented 7 years ago
kotlinCompile in Compile := ((kotlinCompile in Compile) dependsOn (TwirlKeys.compileTemplates in Compile)).value

will compile the Twirl templates, but the task doesn't result in .class files but rather some .scala files under target/scala-1.12/twirl/main/views/html.

Since the Kotlin Controller needs to import and reference these as classes, it sounds like I would need a mix-mode scala+java+kotlin which doesn't exist. Thanks for your help.

pfn commented 7 years ago

You will need to remove the dependency on kotlinCompile from compile (see how it's defined in Defaults.scala for sbt and re-declare it); it will look something like the following:

   // fix task scopes as necessary.
   compile in Compile := Defaults.compileTask.value
   compile in Compile := { // this will make kotlinCompile run after compile
      KotlinCompile.compile(kotlincOptions.value,
         sourceDirectories.value, kotlincPluginOptions.value,
         dependencyClasspath.value, (managedClasspath in KotlinInternal).value,
         classDirectory.value, streams.value)
     (compile in Compile).value
   },