From 3c88f761a6bed63aa25ff1829c11581f2cba7fcd Mon Sep 17 00:00:00 2001 From: Lucas Smaira Date: Wed, 6 Jun 2018 11:18:56 +0100 Subject: [PATCH] Introduce tooling model for Android extensions plugin Introduce Gradle models for plugins 'kotlin-android-extensions'. --- .../jetbrains/kotlin/gradle/BaseGradleIT.kt | 4 +- .../gradle/model/KotlinAndroidExtensionIT.kt | 54 +++++++++++++++++++ .../gradle/model/KotlinAndroidExtension.java | 47 ++++++++++++++++ .../gradle/internal/AndroidSubplugin.kt | 7 ++- .../KotlinAndroidExtensionModelBuilder.kt | 31 +++++++++++ .../model/impl/KotlinAndroidExtensionImpl.kt | 39 ++++++++++++++ .../KotlinAndroidExtensionModelBuilderTest.kt | 20 +++++++ .../impl/KotlinAndroidExtensionImplTest.kt | 18 +++++++ 8 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtensionIT.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-model/src/main/java/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtension.java create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilder.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImpl.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilderTest.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImplTest.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index 0565553d8a5..458231117b2 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -284,7 +284,9 @@ abstract class BaseGradleIT { val connection = GradleConnector.newConnector().forProjectDirectory(projectDir).connect() val options = defaultBuildOptions() - val model = connection.action(ModelFetcherBuildAction(modelType)) .withArguments("-Pkotlin_version=" + options.kotlinVersion).run() + val arguments = mutableListOf("-Pkotlin_version=${options.kotlinVersion}") + options.androidGradlePluginVersion?.let { arguments.add("-Pandroid_tools_version=$it") } + val model = connection.action(ModelFetcherBuildAction(modelType)).withArguments(arguments).run() connection.close() return model } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtensionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtensionIT.kt new file mode 100644 index 00000000000..a0bdd623817 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtensionIT.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model + +import org.jetbrains.kotlin.gradle.BaseGradleIT +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNull +import kotlin.test.assertTrue + +class KotlinAndroidExtensionIT : BaseGradleIT() { + + override fun defaultBuildOptions(): BuildOptions { + return super.defaultBuildOptions().copy( + androidGradlePluginVersion = "3.0.0", + androidHome = KotlinTestUtils.findAndroidSdk() + ) + } + + @Test + fun testAndroidExtensionsProject() { + val project = Project("AndroidExtensionsProject") + val androidExtensionModel = project.getModels(KotlinAndroidExtension::class.java).getModel(":app")!! + + assertEquals(1L, androidExtensionModel.modelVersion) + assertEquals("app", androidExtensionModel.name) + assertFalse(androidExtensionModel.isExperimental) + assertEquals("hashMap", androidExtensionModel.defaultCacheImplementation) + } + + @Test + fun testAndroidExtensionsManyVariants() { + val project = Project("AndroidExtensionsManyVariants") + val androidExtensionModel = project.getModels(KotlinAndroidExtension::class.java).getModel(":app")!! + + assertEquals(1L, androidExtensionModel.modelVersion) + assertEquals("app", androidExtensionModel.name) + assertTrue(androidExtensionModel.isExperimental) + assertEquals("hashMap", androidExtensionModel.defaultCacheImplementation) + } + + @Test + fun testNonAndroidExtensionsProjects() { + val project = Project("kotlinProject") + val model = project.getModels(KotlinAndroidExtension::class.java).getModel(":") + + assertNull(model) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-model/src/main/java/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtension.java b/libraries/tools/kotlin-gradle-plugin-model/src/main/java/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtension.java new file mode 100644 index 00000000000..baf34a29418 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-model/src/main/java/org/jetbrains/kotlin/gradle/model/KotlinAndroidExtension.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Entry point for Kotlin Android Extensions models. + * Represents the description of Android only features. Provided by 'kotlin-android-extensions' plugin. + */ +public interface KotlinAndroidExtension { + + /** + * Return a number representing the version of this API. + * Always increasing if changed. + * + * @return the version of this model. + */ + long getModelVersion(); + + /** + * Returns the module (Gradle project) name. + * + * @return the module name. + */ + @NotNull + String getName(); + + /** + * Indicate the use of experimental features. + * + * @return if experimental features are used. + */ + boolean isExperimental(); + + /** + * Return the default cache implementation. + * + * @return the default cache implementation. + */ + @Nullable + String getDefaultCacheImplementation(); +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt index 96ba8e50033..9da70ab4b2e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt @@ -27,15 +27,18 @@ import org.gradle.api.Project import org.gradle.api.UnknownDomainObjectException import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.AbstractCompile +import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry +import org.jetbrains.kotlin.gradle.model.builder.KotlinAndroidExtensionModelBuilder import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.w3c.dom.Document import java.io.File +import javax.inject.Inject import javax.xml.parsers.DocumentBuilderFactory // Use apply plugin: 'kotlin-android-extensions' to enable Android Extensions in an Android project. -class AndroidExtensionsSubpluginIndicator : Plugin { +class AndroidExtensionsSubpluginIndicator @Inject internal constructor(private val registry: ToolingModelBuilderRegistry) : Plugin { override fun apply(project: Project) { val extension = project.extensions.create("androidExtensions", AndroidExtensionsExtension::class.java) @@ -44,6 +47,8 @@ class AndroidExtensionsSubpluginIndicator : Plugin { addAndroidExtensionsRuntimeIfNeeded(project) } } + + registry.register(KotlinAndroidExtensionModelBuilder()) } private fun addAndroidExtensionsRuntimeIfNeeded(project: Project) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilder.kt new file mode 100644 index 00000000000..a955be8ea63 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilder.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model.builder + +import org.gradle.api.Project +import org.gradle.tooling.provider.model.ToolingModelBuilder +import org.jetbrains.kotlin.gradle.internal.AndroidExtensionsExtension +import org.jetbrains.kotlin.gradle.model.KotlinAndroidExtension +import org.jetbrains.kotlin.gradle.model.impl.KotlinAndroidExtensionImpl + +/** + * [ToolingModelBuilder] for [KotlinAndroidExtension] models. + * This model builder is registered for Kapt Gradle sub-plugin. + */ +class KotlinAndroidExtensionModelBuilder : ToolingModelBuilder { + + override fun canBuild(modelName: String): Boolean { + return modelName == KotlinAndroidExtension::class.java.name + } + + override fun buildAll(modelName: String, project: Project): Any? { + if (modelName == KotlinAndroidExtension::class.java.name) { + val extension = project.extensions.getByType(AndroidExtensionsExtension::class.java) + return KotlinAndroidExtensionImpl(project.name, extension.isExperimental, extension.defaultCacheImplementation.optionName) + } + return null + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImpl.kt new file mode 100644 index 00000000000..6efd942bb6e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImpl.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model.impl + +import org.jetbrains.kotlin.gradle.model.KotlinAndroidExtension +import java.io.Serializable + +/** + * Implementation of the [KotlinAndroidExtension] interface. + */ +data class KotlinAndroidExtensionImpl( + private val myName: String, + private val myIsExperimental: Boolean, + private val myDefaultCacheImplementation: String? +) : KotlinAndroidExtension, Serializable { + + override fun getModelVersion(): Long { + return serialVersionUID + } + + override fun getName(): String { + return myName + } + + override fun isExperimental(): Boolean { + return myIsExperimental + } + + override fun getDefaultCacheImplementation(): String? { + return myDefaultCacheImplementation + } + + companion object { + private const val serialVersionUID = 1L + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilderTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilderTest.kt new file mode 100644 index 00000000000..32399f525aa --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinAndroidExtensionModelBuilderTest.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model.builder + +import org.jetbrains.kotlin.gradle.model.KotlinAndroidExtension +import org.junit.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class KotlinAndroidExtensionModelBuilderTest { + @Test + fun testCanBuild() { + val modelBuilder = KotlinAndroidExtensionModelBuilder() + assertTrue(modelBuilder.canBuild(KotlinAndroidExtension::class.java.name)) + assertFalse(modelBuilder.canBuild("wrongModel")) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImplTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImplTest.kt new file mode 100644 index 00000000000..79dccd102dd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/model/impl/KotlinAndroidExtensionImplTest.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.model.impl + +import nl.jqno.equalsverifier.EqualsVerifier +import nl.jqno.equalsverifier.Warning +import org.junit.Test + +class KotlinAndroidExtensionImplTest { + @Test + @Throws(Exception::class) + fun equals() { + EqualsVerifier.forClass(KotlinAndroidExtensionImpl::class.java).suppress(Warning.NULL_FIELDS).verify() + } +} \ No newline at end of file