Wizard: introduce gradle IR builder

This commit is contained in:
Ilya Kirillov
2020-04-10 15:34:15 +03:00
parent aa3cdc09fc
commit e6a3caa267
11 changed files with 144 additions and 157 deletions
@@ -79,4 +79,4 @@ task(packForXcode, type: Sync) {
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
tasks.getByName('build').dependsOn(packForXcode)
@@ -1,29 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle
import org.jetbrains.kotlin.tools.projectWizard.core.ListBuilder
import org.jetbrains.kotlin.tools.projectWizard.core.buildList
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.render
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
data class BodyIR(
val body: List<BuildSystemIR>
) : GradleIR {
constructor(vararg body: BuildSystemIR) : this(body.toList())
override fun GradlePrinter.renderGradle() {
inBrackets {
body.listNl()
}
}
}
fun buildBody(builder: ListBuilder<BuildSystemIR>.() -> Unit) =
BodyIR(buildList(builder))
fun BodyIR.renderIfNotEmpty(printer: GradlePrinter) =
takeIf { it.isNotEmpty() }?.render(printer)
fun BodyIR.isEmpty() = body.isEmpty()
fun BodyIR.isNotEmpty() = body.isNotEmpty()
@@ -23,15 +23,7 @@ data class RawGradleIR(
override fun GradlePrinter.renderGradle() = renderer()
}
fun rawIR(@NonNls ir: String) = RawGradleIR { +ir }
fun rawIR(ir: GradlePrinter.() -> String) = RawGradleIR { +ir() }
fun MutableList<BuildSystemIR>.addRawIR(ir: GradlePrinter.() -> String) {
add(RawGradleIR { +ir() })
}
class CreateGradleValueIR(@NonNls val name: String, val body: GradleIR) : GradleIR {
class CreateGradleValueIR(@NonNls val name: String, val body: BuildSystemIR) : GradleIR {
override fun GradlePrinter.renderGradle() {
when (dsl) {
GradlePrinter.GradleDsl.KOTLIN -> {
@@ -87,17 +79,12 @@ data class GradleNewInstanceCall(
data class GradleSectionIR(
@NonNls val name: String,
val body: BodyIR
val irs: List<BuildSystemIR>
) : GradleIR, FreeIR {
constructor(name: String, bodyBuilder: MutableList<BuildSystemIR>.() -> Unit) : this(
name,
BodyIR(mutableListOf<BuildSystemIR>().apply(bodyBuilder))
)
override fun GradlePrinter.renderGradle() {
+name
+" "
body.render(this)
sectionCall(name) {
irs.listNl()
}
}
}
@@ -0,0 +1,58 @@
/*
* 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.gradle
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
typealias IRsListBuilderFunction = GradleIRListBuilder.() -> Unit
fun IRsListBuilderFunction.build() = GradleIRListBuilder.build(this)
interface GradleIRBuilderBase {
fun const(const: String) = GradleStringConstIR(const)
fun raw(renderer: GradlePrinter.() -> Unit) = RawGradleIR(renderer)
fun raw(string: String) = RawGradleIR { +string }
fun new(@NonNls name: String, vararg parameters: BuildSystemIR) = GradleCallIr(name, parameters.toList(), isConstructorCall = true)
fun new(@NonNls name: String, parameters: IRsListBuilderFunction) = new(name, *parameters.build().toTypedArray())
fun fromString(renderer: GradlePrinter.() -> String) = RawGradleIR { +renderer() }
}
class GradleIRListBuilder private constructor() : GradleIRBuilderBase {
private val irs = mutableListOf<BuildSystemIR>()
operator fun String.invoke(inner: IRsListBuilderFunction) =
GradleSectionIR(this, build(inner)).also(irs::add)
operator fun String.invoke(vararg parameters: BuildSystemIR) =
GradleCallIr(this, parameters.toList()).also(irs::add)
infix fun String.assign(assignee: BuildSystemIR) =
GradleAssignmentIR(this, assignee).also(irs::add)
infix fun String.createValue(assignee: BuildSystemIR) =
CreateGradleValueIR(this, assignee).also(irs::add)
operator fun String.unaryPlus() = RawGradleIR { +this@unaryPlus }.also(irs::add)
operator fun BuildSystemIR.unaryPlus() = also(irs::add)
fun addRaw(raw: GradlePrinter.() -> Unit) = RawGradleIR(raw).also(irs::add)
fun addRaw(@NonNls raw: String) = RawGradleIR { +raw }.also(irs::add)
fun import(@NonNls import: String) = GradleImportIR(import).also(irs::add)
fun build(): List<BuildSystemIR> = irs
companion object {
fun build(inner: IRsListBuilderFunction) = GradleIRListBuilder().apply(inner).build()
}
}
fun irsList(inner: IRsListBuilderFunction): List<BuildSystemIR> =
GradleIRListBuilder.build(inner)
@@ -66,8 +66,8 @@ data class GradleConfigureTaskIR(
constructor(
taskAccess: GradleTaskAccessIR,
dependsOn: List<BuildSystemIR> = emptyList(),
createIrs: MutableList<BuildSystemIR>.() -> Unit = {}
) : this(taskAccess, dependsOn, mutableListOf<BuildSystemIR>().apply(createIrs))
createIrs: IRsListBuilderFunction
) : this(taskAccess, dependsOn, createIrs.build())
override fun GradlePrinter.renderGradle() {
taskAccess.render(this)
@@ -1,11 +1,14 @@
package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.IrsOwner
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.KotlinIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.GradleCallIr
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.GradleIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.IRsListBuilderFunction
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.build
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.withIrs
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
@@ -45,6 +48,9 @@ data class DefaultTargetConfigurationIR(
override val targetName: String
get() = targetAccess.nonDefaultName ?: targetAccess.type.name
constructor(targetAccess: TargetAccessIR, irs: IRsListBuilderFunction)
: this(targetAccess, irs.build().toPersistentList())
override fun withReplacedIrs(irs: PersistentList<BuildSystemIR>): DefaultTargetConfigurationIR =
copy(irs = irs)
@@ -67,6 +73,9 @@ data class NonDefaultTargetConfigurationIR(
override fun withReplacedIrs(irs: PersistentList<BuildSystemIR>): NonDefaultTargetConfigurationIR =
copy(irs = irs)
constructor(variableName: String, targetName: String, irs: IRsListBuilderFunction)
: this(variableName, targetName, irs.build().toPersistentList())
override fun GradlePrinter.renderGradle() {
if (irs.isNotEmpty()) {
+variableName
@@ -9,21 +9,17 @@ import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.core.buildList
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
fun runTaskIrs(@NonNls mainClass: String, classPath: BuildSystemIR? = null) = buildList<BuildSystemIR> {
fun runTaskIrs(@NonNls mainClass: String, classPath: BuildSystemIR? = null) = irsList {
+ApplicationPluginIR(mainClass)
+GradleSectionIR("application", buildBody {
+GradleAssignmentIR("mainClassName", GradleStringConstIR(mainClass))
})
"application" {
"mainClassName" assign const(mainClass)
}
if (classPath != null) {
+GradleConfigureTaskIR(
GradleByNameTaskAccessIR(
name = "run",
taskClass = "JavaExec"
),
irs = listOf(GradleAssignmentIR("classpath", classPath))
)
+GradleConfigureTaskIR(GradleByNameTaskAccessIR("run", "JavaExec")) {
"classpath" assign classPath
}
}
}
@@ -9,13 +9,11 @@ package org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.core.Reader
import org.jetbrains.kotlin.tools.projectWizard.core.buildList
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.KotlinBuildSystemPluginIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.RawGradleIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.rawIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.irsList
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind
@@ -47,13 +45,11 @@ object JsSingleplatformModuleConfigurator : JSConfigurator, ModuleConfiguratorWi
reader: Reader,
configurationData: ModulesToIrConversionData,
module: Module
): List<BuildSystemIR> = buildList {
+RawGradleIR {
sectionCall("kotlin", needIndent = true) {
sectionCall("js", needIndent = true) {
+"browser {}"; nlIndented()
+"binaries.executable()"
}
): List<BuildSystemIR> = irsList {
"kotlin" {
"js" {
+"browser {}"
+"binaries.executable()"
}
}
}
@@ -25,16 +25,12 @@ class RealNativeTargetConfigurator private constructor(
override val isDesktopTarget: Boolean
get() = moduleSubType.isNativeDesktop
override fun createInnerTargetIrs(reader: Reader, module: Module): List<BuildSystemIR> = if (moduleSubType.isIOS) {
listOf(
GradleSectionIR("binaries") {
add(
GradleSectionIR("framework") {
add(GradleAssignmentIR("baseName", GradleStringConstIR(module.parent!!.name)))
}
)
override fun createInnerTargetIrs(reader: Reader, module: Module): List<BuildSystemIR> = if (moduleSubType.isIOS) irsList {
"binaries" {
"framework" {
"baseName" assign const(module.parent!!.name)
}
)
}
} else emptyList()
companion object {
@@ -62,12 +58,11 @@ object NativeForCurrentSystemTarget : NativeTargetConfigurator, SingleCoexistenc
val moduleName = module.name
val variableName = "${moduleName}Target"
return buildList {
+CreateGradleValueIR("hostOs", RawGradleIR { +"System.getProperty(\"os.name\")" })
+CreateGradleValueIR("isMingwX64", RawGradleIR { +"hostOs.startsWith(\"Windows\")" })
return irsList {
"hostOs" createValue raw("System.getProperty(\"os.name\")")
"isMingwX64" createValue raw("hostOs.startsWith(\"Windows\")")
//TODO do not use RawGradleIR here
+RawGradleIR {
addRaw {
when (dsl) {
GradlePrinter.GradleDsl.KOTLIN -> {
+"val $variableName = when "
@@ -102,9 +97,9 @@ object NativeForCurrentSystemTarget : NativeTargetConfigurator, SingleCoexistenc
reader: Reader,
configurationData: ModulesToIrConversionData,
module: Module
): List<BuildSystemIR> = buildList {
): List<BuildSystemIR> = irsList {
if (configurationData.buildSystemType == BuildSystemType.GradleGroovyDsl) {
+GradleImportIR("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests")
import("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests")
}
}
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.DefaultTargetConfigurationIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetAccessIR
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.JsBrowserTargetConfigurator.isApplication
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.JsNodeTargetConfigurator.isApplication
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.buildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
@@ -105,19 +106,16 @@ object JsBrowserTargetConfigurator : JsTargetConfigurator, ModuleConfiguratorWit
override fun Reader.createTargetIrs(
module: Module
): List<BuildSystemIR> = buildList {
): List<BuildSystemIR> = irsList {
+DefaultTargetConfigurationIR(
module.createTargetAccessIr(ModuleSubType.js),
buildPersistenceList {
+RawGradleIR {
sectionCall("browser", needIndent = true) {
if (isApplication(module)) {
+"binaries.executable()"
}
}
module.createTargetAccessIr(ModuleSubType.js)
) {
"browser" {
if (isApplication(module)) {
+"binaries.executable()"
}
}
)
}
}
}
@@ -133,19 +131,16 @@ object JsNodeTargetConfigurator : JsTargetConfigurator {
override fun Reader.createTargetIrs(
module: Module
): List<BuildSystemIR> = buildList {
): List<BuildSystemIR> = irsList {
+DefaultTargetConfigurationIR(
module.createTargetAccessIr(ModuleSubType.js),
buildPersistenceList {
+RawGradleIR {
sectionCall("nodejs", needIndent = true) {
if (isApplication(module)) {
+"binaries.executable()"
}
}
module.createTargetAccessIr(ModuleSubType.js)
) {
"nodejs" {
if (isApplication(module)) {
+"binaries.executable()"
}
}
)
}
}
}
@@ -168,20 +163,18 @@ object JvmTargetConfigurator : JvmModuleConfigurator,
override fun createInnerTargetIrs(
reader: Reader,
module: Module
): List<BuildSystemIR> = buildList {
): List<BuildSystemIR> = irsList {
reader {
withSettingsOf(module) {
val targetVersionValue = JvmModuleConfigurator.targetJvmVersion.reference.settingValue.value
if (buildSystemType.isGradle) {
+GradleSectionIR(
"compilations.all",
BodyIR(
GradleAssignmentIR("kotlinOptions.jvmTarget", GradleStringConstIR(targetVersionValue))
)
)
"compilations.all" {
"kotlinOptions.jvmTarget" assign GradleStringConstIR(targetVersionValue)
}
}
if (Settings.javaSupport.reference.settingValue) {
+GradleCallIr("withJava")
"withJava"()
}
}
}
@@ -81,51 +81,33 @@ sealed class ModuleDependencyType(
module.configurator.safeAs<SimpleTargetConfigurator>()?.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")
)
return irsList {
+GradleConfigureTaskIR(GradleByClassTasksCreateIR("packForXcode", "Sync")) {
"group" assign const("build")
"mode" createValue GradleBinaryExpressionIR(
raw { +"System.getenv("; +"CONFIGURATION".quotified; +")" },
"?:",
const("DEBUG")
)
)
add(
CreateGradleValueIR(
"framework",
RawGradleIR {
+"kotlin.targets."
when (dsl) {
GradlePrinter.GradleDsl.KOTLIN -> +"""getByName<KotlinNativeTarget>("$iosTargetName")"""
GradlePrinter.GradleDsl.GROOVY -> +iosTargetName
}
+".binaries.getFramework(mode)"
"framework" createValue raw {
+"kotlin.targets."
when (dsl) {
GradlePrinter.GradleDsl.KOTLIN -> +"""getByName<KotlinNativeTarget>("$iosTargetName")"""
GradlePrinter.GradleDsl.GROOVY -> +iosTargetName
}
)
)
addRawIR { "inputs.property(${"mode".quotified}, mode)" }
addRawIR { "dependsOn(framework.linkTask)" }
add(
CreateGradleValueIR(
"targetDir",
GradleCallIr("File", rawIR("buildDir"), GradleStringConstIR("xcode-frameworks"), isConstructorCall = true)
)
)
addRawIR { "from({ framework.outputDirectory })" }
addRawIR { "into(targetDir)" }
}
+".binaries.getFramework(mode)"
};
val dependency = rawIR { """tasks.getByName("build").dependsOn(packForXcode)""" }
addRaw { +"inputs.property(${"mode".quotified}, mode)" }
addRaw("dependsOn(framework.linkTask)")
"targetDir" createValue new("File", raw("buildDir"), const("xcode-frameworks"))
addRaw("from({ framework.outputDirectory })")
addRaw("into(targetDir)")
}
addRaw { +"""tasks.getByName(${"build".quotified}).dependsOn(packForXcode)""" }
import("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget")
return buildList {
add(packForXcodeTask)
add(dependency)
add(GradleImportIR("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget"))
}.asSuccess()
}
}