Kotlin2Js Gradle plugin implementation

This commit is contained in:
Zoltan Nagy
2014-11-15 23:25:54 +01:00
committed by Zalim Bashorov
parent ec47cb57c5
commit b1723668ce
5 changed files with 373 additions and 97 deletions
@@ -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()
}
@@ -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>
@@ -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"
}
}
@@ -0,0 +1 @@
implementation-class=org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPluginWrapper