Kotlin2Js Gradle plugin implementation
This commit is contained in:
committed by
Zalim Bashorov
parent
ec47cb57c5
commit
b1723668ce
+218
-49
@@ -35,10 +35,187 @@ import org.gradle.api.UnknownDomainObjectException
|
||||
import org.gradle.api.initialization.dsl.ScriptHandler
|
||||
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
|
||||
import javax.inject.Inject
|
||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import kotlin.properties.Delegates
|
||||
import org.gradle.api.tasks.Delete
|
||||
import org.codehaus.groovy.runtime.MethodClosure
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
|
||||
val DEFAULT_ANNOTATIONS = "org.jebrains.kotlin.gradle.defaultAnnotations"
|
||||
|
||||
open class KotlinPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin<Project> {
|
||||
|
||||
abstract class KotlinSourceSetProcessor<T : AbstractCompile>(val project: ProjectInternal,
|
||||
val javaBasePlugin: JavaBasePlugin,
|
||||
val sourceSet: SourceSet,
|
||||
val pluginName: String,
|
||||
val compileTaskNameSuffix: String,
|
||||
val taskDescription: String,
|
||||
val compilerClass: Class<T>) {
|
||||
abstract protected fun doTargetSpecificProcessing()
|
||||
val logger = Logging.getLogger(this.javaClass)
|
||||
|
||||
protected val sourceSetName: String = sourceSet.getName()
|
||||
protected val sourceRootDir: String = "src/${sourceSetName}/kotlin"
|
||||
protected val absoluteSourceRootDir: String = project.getProjectDir().getPath() + "/" + sourceRootDir
|
||||
protected val kotlinSourceSet: KotlinSourceSet? by Delegates.lazy { createKotlinSourceSet() }
|
||||
protected val kotlinDirSet: SourceDirectorySet? by Delegates.lazy { createKotlinDirSet() }
|
||||
protected val kotlinTask: T by Delegates.lazy { createKotlinCompileTask() }
|
||||
protected val kotlinTaskName: String by Delegates.lazy { kotlinTask.getName() }
|
||||
|
||||
public fun run() {
|
||||
if (kotlinSourceSet == null || kotlinDirSet == null) {
|
||||
return
|
||||
}
|
||||
addSourcesToKotlinDirSet()
|
||||
commonTaskConfiguration()
|
||||
doTargetSpecificProcessing()
|
||||
}
|
||||
|
||||
open protected fun createKotlinSourceSet(): KotlinSourceSet? =
|
||||
if (sourceSet is HasConvention) {
|
||||
logger.debug("Creating KotlinSourceSet for source set ${sourceSet}")
|
||||
val kotlinSourceSet = KotlinSourceSetImpl(sourceSet.getName(), project.getFileResolver())
|
||||
sourceSet.getConvention().getPlugins().put(pluginName, kotlinSourceSet)
|
||||
kotlinSourceSet
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
open protected fun createKotlinDirSet(): SourceDirectorySet? {
|
||||
val srcDir = project.file(sourceRootDir)
|
||||
logger.debug("Creating Kotlin SourceDirectorySet for source set ${kotlinSourceSet} with src dir ${srcDir}")
|
||||
val kotlinDirSet = kotlinSourceSet?.getKotlin()
|
||||
kotlinDirSet?.srcDir(srcDir)
|
||||
return kotlinDirSet
|
||||
}
|
||||
|
||||
open protected fun addSourcesToKotlinDirSet() {
|
||||
logger.debug("Adding Kotlin SourceDirectorySet ${kotlinDirSet} to source set ${sourceSet}")
|
||||
sourceSet.getAllJava()?.source(kotlinDirSet)
|
||||
sourceSet.getAllSource()?.source(kotlinDirSet)
|
||||
sourceSet.getResources()?.getFilter()?.exclude { kotlinDirSet!!.contains(it.getFile()) }
|
||||
}
|
||||
|
||||
open protected fun createKotlinCompileTask(): T {
|
||||
val name = sourceSet.getCompileTaskName(compileTaskNameSuffix)
|
||||
logger.debug("Creating kotlin compile task $name with class $compilerClass")
|
||||
return project.getTasks().create(name, compilerClass)
|
||||
}
|
||||
|
||||
open protected fun commonTaskConfiguration() {
|
||||
javaBasePlugin.configureForSourceSet(sourceSet, kotlinTask)
|
||||
kotlinTask.setDescription(taskDescription)
|
||||
kotlinTask.source(kotlinDirSet)
|
||||
}
|
||||
}
|
||||
|
||||
class Kotlin2JvmSourceSetProcessor(
|
||||
project: ProjectInternal,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
val scriptHandler: ScriptHandler)
|
||||
: KotlinSourceSetProcessor<KotlinCompile>(
|
||||
project, javaBasePlugin, sourceSet,
|
||||
pluginName = "kotlin",
|
||||
compileTaskNameSuffix = "kotlin",
|
||||
taskDescription = "Compiles the $sourceSet.kotlin.",
|
||||
compilerClass = javaClass()) {
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
// store kotlin classes in separate directory. They will serve as class-path to java compiler
|
||||
kotlinTask.kotlinDestinationDir = File(project.getBuildDir(), "kotlin-classes/${sourceSetName}")
|
||||
|
||||
val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?
|
||||
|
||||
if (javaTask != null) {
|
||||
javaTask.dependsOn(kotlinTaskName)
|
||||
val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir);
|
||||
javaTask.setClasspath(javacClassPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Kotlin2JsSourceSetProcessor(
|
||||
project: ProjectInternal,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
val scriptHandler: ScriptHandler
|
||||
) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
|
||||
project, javaBasePlugin, sourceSet,
|
||||
pluginName = "kotlin2js",
|
||||
taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.",
|
||||
compileTaskNameSuffix = "kotlin2Js",
|
||||
compilerClass = javaClass<Kotlin2JsCompile>()) {
|
||||
val copyKotlinJsTaskName = sourceSet.getTaskName("copy", "kotlinJs")
|
||||
val clean = project.getTasks().findByName("clean")
|
||||
val build = project.getTasks().findByName("build")
|
||||
|
||||
val defaultKotlinDestinationDir = File(project.getBuildDir(), "kotlin2js/${sourceSetName}")
|
||||
private fun kotlinTaskDestinationDir(): File? = kotlinTask.kotlinDestinationDir
|
||||
private fun kotlinJsDestinationDir(): File? = if (kotlinTask.outputFile() == null) {
|
||||
null
|
||||
} else {
|
||||
File(kotlinTask.outputFile()).directory
|
||||
}
|
||||
|
||||
private fun copyKotlinJsTaskOutput(): String? = if (kotlinJsDestinationDir() == null) {
|
||||
null
|
||||
} else {
|
||||
val copyTask = project.getTasks().getByName(copyKotlinJsTaskName) as Copy
|
||||
"${copyTask.getDestinationDir()}/kotlin.js"
|
||||
}
|
||||
|
||||
private fun kotlinSourcePathsForSourceMap() = sourceSet.getAllSource()
|
||||
.map { it.path }
|
||||
.filter { it.endsWith(".kt") }
|
||||
.map { it.replace(absoluteSourceRootDir, kotlinTask.sourceMapDestinationDir().getPath()) }
|
||||
|
||||
private fun shouldGenerateSourceMap() = kotlinTask.kotlinOptions.sourceMap
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
kotlinTask.kotlinDestinationDir = defaultKotlinDestinationDir
|
||||
build?.dependsOn(kotlinTaskName)
|
||||
clean?.dependsOn("clean" + kotlinTaskName.capitalize())
|
||||
|
||||
createCopyKotlinJsTask(GradleUtils(scriptHandler, project).resolveJsLibrary().getAbsolutePath())
|
||||
createCleanSourceMapTask()
|
||||
}
|
||||
|
||||
private fun createCopyKotlinJsTask(jsLibraryJar: String) {
|
||||
val copyKotlinJsTaskName = sourceSet.getTaskName("copy", "kotlinJs")
|
||||
|
||||
val copyKotlinJsTask = project.getTasks().create(copyKotlinJsTaskName, javaClass<Copy>())
|
||||
copyKotlinJsTask.from(project.zipTree(jsLibraryJar))
|
||||
copyKotlinJsTask.into(MethodClosure(this, "kotlinJsDestinationDir"))
|
||||
copyKotlinJsTask.include("kotlin.js")
|
||||
copyKotlinJsTask.onlyIf { kotlinJsDestinationDir() != null }
|
||||
build?.dependsOn(copyKotlinJsTaskName)
|
||||
|
||||
val cleanTaskName = "clean" + copyKotlinJsTaskName.capitalize()
|
||||
val cleanTask = project.getTasks().create(cleanTaskName, javaClass<Delete>())
|
||||
cleanTask.delete(MethodClosure(this, "copyKotlinJsTaskOutput"))
|
||||
copyKotlinJsTask.onlyIf { copyKotlinJsTaskOutput() != null }
|
||||
clean?.dependsOn(cleanTaskName)
|
||||
}
|
||||
|
||||
private fun createCleanSourceMapTask() {
|
||||
val taskName = sourceSet.getTaskName("clean", "sourceMap")
|
||||
val task = project.getTasks().create(taskName, javaClass<Delete>())
|
||||
task.onlyIf { kotlinTask.kotlinOptions.sourceMap }
|
||||
task.delete(object : Closure<String>(this) {
|
||||
override fun call(): String? = kotlinTask.outputFile() + ".map"
|
||||
})
|
||||
clean?.dependsOn(taskName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract class AbstractKotlinPlugin [Inject] (val scriptHandler: ScriptHandler) : Plugin<Project> {
|
||||
abstract fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet): KotlinSourceSetProcessor<*>
|
||||
|
||||
public override fun apply(project: Project) {
|
||||
val javaBasePlugin = project.getPlugins().apply(javaClass<JavaBasePlugin>())
|
||||
@@ -49,49 +226,23 @@ open class KotlinPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin<Proj
|
||||
configureSourceSetDefaults(project as ProjectInternal, javaBasePlugin, javaPluginConvention)
|
||||
configureKDoc(project, javaPluginConvention)
|
||||
|
||||
val version = project.getProperties()["kotlin.gradle.plugin.version"] as String
|
||||
project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler).resolveDependencies("org.jetbrains.kotlin:kotlin-jdk-annotations:$version"))
|
||||
val gradleUtils = GradleUtils(scriptHandler, project)
|
||||
project.getExtensions().add(DEFAULT_ANNOTATIONS, gradleUtils.resolveKotlinPluginDependency("kotlin-jdk-annotations"))
|
||||
}
|
||||
|
||||
|
||||
private fun configureSourceSetDefaults(project: ProjectInternal,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
javaPluginConvention: JavaPluginConvention) {
|
||||
javaPluginConvention.getSourceSets()?.all(Action<SourceSet> { sourceSet ->
|
||||
if (sourceSet is HasConvention) {
|
||||
val sourceSetName = sourceSet.getName()
|
||||
val kotlinSourceSet = KotlinSourceSetImpl( sourceSetName, project.getFileResolver())
|
||||
sourceSet.getConvention().getPlugins().put("kotlin", kotlinSourceSet)
|
||||
|
||||
val kotlinDirSet = kotlinSourceSet.getKotlin()
|
||||
kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin"))
|
||||
|
||||
sourceSet.getAllJava()?.source(kotlinDirSet)
|
||||
sourceSet.getAllSource()?.source(kotlinDirSet)
|
||||
sourceSet.getResources()?.getFilter()?.exclude({ kotlinDirSet.contains(it.getFile()) })
|
||||
|
||||
val kotlinTaskName = sourceSet.getCompileTaskName("kotlin")
|
||||
val kotlinTask: KotlinCompile = project.getTasks().create(kotlinTaskName, javaClass<KotlinCompile>())
|
||||
|
||||
javaBasePlugin.configureForSourceSet(sourceSet, kotlinTask)
|
||||
// store kotlin classes in separate directory. They will serve as class-path to java compiler
|
||||
kotlinTask.kotlinDestinationDir = File(project.getBuildDir(), "kotlin-classes/${sourceSetName}")
|
||||
|
||||
kotlinTask.setDescription("Compiles the $sourceSet.kotlin.")
|
||||
kotlinTask.source(kotlinDirSet)
|
||||
|
||||
val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?
|
||||
|
||||
if (javaTask != null) {
|
||||
javaTask.dependsOn(kotlinTaskName)
|
||||
val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir)
|
||||
javaTask.setClasspath(javacClassPath)
|
||||
open protected fun configureSourceSetDefaults(project: ProjectInternal,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
javaPluginConvention: JavaPluginConvention) {
|
||||
javaPluginConvention.getSourceSets()?.all(object : Action<SourceSet> {
|
||||
override fun execute(sourceSet: SourceSet?) {
|
||||
if (sourceSet != null) {
|
||||
buildSourceSetProcessor(project, javaBasePlugin, sourceSet).run()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun configureKDoc(project: Project, javaPluginConvention: JavaPluginConvention) {
|
||||
open protected fun configureKDoc(project: Project, javaPluginConvention: JavaPluginConvention) {
|
||||
val mainSourceSet = javaPluginConvention.getSourceSets()?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) as HasConvention?
|
||||
|
||||
if (mainSourceSet != null) {
|
||||
@@ -113,7 +264,19 @@ open class KotlinPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin<Proj
|
||||
}
|
||||
|
||||
|
||||
open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin<Project> {
|
||||
open class KotlinPlugin [Inject] (scriptHandler: ScriptHandler) : AbstractKotlinPlugin(scriptHandler) {
|
||||
override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet): KotlinSourceSetProcessor<KotlinCompile> =
|
||||
Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler)
|
||||
}
|
||||
|
||||
|
||||
open class Kotlin2JsPlugin [Inject] (scriptHandler: ScriptHandler) : AbstractKotlinPlugin(scriptHandler) {
|
||||
override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet) =
|
||||
Kotlin2JsSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler)
|
||||
}
|
||||
|
||||
|
||||
open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plugin<Project> {
|
||||
|
||||
val log = Logging.getLogger(this.javaClass)
|
||||
|
||||
@@ -125,7 +288,7 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plug
|
||||
ext.getSourceSets().all(Action<AndroidSourceSet> { sourceSet ->
|
||||
if (sourceSet is HasConvention) {
|
||||
val sourceSetName = sourceSet.getName()
|
||||
val kotlinSourceSet = KotlinSourceSetImpl( sourceSetName, project.getFileResolver())
|
||||
val kotlinSourceSet = KotlinSourceSetImpl(sourceSetName, project.getFileResolver())
|
||||
sourceSet.getConvention().getPlugins().put("kotlin", kotlinSourceSet)
|
||||
val kotlinDirSet = kotlinSourceSet.getKotlin()
|
||||
kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin"))
|
||||
@@ -161,8 +324,7 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plug
|
||||
}
|
||||
}
|
||||
|
||||
val version = project.getProperties()["kotlin.gradle.plugin.version"] as String
|
||||
project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler!!).resolveDependencies("org.jetbrains.kotlin:kotlin-android-sdk-annotations:$version"))
|
||||
project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler, project).resolveKotlinPluginDependency("kotlin-android-sdk-annotations"))
|
||||
}
|
||||
|
||||
private fun processVariants(variants: DefaultDomainObjectSet<out BaseVariant>, project: Project, androidExt: BaseExtension): Unit {
|
||||
@@ -182,13 +344,13 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plug
|
||||
val buildTypeSourceSetName = AndroidGradleWrapper.getVariantName(variant)
|
||||
|
||||
logger.debug("Variant build type is [$buildTypeSourceSetName]")
|
||||
val buildTypeSourceSet : AndroidSourceSet? = sourceSets.findByName(buildTypeSourceSetName)
|
||||
val buildTypeSourceSet: AndroidSourceSet? = sourceSets.findByName(buildTypeSourceSetName)
|
||||
|
||||
val javaTask = variant.getJavaCompile()!!
|
||||
val variantName = variant.getName()
|
||||
|
||||
val kotlinTaskName = "compile${variantName.capitalize()}Kotlin"
|
||||
val kotlinTask: KotlinCompile = project.getTasks().create(kotlinTaskName, javaClass<KotlinCompile>())
|
||||
val kotlinTask = project.getTasks().create(kotlinTaskName, javaClass<KotlinCompile>())
|
||||
kotlinTask.kotlinOptions = kotlinOptions
|
||||
|
||||
|
||||
@@ -246,7 +408,7 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plug
|
||||
if (null == plugin) {
|
||||
plugin = project.getPlugins().findPlugin("android-library")
|
||||
}
|
||||
val basePlugin : BasePlugin = plugin as BasePlugin
|
||||
val basePlugin: BasePlugin = plugin as BasePlugin
|
||||
val javaSources = project.files(javaSourceList)
|
||||
val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(basePlugin))
|
||||
val fullClasspath = (javaTask.getClasspath() + (javaSources + androidRT)) - project.files(kotlinTask.kotlinDestinationDir)
|
||||
@@ -273,16 +435,23 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler): Plug
|
||||
|
||||
}
|
||||
|
||||
|
||||
open class GradleUtils(val scriptHandler: ScriptHandler) {
|
||||
|
||||
open class GradleUtils(val scriptHandler: ScriptHandler, val project: ProjectInternal) {
|
||||
public fun resolveDependencies(vararg coordinates: String): Collection<File> {
|
||||
val dependencyHandler : DependencyHandler = scriptHandler.getDependencies()
|
||||
val configurationsContainer : ConfigurationContainer = scriptHandler.getConfigurations()
|
||||
val dependencyHandler: DependencyHandler = scriptHandler.getDependencies()
|
||||
val configurationsContainer: ConfigurationContainer = scriptHandler.getConfigurations()
|
||||
|
||||
val deps = coordinates map { dependencyHandler.create(it) }
|
||||
val configuration = configurationsContainer.detachedConfiguration(*deps.copyToArray())
|
||||
|
||||
return configuration.getResolvedConfiguration().getFiles({true})
|
||||
}
|
||||
}
|
||||
|
||||
public fun kotlinPluginVersion(): String = project.getProperties()["kotlin.gradle.plugin.version"] as String
|
||||
public fun kotlinPluginArtifactCoordinates(artifact: String): String = "org.jetbrains.kotlin:${artifact}:${kotlinPluginVersion()}"
|
||||
public fun kotlinJsLibraryCoordinates(): String = kotlinPluginArtifactCoordinates("kotlin-js-library")
|
||||
|
||||
public fun resolveKotlinPluginDependency(artifact: String): Collection<File> =
|
||||
resolveDependencies(kotlinPluginArtifactCoordinates(artifact))
|
||||
public fun resolveJsLibrary(): File = resolveDependencies(kotlinJsLibraryCoordinates()).first()
|
||||
}
|
||||
|
||||
+145
-47
@@ -24,19 +24,44 @@ import org.apache.commons.io.FileUtils
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.jet.config.Services
|
||||
import org.jetbrains.jet.cli.js.K2JSCompiler
|
||||
import org.jetbrains.jet.cli.common.arguments.K2JSCompilerArguments
|
||||
import org.jetbrains.k2js.config.MetaInfServices
|
||||
import org.jetbrains.k2js.config.ClassPathLibraryDefintionsConfig
|
||||
import org.jetbrains.jet.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.jet.config.CompilerConfiguration
|
||||
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.k2js.config.EcmaVersion
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import groovy.lang.Closure
|
||||
import org.codehaus.groovy.runtime.MethodClosure
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.jet.cli.common.CLICompiler
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import org.jetbrains.jet.plugin.JetFileType
|
||||
|
||||
public open class KotlinCompile(): AbstractCompile() {
|
||||
|
||||
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCompile() {
|
||||
abstract protected val compiler: CLICompiler<T>
|
||||
abstract protected fun createBlankArgs(): T
|
||||
open protected fun afterCompileHook(args: T) {
|
||||
}
|
||||
abstract protected fun populateTargetSpecificArgs(args: T)
|
||||
|
||||
public var kotlinOptions: T = createBlankArgs()
|
||||
val srcDirsSources = HashSet<SourceDirectorySet>()
|
||||
val compiler = K2JVMCompiler()
|
||||
|
||||
public var kotlinDestinationDir: File? = getDestinationDir()
|
||||
|
||||
private val logger = Logging.getLogger(this.javaClass)
|
||||
override fun getLogger() = logger
|
||||
|
||||
public var kotlinOptions: K2JVMCompilerArguments = K2JVMCompilerArguments()
|
||||
|
||||
public var kotlinDestinationDir : File? = getDestinationDir()
|
||||
|
||||
// override setSource to track source directory sets
|
||||
override fun setSource(source: Any?) {
|
||||
srcDirsSources.clear()
|
||||
@@ -71,48 +96,69 @@ public open class KotlinCompile(): AbstractCompile() {
|
||||
|
||||
[TaskAction]
|
||||
override fun compile() {
|
||||
|
||||
getLogger().debug("Starting Kotlin compilation task")
|
||||
|
||||
val args = K2JVMCompilerArguments()
|
||||
|
||||
val javaSrcRoots = HashSet<File>()
|
||||
val sources = ArrayList<File>()
|
||||
|
||||
// collect source directory roots for all java files to allow cross compilation
|
||||
for (file in getSource()) {
|
||||
if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase("java")) {
|
||||
val javaRoot = findSrcDirRoot(file)
|
||||
if (javaRoot != null) {
|
||||
javaSrcRoots.add(javaRoot)
|
||||
}
|
||||
} else {
|
||||
sources.add(file)
|
||||
}
|
||||
}
|
||||
|
||||
getLogger().debug("Starting ${javaClass} task")
|
||||
val args = createBlankArgs()
|
||||
val sources = getKotlinSources()
|
||||
if (sources.empty) {
|
||||
getLogger().warn("No Kotlin files found, skipping Kotlin compiler task")
|
||||
return
|
||||
}
|
||||
|
||||
args.suppressWarnings = kotlinOptions.suppressWarnings
|
||||
args.version = kotlinOptions.version
|
||||
args.verbose = logger.isDebugEnabled()
|
||||
populateTargetSpecificArgs(args)
|
||||
populateCommonArgs(args, sources)
|
||||
callCompiler(args)
|
||||
afterCompileHook(args)
|
||||
}
|
||||
|
||||
protected fun isJava(it: File): Boolean = it.extension.equalsIgnoreCase(JavaFileType.INSTANCE.getDefaultExtension())
|
||||
protected fun isKotlin(it: File): Boolean = it.extension.equalsIgnoreCase(JetFileType.INSTANCE.getDefaultExtension())
|
||||
|
||||
private fun getKotlinSources(): List<File> = getSource().filter{ isKotlin(it) }
|
||||
|
||||
private fun populateCommonArgs(args: T, sources: List<File>) {
|
||||
args.freeArgs = sources.map { it.getAbsolutePath() }
|
||||
args.suppressWarnings = kotlinOptions.suppressWarnings
|
||||
args.verbose = kotlinOptions.verbose
|
||||
args.version = kotlinOptions.version
|
||||
args.noInline = kotlinOptions.noInline
|
||||
}
|
||||
|
||||
|
||||
private fun callCompiler(args: T) {
|
||||
val messageCollector = GradleMessageCollector(getLogger())
|
||||
getLogger().debug("Calling compiler")
|
||||
val exitCode = compiler.exec(messageCollector, Services.EMPTY, args)
|
||||
|
||||
when (exitCode) {
|
||||
ExitCode.COMPILATION_ERROR -> throw GradleException("Compilation error. See log for more details")
|
||||
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
||||
override val compiler = K2JVMCompiler()
|
||||
|
||||
override fun createBlankArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
||||
|
||||
override fun populateTargetSpecificArgs(args: K2JVMCompilerArguments) {
|
||||
if (StringUtils.isEmpty(kotlinOptions.classpath)) {
|
||||
val existingClasspathEntries = getClasspath().filter({ it != null && it.exists() })
|
||||
val effectiveClassPath = (javaSrcRoots + existingClasspathEntries).makeString(File.pathSeparator)
|
||||
val effectiveClassPath = (getJavaSourceRoots() + existingClasspathEntries).makeString(File.pathSeparator)
|
||||
args.classpath = effectiveClassPath
|
||||
}
|
||||
|
||||
args.destination = if (StringUtils.isEmpty(kotlinOptions.destination)) { kotlinDestinationDir?.getPath() } else { kotlinOptions.destination }
|
||||
args.destination = if (StringUtils.isEmpty(kotlinOptions.destination)) {
|
||||
kotlinDestinationDir?.getPath()
|
||||
} else {
|
||||
kotlinOptions.destination
|
||||
}
|
||||
|
||||
val embeddedAnnotations = getAnnotations(getProject(), getLogger())
|
||||
val userAnnotations = (kotlinOptions.annotations ?: "").split(File.pathSeparatorChar).toList()
|
||||
val allAnnotations = if (kotlinOptions.noJdkAnnotations) userAnnotations else userAnnotations.plus(embeddedAnnotations.map {it.getPath()})
|
||||
val allAnnotations = if (kotlinOptions.noJdkAnnotations) userAnnotations else userAnnotations.plus(embeddedAnnotations.map { it.getPath() })
|
||||
args.annotations = allAnnotations.makeString(File.pathSeparator)
|
||||
|
||||
args.noStdlib = true
|
||||
@@ -121,17 +167,15 @@ public open class KotlinCompile(): AbstractCompile() {
|
||||
args.noOptimize = kotlinOptions.noOptimize
|
||||
args.noCallAssertions = kotlinOptions.noCallAssertions
|
||||
args.noParamAssertions = kotlinOptions.noParamAssertions
|
||||
}
|
||||
|
||||
val messageCollector = GradleMessageCollector(getLogger())
|
||||
getLogger().debug("Calling compiler")
|
||||
val exitCode = compiler.exec(messageCollector, Services.EMPTY, args)
|
||||
|
||||
when (exitCode) {
|
||||
ExitCode.COMPILATION_ERROR -> throw GradleException("Compilation error. See log for more details")
|
||||
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details")
|
||||
else -> {}
|
||||
}
|
||||
private fun getJavaSourceRoots(): Set<File> = getSource()
|
||||
.filter { isJava(it) }
|
||||
.map { findSrcDirRoot(it) }
|
||||
.filterNotNull()
|
||||
.toSet()
|
||||
|
||||
override fun afterCompileHook(args: K2JVMCompilerArguments) {
|
||||
getLogger().debug("Copying resulting files to classes")
|
||||
// Copy kotlin classes to all classes directory
|
||||
val outputDirFile = File(args.destination!!)
|
||||
@@ -141,7 +185,58 @@ public open class KotlinCompile(): AbstractCompile() {
|
||||
}
|
||||
}
|
||||
|
||||
public open class KDoc(): SourceTask() {
|
||||
public open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>() {
|
||||
override val compiler = K2JSCompiler()
|
||||
|
||||
override fun createBlankArgs(): K2JSCompilerArguments {
|
||||
val args = K2JSCompilerArguments()
|
||||
args.libraryFiles = array<String>() // defaults to null
|
||||
return args
|
||||
}
|
||||
|
||||
public fun addLibraryFiles(vararg fs: String) {
|
||||
kotlinOptions.libraryFiles = (kotlinOptions.libraryFiles + fs).copyToArray()
|
||||
}
|
||||
|
||||
public fun addLibraryFiles(vararg fs: File) {
|
||||
val strs = fs.map { it.getPath() }.copyToArray()
|
||||
addLibraryFiles(*strs)
|
||||
}
|
||||
|
||||
fun outputFile(): String? = kotlinOptions.outputFile
|
||||
|
||||
public fun sourceMapDestinationDir(): File = File(outputFile()).directory
|
||||
|
||||
{
|
||||
getOutputs().file(MethodClosure(this, "outputFile"))
|
||||
}
|
||||
|
||||
override fun populateTargetSpecificArgs(args: K2JSCompilerArguments) {
|
||||
args.outputFile = outputFile()
|
||||
args.outputPrefix = kotlinOptions.outputPrefix
|
||||
args.outputPostfix = kotlinOptions.outputPostfix
|
||||
args.libraryFiles = (kotlinOptions.libraryFiles + getProject().getConfigurations().getByName("compile").map{ it.canonicalPath }).copyToArray()
|
||||
args.target = kotlinOptions.target
|
||||
args.sourceMap = kotlinOptions.sourceMap
|
||||
|
||||
if (args.outputFile == null) {
|
||||
throw GradleException("${getName()}.kotlinOptions.outputFile must be set to a string.")
|
||||
}
|
||||
|
||||
val outputDir = File(args.outputFile).directory
|
||||
if (!outputDir.exists()) {
|
||||
if (!outputDir.mkdirs()) {
|
||||
throw GradleException("Failed to create output directory ${outputDir} or one of its ancestors")
|
||||
}
|
||||
}
|
||||
|
||||
getLogger().debug("${getName()} set libraryFiles to ${args.libraryFiles.join(",")}")
|
||||
getLogger().debug("${getName()} set outputFile to ${args.outputFile}")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public open class KDoc() : SourceTask() {
|
||||
|
||||
private val logger = Logging.getLogger(this.javaClass)
|
||||
override fun getLogger() = logger
|
||||
@@ -161,7 +256,11 @@ public open class KDoc(): SourceTask() {
|
||||
|
||||
val kdocOptions = kdocArgs.docConfig
|
||||
|
||||
cfg.docOutputDir = if ((kdocOptions.docOutputDir.length == 0) && (destinationDir != null)) { destinationDir!!.path } else { kdocOptions.docOutputDir }
|
||||
cfg.docOutputDir = if ((kdocOptions.docOutputDir.length == 0) && (destinationDir != null)) {
|
||||
destinationDir!!.path
|
||||
} else {
|
||||
kdocOptions.docOutputDir
|
||||
}
|
||||
cfg.title = kdocOptions.title
|
||||
cfg.sourceRootHref = kdocOptions.sourceRootHref
|
||||
cfg.projectRootDir = kdocOptions.projectRootDir
|
||||
@@ -180,7 +279,7 @@ public open class KDoc(): SourceTask() {
|
||||
getLogger().warn(args.freeArgs.toString())
|
||||
val embeddedAnnotations = getAnnotations(getProject(), getLogger())
|
||||
val userAnnotations = (kdocArgs.annotations ?: "").split(File.pathSeparatorChar).toList()
|
||||
val allAnnotations = if (kdocArgs.noJdkAnnotations) userAnnotations else userAnnotations.plus(embeddedAnnotations.map {it.getPath()})
|
||||
val allAnnotations = if (kdocArgs.noJdkAnnotations) userAnnotations else userAnnotations.plus(embeddedAnnotations.map { it.getPath() })
|
||||
args.annotations = allAnnotations.makeString(File.pathSeparator)
|
||||
|
||||
args.noStdlib = true
|
||||
@@ -195,7 +294,6 @@ public open class KDoc(): SourceTask() {
|
||||
when (exitCode) {
|
||||
ExitCode.COMPILATION_ERROR -> throw GradleException("Failed to generate kdoc. See log for more details")
|
||||
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal generation error. See log for more details")
|
||||
else -> {}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -205,14 +303,14 @@ fun getAnnotations(project: Project, logger: Logger): Collection<File> {
|
||||
val annotations = project.getExtensions().getByName(DEFAULT_ANNOTATIONS) as Collection<File>
|
||||
|
||||
if (!annotations.isEmpty()) {
|
||||
logger.info("using default annontations from [${annotations.map {it.getPath()}}]")
|
||||
logger.info("using default annontations from [${annotations.map { it.getPath() }}]")
|
||||
return annotations
|
||||
} else {
|
||||
throw GradleException("Default annotations not found in Kotlin gradle plugin classpath")
|
||||
}
|
||||
}
|
||||
|
||||
class GradleMessageCollector(val logger : Logger): MessageCollector {
|
||||
class GradleMessageCollector(val logger: Logger) : MessageCollector {
|
||||
public override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
|
||||
val text = with(StringBuilder()) {
|
||||
append(when (severity) {
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
<extraArtifacts>
|
||||
<extraArtifact>org.jetbrains.kotlin:kotlin-gradle-plugin-core:${project.version}</extraArtifact>
|
||||
<extraArtifact>org.jetbrains.kotlin:kotlin-jdk-annotations:${project.version}</extraArtifact>
|
||||
<extraArtifact>org.jetbrains.kotlin:kotlin-js-library:${project.version}</extraArtifact>
|
||||
<extraArtifact>org.jetbrains.kotlin:kotlin-android-sdk-annotations:${project.version}</extraArtifact>
|
||||
</extraArtifacts>
|
||||
</configuration>
|
||||
|
||||
+8
-1
@@ -111,4 +111,11 @@ open class KotlinAndriodPluginWrapper: KotlinBasePluginWrapper() {
|
||||
public override fun getPluginClassName():String {
|
||||
return "org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class Kotlin2JsPluginWrapper : KotlinBasePluginWrapper() {
|
||||
public override fun getPluginClassName():String {
|
||||
return "org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPlugin"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
implementation-class=org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPluginWrapper
|
||||
Reference in New Issue
Block a user