diff --git a/build.xml b/build.xml index 5b4cb3db4df..31c72ab8991 100644 --- a/build.xml +++ b/build.xml @@ -568,6 +568,10 @@ public protected *; } + -keepclassmembers class com.intellij.openapi.vfs.VirtualFile { + public InputStream getInputStream(); + } + -keep class jet.** { public protected *; } diff --git a/libraries/pom.xml b/libraries/pom.xml index 8de54ae3fdd..d2cb17df171 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -84,6 +84,7 @@ tools/kotlin-js-library tools/kotlin-gradle-plugin tools/kotlin-gradle-plugin-core + tools/kotlin-gradle-plugin-api tools/kotlin-android-compiler-plugin tools/kotlin-maven-plugin tools/kotlin-maven-plugin-test diff --git a/libraries/tools/kotlin-android-compiler-plugin/pom.xml b/libraries/tools/kotlin-android-compiler-plugin/pom.xml index e5b04dde929..fadf54595f8 100644 --- a/libraries/tools/kotlin-android-compiler-plugin/pom.xml +++ b/libraries/tools/kotlin-android-compiler-plugin/pom.xml @@ -17,7 +17,7 @@ kotlin-android-compiler-plugin - pom + jar Android compiler plugin for Kotlin @@ -26,40 +26,95 @@ org.jetbrains.kotlin kotlin-stdlib ${project.version} + provided org.jetbrains.kotlin - kotlin-gradle-plugin-core + kotlin-gradle-plugin-api ${project.version} provided + + org.jetbrains.kotlin + gradle-api + 1.6 + provided + + + com.android.tools.build + gradle + 0.4.2 + provided + + ${project.basedir}/src/main/kotlin + + + + ${project.basedir}/src/main/resources + true + + + - org.codehaus.mojo - build-helper-maven-plugin + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + ${basedir}/kotlinAnnotation + + + + + + compile + compile + compile + + + ${project.basedir}/src/main/kotlin + + + + + + test-compile + test-compile + test-compile + + + + + org.apache.maven.plugins + maven-antrun-plugin 1.7 - attach-artifacts + prepare compile - - attach-artifact - - - - ${kotlin-sdk}/lib/android-compiler-plugin.jar - jar - - + + + + + run + + + + + jetbrains-utils + http://repository.jetbrains.com/utils + + diff --git a/libraries/tools/kotlin-android-compiler-plugin/src/main/kotlin/org/jetbrains/kotlin/android/AndroidSubplugin.kt b/libraries/tools/kotlin-android-compiler-plugin/src/main/kotlin/org/jetbrains/kotlin/android/AndroidSubplugin.kt new file mode 100644 index 00000000000..eebf2988df8 --- /dev/null +++ b/libraries/tools/kotlin-android-compiler-plugin/src/main/kotlin/org/jetbrains/kotlin/android/AndroidSubplugin.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.android + +import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin +import org.gradle.api +import com.android.build.gradle.BaseExtension +import java.io.File +import org.gradle.api.tasks.compile.AbstractCompile +import org.jetbrains.kotlin.gradle.plugin.SubpluginOption + +public class AndroidSubplugin : KotlinGradleSubplugin { + + override fun getExtraArguments(project: api.Project, task: AbstractCompile): List? { + val androidExtension = project.getExtensions().getByName("android") as? BaseExtension + + if (androidExtension == null) return null + + val sourceSets = androidExtension.getSourceSets() + val mainSourceSet = sourceSets.getByName("main") + + val resourceDir = mainSourceSet.getRes().getSrcDirs().firstOrNull() + val manifestFile = mainSourceSet.getManifest().getSrcFile() + + if (resourceDir != null) { + val layoutDir = File(resourceDir, "layout") + task.source(layoutDir) + return listOf( + SubpluginOption("androidRes", layoutDir.getAbsolutePath()), + SubpluginOption("androidManifest", manifestFile.getAbsolutePath()) + ) + } + + return null + } + + override fun getPluginName(): String { + return "org.jetbrains.kotlin.android" + } + + override fun getGroupName(): String { + return "org.jetbrains.kotlin" + } + + override fun getArtifactName(): String { + return "kotlin-android-compiler-plugin" + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-android-compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin b/libraries/tools/kotlin-android-compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin new file mode 100644 index 00000000000..3237be5f789 --- /dev/null +++ b/libraries/tools/kotlin-android-compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin @@ -0,0 +1 @@ +org.jetbrains.kotlin.android.AndroidSubplugin \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-api/pom.xml b/libraries/tools/kotlin-gradle-plugin-api/pom.xml new file mode 100644 index 00000000000..d0332e5495f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-api/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + 1.4.1 + 3.0.4 + + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + kotlin-gradle-plugin-api + jar + + Gradle plugin API for Kotlin + + + + jetbrains-utils + http://repository.jetbrains.com/utils + + + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + org.jetbrains.kotlin + gradle-api + 1.6 + provided + + + com.android.tools.build + gradle + 0.4.2 + provided + + + + + ${project.basedir}/src/main/kotlin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + ${basedir}/kotlinAnnotation + + + + + + compile + compile + compile + + + + test-compile + test-compile + test-compile + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt new file mode 100644 index 00000000000..971b4a75215 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.Project +import org.gradle.api.tasks.compile.AbstractCompile + +public class SubpluginOption(val key: String, val value: String) + +public trait KotlinGradleSubplugin { + public fun getExtraArguments(project: Project, task: AbstractCompile): List? + public fun getPluginName(): String + public fun getGroupName(): String + public fun getArtifactName(): String +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/pom.xml b/libraries/tools/kotlin-gradle-plugin-core/pom.xml index b95f9a02538..26a86bf4dab 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/pom.xml @@ -25,6 +25,12 @@ commons-io 2.4 + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ${project.version} + provided + commons-lang commons-lang diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 26a02b367f8..362a296cda9 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -46,8 +46,8 @@ abstract class AbstractKotlinCompile() : AbstractCo private val logger = Logging.getLogger(this.javaClass) override fun getLogger() = logger - public var resPath: String = "" - public var manifestPath: String = "" + var compilerPluginClasspaths: Array = array() + var compilerPluginArguments: Array = array() // override setSource to track source directory sets override fun setSource(source: Any?) { @@ -97,10 +97,14 @@ abstract class AbstractKotlinCompile() : AbstractCo 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 = getSource().filter { it.isKotlinFile() } - private fun getKotlinSources(): List = getSource().filter{ isKotlin(it) } + private fun File.isKotlinFile(): Boolean { + return when (FilenameUtils.getExtension(getName()).toLowerCase()) { + "kt", "kts" -> true + else -> false + } + } private fun populateCommonArgs(args: T, sources: List) { args.freeArgs = sources.map { it.getAbsolutePath() } @@ -131,8 +135,8 @@ public open class KotlinCompile() : AbstractKotlinCompile() override fun populateTargetSpecificArgs(args: K2JVMCompilerArguments) { - args.pluginClasspaths = kotlinOptions.pluginClasspaths - args.pluginOptions = kotlinOptions.pluginOptions + args.pluginClasspaths = compilerPluginClasspaths + args.pluginOptions = compilerPluginArguments if (StringUtils.isEmpty(kotlinOptions.classpath)) { val existingClasspathEntries = getClasspath().filter({ it != null && it.exists() }) @@ -161,11 +165,13 @@ public open class KotlinCompile() : AbstractKotlinCompile = getSource() - .filter { isJava(it) } + .filter { it.isJavaFile() } .map { findSrcDirRoot(it) } .filterNotNull() .toSet() + private fun File.isJavaFile() = extension.equalsIgnoreCase(JavaFileType.INSTANCE.getDefaultExtension()) + override fun afterCompileHook(args: K2JVMCompilerArguments) { getLogger().debug("Copying resulting files to classes") diff --git a/libraries/tools/kotlin-gradle-plugin/pom.xml b/libraries/tools/kotlin-gradle-plugin/pom.xml index f4229d8f4b3..836f7855f00 100644 --- a/libraries/tools/kotlin-gradle-plugin/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin/pom.xml @@ -49,6 +49,11 @@ ${project.version} test + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ${project.version} + diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 14312dca5ac..f53f8cce516 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -39,6 +39,8 @@ import groovy.lang.Closure import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.compiler.plugin.CliOption import org.jetbrains.kotlin.android.AndroidCommandLineProcessor +import java.util.ServiceLoader +import org.jetbrains.kotlin.compiler.plugin.getPluginOptionString val DEFAULT_ANNOTATIONS = "org.jebrains.kotlin.gradle.defaultAnnotations" @@ -144,6 +146,8 @@ class Kotlin2JvmSourceSetProcessor( } } } + + loadSubplugins(project).addSubpluginArguments(project, kotlinTask) } } @@ -304,10 +308,6 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler, project).resolveKotlinPluginDependency("kotlin-android-sdk-annotations")) } - private fun makePluginOption(option: CliOption, value: String): String { - return "plugin:${AndroidCommandLineProcessor.ANDROID_COMPILER_PLUGIN_ID}:${option.name}=$value" - } - private fun processVariants(variants: DefaultDomainObjectSet, project: Project, androidExt: BaseExtension): Unit { val logger = project.getLogger() val kotlinOptions = getExtension(androidExt, "kotlinOptions") @@ -320,6 +320,8 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t sourceSets.getByName("androidTest") } + val subpluginEnvironment = loadSubplugins(project) + for (variant in variants) { if (variant is LibraryVariant || variant is ApkVariant) { val buildTypeSourceSetName = AndroidGradleWrapper.getVariantName(variant) @@ -330,17 +332,6 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t val javaTask = variant.getJavaCompile()!! val variantName = variant.getName() - val resourceDir = AndroidGradleWrapper.getResourceDirs(mainSourceSet).firstOrNull() - val manifestFile = AndroidGradleWrapper.getManifestFile(mainSourceSet) - - if (resourceDir != null) { - val layoutDir = File(resourceDir, "layout") - kotlinOptions.pluginOptions = array( - makePluginOption("androidRes", layoutDir.getAbsolutePath()), - makePluginOption("androidManifest", manifestFile.getAbsolutePath()) - ) - } - val kotlinTaskName = "compile${variantName.capitalize()}Kotlin" val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName) if (kotlinOptions != null) { @@ -400,6 +391,8 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t } } + subpluginEnvironment.addSubpluginArguments(project, kotlinTask) + kotlinTask doFirst { var plugin = project.getPlugins().findPlugin("android") if (null == plugin) { @@ -429,9 +422,57 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t val result = (obj as HasConvention).getConvention().getPlugins()[extensionName] return result as T } - } +private fun loadSubplugins(project: Project): SubpluginEnvironment { + try { + val subplugins = ServiceLoader.load( + javaClass(), project.getBuildscript().getClassLoader()).toList() + val subpluginDependencyNames = + subplugins.mapTo(hashSetOf()) { it.getGroupName() + ":" + it.getArtifactName() } + + val classpath = project.getBuildscript().getConfigurations().getByName("classpath") + val subpluginClasspaths = hashMapOf>() + + for (subplugin in subplugins) { + val files = classpath.getDependencies() + .filter { subpluginDependencyNames.contains(it.getGroup() + ":" + it.getName()) } + .flatMap { classpath.files(it).map { it.getAbsolutePath() } } + subpluginClasspaths.put(subplugin, files) + } + + return SubpluginEnvironment(subpluginClasspaths, subplugins) + } catch (e: NoClassDefFoundError) { + // Skip plugin loading if KotlinGradleSubplugin is not defined. + // It is true now for tests in kotlin-gradle-plugin-core. + return SubpluginEnvironment(mapOf(), listOf()) + } +} + +private class SubpluginEnvironment( + val subpluginClasspaths: Map>, + val subplugins: List +) { + + fun addSubpluginArguments(project: Project, compileTask: KotlinCompile) { + val realPluginClasspaths = arrayListOf() + val pluginArguments = arrayListOf() + + subplugins.forEach { subplugin -> + val args = subplugin.getExtraArguments(project, compileTask) + if (args != null) { + realPluginClasspaths.addAll(subpluginClasspaths[subplugin]) + for (arg in args) { + val option = getPluginOptionString(subplugin.getPluginName(), arg.key, arg.value) + pluginArguments.add(option) + } + } + } + + compileTask.compilerPluginClasspaths = realPluginClasspaths.copyToArray() + compileTask.compilerPluginArguments = pluginArguments.copyToArray() + } +} open class GradleUtils(val scriptHandler: ScriptHandler, val project: ProjectInternal) { public fun resolveDependencies(vararg coordinates: String): Collection { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/AndroidGradleWrapper.groovy b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/AndroidGradleWrapper.groovy index 94a93f3c115..6d061483fff 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/AndroidGradleWrapper.groovy +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/AndroidGradleWrapper.groovy @@ -46,16 +46,6 @@ class AndroidGradleWrapper { return androidSourceSet.getJava().getSrcDirs() } - @NotNull - static def Set getResourceDirs(Object androidSourceSet) { - return androidSourceSet.getRes().getSrcDirs() - } - - @NotNull - static def File getManifestFile(Object androidSourceSet) { - return androidSourceSet.getManifest().getSrcFile() - } - @NotNull static def List getProductFlavorsNames(ApkVariant variant) { return variant.getProductFlavors().iterator().collect { it.getName() }