From e98b0782c16acf7e731eb7659b70500452717572 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 23 Mar 2020 17:11:09 +0300 Subject: [PATCH] Wizard: add packForXCodeTaskGeneration --- .../tools/projectWizard/core/TaskResult.kt | 3 + .../kotlin/tools/projectWizard/core/errors.kt | 4 +- .../ir/buildsystem/BuildFileIR.kt | 2 + .../ir/buildsystem/gradle/GradleIR.kt | 22 ++++++- .../ir/buildsystem/gradle/GradleTaskIR.kt | 23 +++++++ .../plugins/kotlin/ModuleType.kt | 4 ++ .../plugins/kotlin/ModulesToIRsConverter.kt | 24 ++++++- .../settings/buildsystem/ModuleDependency.kt | 66 +++++++++++++++++++ 8 files changed, 141 insertions(+), 7 deletions(-) diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/TaskResult.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/TaskResult.kt index b24332225d5..39f1e964280 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/TaskResult.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/TaskResult.kt @@ -52,6 +52,9 @@ inline fun TaskResult.mappendM( infix fun TaskResult<*>.andThen(other: TaskResult): TaskResult = mappendM(other) { _, _ -> other } +infix fun TaskResult.andThenIgnoring(other: TaskResult): TaskResult = + mappendM(other) { _, _ -> this } + operator fun TaskResult>.plus(other: TaskResult>): TaskResult = mappend(other) { _, _ -> Unit } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/errors.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/errors.kt index ddcc5fd41bc..f8a4a5e8858 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/errors.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/errors.kt @@ -58,7 +58,7 @@ data class ValidationError(val validationMessage: String) : Error() { data class ProjectImportingError(override val message: String) : Error() -data class InvalidModuleDependencyError(val from: Module, val to: Module) : Error() { +data class InvalidModuleDependencyError(val from: Module, val to: Module, val reason: String? = null) : Error() { override val message: String - get() = "Invalid module dependency from module ${from.name} to ${to.name}" + get() = "Invalid module dependency from module ${from.name} to ${to.name}" + reason?.let { ": $it" } } \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildFileIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildFileIR.kt index 361739a5b6e..2552589a64a 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildFileIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/BuildFileIR.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.BuildFilePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.MavenPrinter import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module import java.nio.file.Path interface FileIR : BuildSystemIR, IrsOwner @@ -20,6 +21,7 @@ data class BuildFileIR( val name: String, val directoryPath: Path, val modules: ModulesStructureIR, + val fromModules: List, val pom: PomIR, override val irs: PersistentList ) : FileIR { diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleIR.kt index 3f83e400d96..8a99501ed38 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleIR.kt @@ -22,7 +22,15 @@ data class RawGradleIR( override fun GradlePrinter.renderGradle() = renderer() } -data class CreateGradleValueIR(val name: String, val body: GradleIR) : GradleIR { +fun rawIR(ir: String) = RawGradleIR { +ir } +fun rawIR(ir: GradlePrinter.() -> String) = RawGradleIR { +ir() } + +fun MutableList.addRawIR(ir: GradlePrinter.() -> String) { + add(RawGradleIR { +ir() }) +} + + +class CreateGradleValueIR(val name: String, val body: GradleIR) : GradleIR { override fun GradlePrinter.renderGradle() { when (dsl) { GradlePrinter.GradleDsl.KOTLIN -> { @@ -46,6 +54,8 @@ data class GradleCallIr( val name: String, val parameters: List = emptyList() ) : GradleIR { + constructor(name: String, vararg parameters: BuildSystemIR) : this(name, parameters.toList()) + override fun GradlePrinter.renderGradle() { call(name, forceBrackets = true) { parameters.list { it.render(this) } @@ -68,8 +78,6 @@ data class GradleNewInstanceCall( } - - data class GradleSectionIR( val name: String, val body: BodyIR @@ -136,6 +144,14 @@ data class GradleImportIR(val import: String) : GradleIR { } } +data class GradleBinaryExpressionIR(val left: BuildSystemIR, val op: String, val right: BuildSystemIR) : GradleIR { + override fun GradlePrinter.renderGradle() { + left.render(this) + +" $op " + right.render(this) + } +} + interface BuildScriptIR : BuildSystemIR data class BuildScriptDependencyIR(val dependencyIR: GradleIR) : BuildScriptIR, BuildSystemIR by dependencyIR diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleTaskIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleTaskIR.kt index 14a0746f697..2ceb4f7a3a6 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleTaskIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/GradleTaskIR.kt @@ -40,11 +40,34 @@ data class GradleByClassTasksAccessIR( } } +data class GradleByClassTasksCreateIR( + val taskName: String, + val taskClass: String +) : GradleTaskAccessIR { + override fun GradlePrinter.renderGradle() { + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> { + +"val $taskName by tasks.creating($taskClass::class)" + } + GradlePrinter.GradleDsl.GROOVY -> { + +"task($taskName, type: $taskClass)" + } + } + } +} + + data class GradleConfigureTaskIR( val taskAccess: GradleTaskAccessIR, val dependsOn: List = emptyList(), val irs: List = emptyList() ) : GradleIR, FreeIR { + constructor( + taskAccess: GradleTaskAccessIR, + dependsOn: List = emptyList(), + createIrs: MutableList.() -> Unit = {} + ) : this(taskAccess, dependsOn, mutableListOf().apply(createIrs)) + override fun GradlePrinter.renderGradle() { taskAccess.render(this) +" " diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModuleType.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModuleType.kt index bf669b4a508..4e7966f10e3 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModuleType.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/kotlin/ModuleType.kt @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.StdlibType +import java.util.* //TODO maybe split into interfaces like it made with module configurators @Suppress("EnumEntryName") @@ -33,6 +34,9 @@ enum class ModuleSubType(val moduleType: ModuleType) { common(ModuleType.common) } +val ModuleSubType.isIOS: Boolean + get() = this in EnumSet.of(ModuleSubType.iosX64, ModuleSubType.iosArm32, ModuleSubType.iosArm64) + fun ModuleType.correspondingStdlib(): StdlibType? = when (this) { ModuleType.jvm -> StdlibType.StdlibJdk8 ModuleType.js -> StdlibType.StdlibJs 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 21b6604d74f..ba6098433ff 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 @@ -58,6 +58,9 @@ class ModulesToIRsConverter( return data.isSingleRootModuleMode } + private val irsToAddToModules = hashMapOf>() + private val moduleToBuildFile = hashMapOf() + private fun calculatePathForModule(module: Module, rootPath: Path) = when { needFlattening && module.isRootModule -> data.projectPath else -> rootPath / module.name @@ -75,6 +78,11 @@ class ModulesToIRsConverter( }.map { it.flatten() }.map { buildFiles -> if (needExplicitRootBuildFile) buildFiles + createRootBuildFile() else buildFiles + }.map { buildFiles -> + buildFiles.map { buildFile -> + val irs = buildFile.fromModules.flatMap { irsToAddToModules[it]?.toList() ?: emptyList() } + buildFile.withIrs(irs) + } } } @@ -83,6 +91,7 @@ class ModulesToIRsConverter( projectName, projectPath, RootFileModuleStructureIR(persistentListOf()), + emptyList(), pomIr, rootBuildFileIrs.toPersistentList() ) @@ -112,6 +121,7 @@ class ModulesToIRsConverter( with(dependencyType) { @Suppress("DEPRECATION") with(unsafeSettingWriter) { runArbitraryTask(module, to, data).ensure() } + irsToAddToModules.getOrPut(to) { mutableListOf() } += createToIRs(module, to, data).get() createDependencyIrs(module, to, data) } }.sequence().map { it.flatten() } @@ -155,9 +165,12 @@ class ModulesToIRsConverter( moduleIr, persistentListOf() ), + listOf(module), data.pomIr.copy(artifactId = module.name), createBuildFileIRs(module, state) - ) + ).also { + moduleToBuildFile[module] = it + } } module.subModules.mapSequence { subModule -> @@ -193,12 +206,19 @@ class ModulesToIRsConverter( targetModuleIrs, persistentListOf() ), + module.subModules + module, pomIr, buildPersistenceList { +createBuildFileIRs(module, state) module.subModules.forEach { +createBuildFileIRs(it, state) } } - ).asSingletonList().asSuccess() + ).also { buildFile -> + moduleToBuildFile[module] = buildFile + module.subModules.forEach { subModule -> + moduleToBuildFile[subModule] = buildFile + } + }.asSingletonList().asSuccess() + } private fun Writer.createTargetModule(target: Module, modulePath: Path): MultiplatformModuleIR { diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/ModuleDependency.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/ModuleDependency.kt index c56c3808138..c42adc9d135 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/ModuleDependency.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/ModuleDependency.kt @@ -11,9 +11,13 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.DependencyType import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.GradleRootProjectDependencyIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleDependencyIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.* import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.* import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.isIOS +import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter +import kotlin.collections.buildList import kotlin.reflect.KClass sealed class ModuleDependencyType( @@ -41,6 +45,9 @@ sealed class ModuleDependencyType( open fun SettingsWriter.runArbitraryTask(from: Module, to: Module, data: ModulesToIrConversionData): TaskResult = UNIT_SUCCESS + open fun Reader.createToIRs(from: Module, to: Module, data: ModulesToIrConversionData): TaskResult> = + Success(emptyList()) + object JVMSinglePlatformToJVMSinglePlatform : ModuleDependencyType( from = JvmSinglePlatformModuleConfigurator::class, to = JvmSinglePlatformModuleConfigurator::class @@ -67,6 +74,65 @@ sealed class ModuleDependencyType( .setValue(IOSSinglePlatformModuleConfigurator.DependentModuleReference(to)) UNIT_SUCCESS } + + @OptIn(ExperimentalStdlibApi::class) + override fun Reader.createToIRs(from: Module, to: Module, data: ModulesToIrConversionData): TaskResult> { + val iosTargetName = to.subModules.firstOrNull { module -> + module.configurator.safeAs()?.moduleSubType?.isIOS == true + }?.name ?: return Failure(InvalidModuleDependencyError(from, to, "Module ${to.name} should contain at least one iOS target")) + + val packForXcodeTask = GradleConfigureTaskIR(GradleByClassTasksCreateIR("packForXcode", "Sync")) { + add(GradleAssignmentIR("group", GradleStringConstIR("build"))) + add( + CreateGradleValueIR( + "mode", + GradleBinaryExpressionIR( + RawGradleIR { +"System.getenv("; +"CONFIGURATION".quotified; +")" }, + "?:", + GradleStringConstIR("DEBUG") + ) + ) + ) + + add( + CreateGradleValueIR( + "framework", + RawGradleIR { + +"kotlin.targets" + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> +""".getByName("$iosTargetName")""" + GradlePrinter.GradleDsl.GROOVY -> +"['$iosTargetName']" + } + +".binaries.getFramework(mode)" + + } + ) + ) + addRawIR { "inputs.property(${"mode".quotified}, mode)" } + addRawIR { "dependsOn(framework.linkTask)" } + add( + CreateGradleValueIR( + "targetDir", + GradleCallIr("File", rawIR("buildDir"), GradleStringConstIR("xcode-frameworks")) + ) + ) + addRawIR { "from({ framework.outputDirectory })" } + addRawIR { "into(targetDir)" } + } + + val dependency = rawIR { + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> """tasks.getByName("build").dependsOn(packForXcode)""" + GradlePrinter.GradleDsl.GROOVY -> "tasks['build'].dependsOn(packForXcode)" + } + } + + return buildList { + add(packForXcodeTask) + add(dependency) + add(GradleImportIR("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget")) + }.asSuccess() + } } companion object {