From 7e22572324471222bfd2f97638ef0e5192de6393 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 20 Feb 2020 21:30:59 +0300 Subject: [PATCH] Wizard: add configuration for Android MPP target --- .../android/expected/android/build.gradle | 4 +- .../android/expected/android/build.gradle.kts | 4 +- .../android/expected/build.gradle | 11 -- .../android/expected/build.gradle.kts | 11 -- .../android/AndroidManifestLibrary.xml.vm | 2 + .../kotlin/tools/projectWizard/Versions.kt | 16 ++ .../ir/buildsystem/BuildSystemPluginIR.kt | 7 +- .../projectWizard/ir/buildsystem/IrsOwner.kt | 3 + .../ir/buildsystem/PluginManagementIR.kt | 42 +++++ .../ir/buildsystem/gradle/AndroidIR.kt | 6 +- .../gradle/SettingsGradleFileIR.kt | 14 +- .../AndroidModuleConfigurator.kt | 158 ++++++++++++++++++ ...AndroidSinglePlatformModuleConfigurator.kt | 137 +++++---------- .../JsModuleConfigurator.kt | 3 +- .../moduleConfigurators/ModuleConfigurator.kt | 14 +- .../ModuleConfiguratorWithTests.kt | 25 ++- .../NativeTargetConfigurator.kt | 3 +- .../moduleConfigurators/TargetConfigurator.kt | 7 - .../moduleConfigurators/configurators.kt | 13 +- .../buildSystem/gradle/GradlePlugin.kt | 10 +- .../plugins/kotlin/ModulesToIRsConverter.kt | 22 ++- 21 files changed, 347 insertions(+), 165 deletions(-) create mode 100644 libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/android/AndroidManifestLibrary.xml.vm create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/PluginManagementIR.kt create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidModuleConfigurator.kt diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle index cbca5618482..b9d710a4ebb 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle @@ -1,6 +1,6 @@ plugins { id 'com.android.application' - id 'kotlin-android' + id 'org.jetbrains.kotlin.android' version '1.3.61' id 'kotlin-android-extensions' } group = 'testGroupId' @@ -13,8 +13,8 @@ repositories { mavenCentral() } dependencies { - implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.core:core-ktx:1.1.0' + implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7' } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle.kts b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle.kts index 93a23a07186..05c3322eb91 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle.kts +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/android/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("com.android.application") - id("kotlin-android") + kotlin("android") version "1.3.61" id("kotlin-android-extensions") } group = "testGroupId" @@ -13,8 +13,8 @@ repositories { mavenCentral() } dependencies { - implementation("androidx.appcompat:appcompat:1.1.0") implementation("androidx.core:core-ktx:1.1.0") + implementation("androidx.appcompat:appcompat:1.1.0") implementation("androidx.constraintlayout:constraintlayout:1.1.3") implementation(kotlin("stdlib-jdk7")) } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle index 06240c5bba0..dafeb336c4d 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle @@ -1,14 +1,3 @@ -buildscript { - repositories { - gradlePluginPortal() - google() - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61' - } -} group = 'testGroupId' version = '1.0-SNAPSHOT' diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle.kts b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle.kts index 41b736e6b26..bba1c3579c5 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle.kts +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/android/expected/build.gradle.kts @@ -1,14 +1,3 @@ -buildscript { - repositories { - gradlePluginPortal() - google() - jcenter() - } - dependencies { - classpath("com.android.tools.build:gradle:3.2.1") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61") - } -} group = "testGroupId" version = "1.0-SNAPSHOT" diff --git a/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/android/AndroidManifestLibrary.xml.vm b/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/android/AndroidManifestLibrary.xml.vm new file mode 100644 index 00000000000..7b03e59b178 --- /dev/null +++ b/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/android/AndroidManifestLibrary.xml.vm @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt new file mode 100644 index 00000000000..bbc58024c1f --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.tools.projectWizard + +import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version + +object Versions { + object GradlePlugins { + val ANDROID = version("3.5.2") + } +} + +private fun version(version: String) = Version.fromString(version) \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildSystemPluginIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildSystemPluginIR.kt index 8f7836a3a33..e5d16b8338a 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildSystemPluginIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildSystemPluginIR.kt @@ -43,10 +43,9 @@ data class KotlinBuildSystemPluginIR( override fun BuildFilePrinter.render() = when (this) { is GradlePrinter -> { - when { - type == Type.android -> call("id") { +"kotlin-android".quotified } - dsl == GradlePrinter.GradleDsl.KOTLIN -> call("kotlin") { +type.toString().quotified } - else -> call("id") { +"org.jetbrains.kotlin.$type".quotified } + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> call("kotlin") { +type.toString().quotified } + GradlePrinter.GradleDsl.GROOVY -> call("id") { +"org.jetbrains.kotlin.$type".quotified } } version?.let { +" version " diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/IrsOwner.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/IrsOwner.kt index 3ddb6120736..ca6711fc284 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/IrsOwner.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/IrsOwner.kt @@ -20,6 +20,9 @@ inline fun IrsOwner.irsOfType(): List = inline fun IrsOwner.irsOfTypeOrNull() = irsOfType().takeIf { it.isNotEmpty() } +inline fun List.irsOfTypeOrNull() = + filterIsInstance().takeIf { it.isNotEmpty() } + inline fun IrsOwner.firstIrOfType() = irs.firstOrNull { ir -> ir is T } as T? diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/PluginManagementIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/PluginManagementIR.kt new file mode 100644 index 00000000000..1aefd171869 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/PluginManagementIR.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.tools.projectWizard.ir.buildsystem + +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.GradleIR +import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter +import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version + +interface PluginManagementIR : GradleIR + +data class AndroidResolutionStrategyIR( + val androidGradlePluginVersion: Version +) : PluginManagementIR, FreeIR { + override fun GradlePrinter.renderGradle() { + sectionCall("resolutionStrategy", needIndent = true) { + sectionCall("eachPlugin", needIndent = true) { + sectionCall( + "if (requested.id.namespace == ${"com.android".quotified} || requested.id.name == ${"kotlin-android-extensions".quotified})", + needIndent = true + ) { + call("useModule", forceBrackets = true) { + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> + +"com.android.tools.build:gradle:${androidGradlePluginVersion}".quotified + GradlePrinter.GradleDsl.GROOVY -> + +"com.android.tools.build:gradle:$androidGradlePluginVersion".quotified + } + } + } + } + } + } +} + +data class PluginManagementRepositoryIR(val repositoryIR: RepositoryIR) : PluginManagementIR { + override fun GradlePrinter.renderGradle() { + repositoryIR.render(this) + } +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/AndroidIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/AndroidIR.kt index 54028690fb6..ac2964b290e 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/AndroidIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/AndroidIR.kt @@ -7,12 +7,14 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.JavaPackage interface AndroidIR : GradleIR //TODO parematrize -data class AndroidConfigIR(val javaPackage: JavaPackage) : AndroidIR, FreeIR { +data class AndroidConfigIR(val javaPackage: JavaPackage?) : AndroidIR, FreeIR { override fun GradlePrinter.renderGradle() { sectionCall("android", needIndent = true) { call("compileSdkVersion") { +"29" }; nlIndented() // TODO dehardcode sectionCall("defaultConfig", needIndent = true) { - assignmentOrCall("applicationId") { +javaPackage.asCodePackage().quotified }; nlIndented() + if (javaPackage != null) { + assignmentOrCall("applicationId") { +javaPackage.asCodePackage().quotified }; nlIndented() + } call("minSdkVersion") { +"24" }; nlIndented() // TODO dehardcode call("targetSdkVersion") { +"29" }; nlIndented() // TODO dehardcode assignmentOrCall("versionCode") { +"1" }; nlIndented() diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/SettingsGradleFileIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/SettingsGradleFileIR.kt index fdfcb5cba3f..ca80a29a974 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/SettingsGradleFileIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/SettingsGradleFileIR.kt @@ -16,15 +16,19 @@ data class SettingsGradleFileIR( override fun withReplacedIrs(irs: List): SettingsGradleFileIR = copy(irs = irs) override fun GradlePrinter.renderGradle() { - val repositories = irsOfType() - if (repositories.isNotEmpty()) { + irsOfTypeOrNull()?.let { pluginManagementIrs -> sectionCall("pluginManagement", needIndent = true) { - sectionCall("repositories") { - repositories.listNl() + pluginManagementIrs.irsOfTypeOrNull()?.let { repositories -> + sectionCall("repositories") { + repositories.listNl() + } } + nl() + freeIrs().listNl() } - nl(lineBreaks = 2) } + nl() + +"rootProject.name = "; +projectName.quotified nl(lineBreaks = 2) if (subProjects.isNotEmpty()) { diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidModuleConfigurator.kt new file mode 100644 index 00000000000..29fdfd0858b --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidModuleConfigurator.kt @@ -0,0 +1,158 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.tools.projectWizard.moduleConfigurators + +import org.jetbrains.kotlin.tools.projectWizard.Versions +import org.jetbrains.kotlin.tools.projectWizard.core.* +import org.jetbrains.kotlin.tools.projectWizard.core.entity.PluginSettingReference +import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType +import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.AndroidConfigIR +import org.jetbrains.kotlin.tools.projectWizard.plugins.AndroidPlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleConfigurationData +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module +import org.jetbrains.kotlin.tools.projectWizard.settings.javaPackage +import org.jetbrains.kotlin.tools.projectWizard.core.entity.ModuleConfiguratorSetting +import org.jetbrains.kotlin.tools.projectWizard.core.service.kotlinVersionKind +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* +import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact +import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType +import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin +import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem +import org.jetbrains.kotlin.tools.projectWizard.settings.JavaPackage +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Repository +import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor +import java.nio.file.Path + +interface AndroidModuleConfigurator : ModuleConfigurator, + ModuleConfiguratorWithSettings, + ModuleConfiguratorWithModuleType, + GradleModuleConfigurator { + + override val moduleType: ModuleType + get() = ModuleType.jvm + override val greyText: String + get() = "Requires Android SDK" + + override fun getPluginSettings(): List>> = + listOf(AndroidPlugin::androidSdkPath.reference) + + override fun createBuildFileIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ) = buildList { + +GradleOnlyPluginByNameIR(readingContext.createAndroidPlugin(module).pluginName) + + +GradleOnlyPluginByNameIR("kotlin-android-extensions") + +AndroidConfigIR( + when (readingContext.createAndroidPlugin(module)) { + AndroidGradlePlugin.APPLICATION -> module.javaPackage(configurationData.pomIr) + AndroidGradlePlugin.LIBRARY -> null + } + ) + +createRepositories(configurationData.kotlinVersion).map(::RepositoryIR) + } + + fun ReadingContext.createAndroidPlugin(module: Module): AndroidGradlePlugin + + override fun ReadingContext.createSettingsGradleIRs(module: Module) = buildList { + +createRepositories(KotlinPlugin::version.propertyValue).map { PluginManagementRepositoryIR(RepositoryIR(it)) } + +AndroidResolutionStrategyIR(Versions.GradlePlugins.ANDROID) + } + + override fun createModuleIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ): List = + buildList { + +ArtifactBasedLibraryDependencyIR( + MavenArtifact(DefaultRepository.GOOGLE, "androidx.core", "core-ktx"), + version = Version.fromString("1.1.0"), + dependencyType = DependencyType.MAIN + ) + } + + + override fun createStdlibType(configurationData: ModuleConfigurationData, module: Module): StdlibType? = + StdlibType.StdlibJdk7 + + object FileTemplateDescriptors { + val activityMainXml = FileTemplateDescriptor( + "android/activity_main.xml.vm", + "src" / "main" / "res" / "layout" / "activity_main.xml" + ) + + val androidManifestXml = FileTemplateDescriptor( + "android/AndroidManifest.xml.vm", + "src" / "main" / "AndroidManifest.xml" + ) + + val androidanifestForLibraryXml = FileTemplateDescriptor( + "android/AndroidManifestLibrary.xml.vm", + "src" / "main" / "AndroidManifest.xml" + ) + + fun mainActivityKt(javaPackage: JavaPackage) = FileTemplateDescriptor( + "android/MainActivity.kt.vm", + "src" / "main" / "java" / javaPackage.asPath() / "MainActivity.kt" + ) + } + + companion object { + fun createRepositories(kotlinVersion: Version) = buildList { + +DefaultRepository.GRADLE_PLUGIN_PORTAL + +DefaultRepository.GOOGLE + +DefaultRepository.JCENTER + addIfNotNull(kotlinVersion.kotlinVersionKind.repository) + } + } +} + +object AndroidTargetConfigurator : TargetConfigurator, + SimpleTargetConfigurator, + AndroidModuleConfigurator, + SingleCoexistenceTargetConfigurator, + ModuleConfiguratorSettings() { + override val moduleSubType = ModuleSubType.android + override val moduleType = ModuleType.jvm + + override fun ReadingContext.createAndroidPlugin(module: Module): AndroidGradlePlugin = + withSettingsOf(module) { androidPlugin.reference.settingValue } + + override fun getConfiguratorSettings() = buildList> { + +super.getConfiguratorSettings() + +androidPlugin + } + + override fun WritingContext.runArbitraryTask( + configurationData: ModuleConfigurationData, + module: Module, + modulePath: Path + ): TaskResult = computeM { + val javaPackage = module.javaPackage(configurationData.pomIr) + val settings = mapOf("package" to javaPackage) + TemplatesPlugin::addFileTemplates.execute( + listOf( + FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidanifestForLibraryXml, modulePath, settings) + ) + ) + } + + val androidPlugin by enumSetting("Android Library", neededAtPhase = GenerationPhase.PROJECT_GENERATION) +} + +enum class AndroidGradlePlugin(override val text: String, val pluginName: String) : DisplayableSettingItem { + APPLICATION("Android Application", "com.android.application"), + LIBRARY("Android Library", "com.android.library") +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidSinglePlatformModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidSinglePlatformModuleConfigurator.kt index 614a1c1fd53..1a3e4976b20 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidSinglePlatformModuleConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/AndroidSinglePlatformModuleConfigurator.kt @@ -1,75 +1,62 @@ package org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators import org.jetbrains.kotlin.tools.projectWizard.core.* -import org.jetbrains.kotlin.tools.projectWizard.core.entity.PluginSettingReference -import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType -import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference -import org.jetbrains.kotlin.tools.projectWizard.core.service.kotlinVersionKind import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.AndroidConfigIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScriptDependencyIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScriptRepositoryIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.RawGradleIR import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact -import org.jetbrains.kotlin.tools.projectWizard.plugins.AndroidPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleConfigurationData -import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin -import org.jetbrains.kotlin.tools.projectWizard.settings.JavaPackage import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module -import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Repository import org.jetbrains.kotlin.tools.projectWizard.settings.javaPackage import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate -import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor import java.nio.file.Path -object AndroidSinglePlatformModuleConfigurator : ModuleConfiguratorWithSettings, +object AndroidSinglePlatformModuleConfigurator : SinglePlatformModuleConfigurator, - AndroidModuleConfigurator, - ModuleConfiguratorWithModuleType { - override val moduleType = ModuleType.jvm + AndroidModuleConfigurator { override val id = "android" override val suggestedModuleName = "android" override val text = "Android" - override val greyText = "Requires Android SDK" - private fun createRepositories(configurationData: ModuleConfigurationData) = buildList { - +DefaultRepository.GRADLE_PLUGIN_PORTAL - +DefaultRepository.GOOGLE - +DefaultRepository.JCENTER - addIfNotNull(configurationData.kotlinVersion.kotlinVersionKind.repository) - } - - - override fun ReadingContext.createBuildFileIRs( + override fun createBuildFileIRs( + readingContext: ReadingContext, configurationData: ModuleConfigurationData, module: Module - ) = - buildList { - +GradleOnlyPluginByNameIR("com.android.application") + ) = buildList { + +super.createBuildFileIRs(readingContext, configurationData, module) - // it is explicitly here instead of by `createKotlinPluginIR` as it should be after `com.android.application` - +KotlinBuildSystemPluginIR( - KotlinBuildSystemPluginIR.Type.android, - version = null // Version is already present in the parent buildfile - ) - +GradleOnlyPluginByNameIR("kotlin-android-extensions") - +AndroidConfigIR(module.javaPackage(configurationData.pomIr)) - +createRepositories(configurationData).map(::RepositoryIR) - } + // it is explicitly here instead of by `createKotlinPluginIR` as it should be after `com.android.application` + +KotlinBuildSystemPluginIR( + KotlinBuildSystemPluginIR.Type.android, + version = configurationData.kotlinVersion + ) + }.sortedBy { ir: BuildSystemIR -> + if (ir is GradleOnlyPluginByNameIR) { + // TODO implement proper sort on irs + // But for now kotlin-android-extensions should be after Android kotlin plugin + if (ir.pluginId == "kotlin-android-extensions") 1 else 0 + } else 0 + } - override fun createRootBuildFileIrs(configurationData: ModuleConfigurationData) = buildList { - +createRepositories(configurationData).map { BuildScriptRepositoryIR(RepositoryIR(it)) } - +listOf( - RawGradleIR { call("classpath") { +"com.android.tools.build:gradle:3.2.1".quotified } }, - RawGradleIR { - call("classpath") { - +"org.jetbrains.kotlin:kotlin-gradle-plugin:${configurationData.kotlinVersion}".quotified - } - } - ).map(::BuildScriptDependencyIR) + override fun createModuleIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ) = buildList { + +super.createModuleIRs(readingContext, configurationData, module) + + +ArtifactBasedLibraryDependencyIR( + MavenArtifact(DefaultRepository.GOOGLE, "androidx.appcompat", "appcompat"), + version = Version.fromString("1.1.0"), + dependencyType = DependencyType.MAIN + ) + + +ArtifactBasedLibraryDependencyIR( + MavenArtifact(DefaultRepository.GOOGLE, "androidx.constraintlayout", "constraintlayout"), + version = Version.fromString("1.1.3"), + dependencyType = DependencyType.MAIN + ) } override fun WritingContext.runArbitraryTask( @@ -78,56 +65,16 @@ object AndroidSinglePlatformModuleConfigurator : ModuleConfiguratorWithSettings, modulePath: Path ): TaskResult = computeM { val javaPackage = module.javaPackage(configurationData.pomIr) + val settings = mapOf("package" to javaPackage) TemplatesPlugin::addFileTemplates.execute( listOf( - FileTemplate(FileTemplateDescriptors.activityMainXml, modulePath, "package" to javaPackage), - FileTemplate(FileTemplateDescriptors.androidManifestXml, modulePath, "package" to javaPackage), - FileTemplate(FileTemplateDescriptors.mainActivityKt(javaPackage), modulePath, "package" to javaPackage) + FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.activityMainXml, modulePath, settings), + FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidManifestXml, modulePath, settings), + FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.mainActivityKt(javaPackage), modulePath, settings) ) ) } - override fun ReadingContext.createModuleIRs(configurationData: ModuleConfigurationData, module: Module): List = - buildList { - +ArtifactBasedLibraryDependencyIR( - MavenArtifact(DefaultRepository.GOOGLE, "androidx.appcompat", "appcompat"), - version = Version.fromString("1.1.0"), - dependencyType = DependencyType.MAIN - ) - - +ArtifactBasedLibraryDependencyIR( - MavenArtifact(DefaultRepository.GOOGLE, "androidx.core", "core-ktx"), - version = Version.fromString("1.1.0"), - dependencyType = DependencyType.MAIN - ) - - +ArtifactBasedLibraryDependencyIR( - MavenArtifact(DefaultRepository.GOOGLE, "androidx.constraintlayout", "constraintlayout"), - version = Version.fromString("1.1.3"), - dependencyType = DependencyType.MAIN - ) - } - - override fun createStdlibType(configurationData: ModuleConfigurationData, module: Module): StdlibType? = - StdlibType.StdlibJdk7 - - override fun getPluginSettings(): List>> = - listOf(AndroidPlugin::androidSdkPath.reference) - - private object FileTemplateDescriptors { - val activityMainXml = FileTemplateDescriptor( - "android/activity_main.xml.vm", - "src" / "main" / "res" / "layout" / "activity_main.xml" - ) - - val androidManifestXml = FileTemplateDescriptor( - "android/AndroidManifest.xml.vm", - "src" / "main" / "AndroidManifest.xml" - ) - - fun mainActivityKt(javaPackage: JavaPackage) = FileTemplateDescriptor( - "android/MainActivity.kt.vm", - "src" / "main" / "java" / javaPackage.asPath() / "MainActivity.kt" - ) - } + override fun ReadingContext.createAndroidPlugin(module: Module): AndroidGradlePlugin = + AndroidGradlePlugin.APPLICATION } \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt index c58bf78a062..378eb801550 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt @@ -35,7 +35,8 @@ object JsSingleplatformModuleConfigurator : JSConfigurator, ModuleConfiguratorWi version = configurationData.kotlinVersion ) - override fun ReadingContext.createBuildFileIRs( + override fun createBuildFileIRs( + readingContext: ReadingContext, configurationData: ModuleConfigurationData, module: Module ): List = buildList { diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfigurator.kt index dfb04acc9fd..5a2f8e6696d 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfigurator.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version import java.nio.file.Path import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass sealed class ModuleCondifuratorSettingsEnvironment { @@ -205,13 +204,18 @@ interface ModuleConfigurator : DisplayableSettingItem, EntitiesOwnerDescriptor { val suggestedModuleName: String? get() = null val canContainSubModules: Boolean get() = false - fun ReadingContext.createBuildFileIRs( + fun createBuildFileIRs( + readingContext: ReadingContext, configurationData: ModuleConfigurationData, module: Module ): List = emptyList() - fun ReadingContext.createModuleIRs(configurationData: ModuleConfigurationData, module: Module): List = + fun createModuleIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ): List = emptyList() fun createStdlibType(configurationData: ModuleConfigurationData, module: Module): StdlibType? = @@ -266,4 +270,8 @@ interface ModuleConfigurator : DisplayableSettingItem, EntitiesOwnerDescriptor { configurator } } +} + +interface GradleModuleConfigurator : ModuleConfigurator { + fun ReadingContext.createSettingsGradleIRs(module: Module): List = emptyList() } \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfiguratorWithTests.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfiguratorWithTests.kt index ae2a02fc958..ce01357a5ec 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfiguratorWithTests.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/ModuleConfiguratorWithTests.kt @@ -39,19 +39,26 @@ interface ModuleConfiguratorWithTests : ModuleConfiguratorWithSettings { fun defaultTestFramework(): KotlinTestFramework - override fun ReadingContext.createModuleIRs(configurationData: ModuleConfigurationData, module: Module): List = + override fun createModuleIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ): List = withSettingsOf(module) { - testFramework.reference.settingValue.dependencyNames.map { dependencyName -> - KotlinArbitraryDependencyIR( - dependencyName, - isInMppModule = module.kind - .let { it == ModuleKind.multiplatform || it == ModuleKind.target }, - version = KotlinPlugin::version.propertyValue, - dependencyType = DependencyType.TEST - ) + with(readingContext) { + testFramework.reference.settingValue.dependencyNames.map { dependencyName -> + KotlinArbitraryDependencyIR( + dependencyName, + isInMppModule = module.kind + .let { it == ModuleKind.multiplatform || it == ModuleKind.target }, + version = KotlinPlugin::version.propertyValue, + dependencyType = DependencyType.TEST + ) + } } } + override fun getConfiguratorSettings(): List> = listOf(testFramework) } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/NativeTargetConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/NativeTargetConfigurator.kt index 381444ded03..38dc2e236b7 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/NativeTargetConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/NativeTargetConfigurator.kt @@ -74,7 +74,8 @@ object NativeForCurrentSystemTarget : NativeTargetConfigurator, SingleCoexistenc } } - override fun ReadingContext.createBuildFileIRs( + override fun createBuildFileIRs( + readingContext: ReadingContext, configurationData: ModuleConfigurationData, module: Module ): List = buildList { diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/TargetConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/TargetConfigurator.kt index 7016ab1a65c..30221671401 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/TargetConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/TargetConfigurator.kt @@ -123,10 +123,3 @@ object JvmTargetConfigurator : JvmModuleConfigurator, } } } - -object AndroidTargetConfigurator : TargetConfigurator, - SimpleTargetConfigurator, - AndroidModuleConfigurator, - SingleCoexistenceTargetConfigurator { - override val moduleSubType = ModuleSubType.android -} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/configurators.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/configurators.kt index bf0f3864d2a..b7bcee3a696 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/configurators.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/configurators.kt @@ -43,7 +43,6 @@ enum class TargetJvmVersion(val value: String) : DisplayableSettingItem { get() = value } -interface AndroidModuleConfigurator : ModuleConfigurator interface ModuleConfiguratorWithModuleType : ModuleConfigurator { val moduleType: ModuleType @@ -89,11 +88,19 @@ object JvmSinglePlatformModuleConfigurator : JvmModuleConfigurator, ) - override fun ReadingContext.createBuildFileIRs(configurationData: ModuleConfigurationData, module: Module): List = + override fun createBuildFileIRs( + readingContext: ReadingContext, + configurationData: ModuleConfigurationData, + module: Module + ): List = buildList { +GradleImportIR("org.jetbrains.kotlin.gradle.tasks.KotlinCompile") - val targetVersionValue = withSettingsOf(module) { JvmModuleConfigurator.targetJvmVersion.reference.settingValue.value } + val targetVersionValue = withSettingsOf(module) { + with(readingContext) { + JvmModuleConfigurator.targetJvmVersion.reference.settingValue.value + } + } when { configurationData.buildSystemType.isGradle -> { +GradleConfigureTaskIR( diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/buildSystem/gradle/GradlePlugin.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/buildSystem/gradle/GradlePlugin.kt index 83807bfad5e..6b962143ef3 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/buildSystem/gradle/GradlePlugin.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/buildSystem/gradle/GradlePlugin.kt @@ -3,6 +3,8 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.PluginManagementRepositoryIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.RepositoryIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.SettingsGradleFileIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.render @@ -36,6 +38,8 @@ abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) { val gradleProperties by listProperty>() + val settingsGradleFileIRs by listProperty() + val createGradlePropertiesFile by pipelineTask(GenerationPhase.PROJECT_GENERATION) { runAfter(KotlinPlugin::createModules) runBefore(TemplatesPlugin::renderFileTemplates) @@ -105,6 +109,7 @@ abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) { val createSettingsFileTask by pipelineTask(GenerationPhase.PROJECT_GENERATION) { + runAfter(KotlinPlugin::createModules) runAfter(KotlinPlugin::createPluginRepositories) isAvailable = isGradle withAction { @@ -115,11 +120,12 @@ abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) { if (isNotEmpty()) { +RepositoryIR(DefaultRepository.MAVEN_CENTRAL) } - } + }.map(::PluginManagementRepositoryIR) + val settingsGradleIR = SettingsGradleFileIR( StructurePlugin::name.settingValue, allModulesPaths.map { path -> path.joinToString(separator = "") { ":$it" } }, - repositories + repositories + GradlePlugin::settingsGradleFileIRs.propertyValue ) val buildFileText = createBuildFile().printBuildFile { settingsGradleIR.render(this) } service().createFile( diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModulesToIRsConverter.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModulesToIRsConverter.kt index 7fba92ae341..4641326354f 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModulesToIRsConverter.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModulesToIRsConverter.kt @@ -3,8 +3,10 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.AndroidSinglePlatformModuleConfigurator +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.GradleModuleConfigurator import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.TargetConfigurator import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType +import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle.GradlePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version @@ -102,7 +104,7 @@ class ModulesToIRsConverter( +module.sourcesets.flatMap { sourceset -> sourceset.dependencies.map { it.toIR(sourceset.sourcesetType.toDependencyType()) } } - with(configurator) { +createModuleIRs(data, module) } + with(configurator) { +createModuleIRs(this@createSinglePlatformModule, data, module) } addIfNotNull( configurator.createStdlibType(data, module)?.let { stdlibType -> KotlinStdlibDependencyIR( @@ -160,7 +162,7 @@ class ModulesToIRsConverter( } val targetModuleIrs = module.subModules.map { target -> - createTargetSourceset(target, modulePath) + createTargetModule(target, modulePath) } return BuildFileIR( @@ -179,7 +181,8 @@ class ModulesToIRsConverter( ).asSingletonList().asSuccess() } - private fun ReadingContext.createTargetSourceset(target: Module, modulePath: Path): MultiplatformModuleIR { + private fun ReadingContext.createTargetModule(target: Module, modulePath: Path): MultiplatformModuleIR { + data.writingContext.mutateProjectStructureByModuleConfigurator(target, modulePath) val sourcesetss = target.sourcesets.map { sourceset -> val sourcesetName = target.name + sourceset.sourcesetType.name.capitalize() val sourcesetIrs = buildList { @@ -208,7 +211,7 @@ class ModulesToIRsConverter( return MultiplatformModuleIR( target.name, modulePath, - with(target.configurator) { createModuleIRs(data, target) }, + with(target.configurator) { createModuleIRs(this@createTargetModule, data, target) }, target.template, target, sourcesetss @@ -219,8 +222,13 @@ class ModulesToIRsConverter( module: Module, modulePath: Path ): TaskResult = with(module.configurator) { - rootBuildFileIrs += createRootBuildFileIrs(data) - runArbitraryTask(data, module, modulePath) + compute { + rootBuildFileIrs += createRootBuildFileIrs(data) + runArbitraryTask(data, module, modulePath).ensure() + if (this@with is GradleModuleConfigurator) { + GradlePlugin::settingsGradleFileIRs.addValues(createSettingsGradleIRs(module)).ensure() + } + } } private fun ReadingContext.createBuildFileIRs( @@ -239,7 +247,7 @@ class ModulesToIRsConverter( } } addIfNotNull(kotlinPlugin) - +with(module.configurator) { createBuildFileIRs(data, module) } + +with(module.configurator) { createBuildFileIRs(this@createBuildFileIRs, data, module) } } private fun SourcesetDependency.toIR(type: DependencyType): DependencyIR = with(data) {