Wizard: introduce interceptors for module templates
This commit is contained in:
+12
@@ -10,6 +10,18 @@ import kotlin.reflect.KProperty
|
|||||||
inline infix fun <A, B, C> ((A) -> B).andThen(crossinline then: (B) -> C): (A) -> C =
|
inline infix fun <A, B, C> ((A) -> B).andThen(crossinline then: (B) -> C): (A) -> C =
|
||||||
{ then(this(it)) }
|
{ then(this(it)) }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composes two function together like normal composition if first function returns non-null value;
|
||||||
|
* Otherwise, applies second function
|
||||||
|
*/
|
||||||
|
inline infix fun <A : Any> ((A) -> A?).andThenNullable(crossinline then: (A) -> A?): (A) -> A? =
|
||||||
|
{ initial ->
|
||||||
|
val thisResult = this(initial)
|
||||||
|
if (thisResult != null) then(thisResult) else then(initial)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <T> idFunction(): (T) -> T = { it }
|
inline fun <T> idFunction(): (T) -> T = { it }
|
||||||
|
|
||||||
|
|||||||
-6
@@ -1,10 +1,4 @@
|
|||||||
package org.jetbrains.kotlin.tools.projectWizard.ir
|
package org.jetbrains.kotlin.tools.projectWizard.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.safeAs
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.FreeIR
|
|
||||||
|
|
||||||
interface IR
|
interface IR
|
||||||
|
|
||||||
interface TaskIR : FreeIR {
|
|
||||||
val name: String
|
|
||||||
}
|
|
||||||
+12
@@ -11,6 +11,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.GradlePrinter
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.MavenPrinter
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.MavenPrinter
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import javax.xml.transform.Source
|
||||||
|
|
||||||
data class BuildFileIR(
|
data class BuildFileIR(
|
||||||
val name: String,
|
val name: String,
|
||||||
@@ -81,6 +82,17 @@ data class BuildFileIR(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val BuildFileIR.targets
|
||||||
|
get() = modules.safeAs<MultiplatformModulesStructureIR>()?.targets.orEmpty()
|
||||||
|
|
||||||
|
val BuildFileIR.sourcesets
|
||||||
|
get() = modules.modules.flatMap { module ->
|
||||||
|
when (module) {
|
||||||
|
is SingleplatformModuleIR -> module.sourcesets
|
||||||
|
is SourcesetModuleIR -> listOf(module as SourcesetIR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class ModulesStructureIR : BuildSystemIR, IrsOwner {
|
sealed class ModulesStructureIR : BuildSystemIR, IrsOwner {
|
||||||
abstract val modules: List<ModuleIR>
|
abstract val modules: List<ModuleIR>
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -40,13 +40,17 @@ data class CreateGradleValueIR(val name: String, val body: GradleIR) : GradleIR
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class GradleCallIr(
|
data class GradleCallIr(
|
||||||
val name: String
|
val name: String,
|
||||||
|
val parameters: List<BuildSystemIR> = emptyList()
|
||||||
) : GradleIR {
|
) : GradleIR {
|
||||||
override fun GradlePrinter.renderGradle() {
|
override fun GradlePrinter.renderGradle() {
|
||||||
call(name, forceBrackets = true) {}
|
call(name, forceBrackets = true) {
|
||||||
|
parameters.list { it.render(this) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class GradleSectionIR(
|
data class GradleSectionIR(
|
||||||
val name: String,
|
val name: String,
|
||||||
val body: BodyIR
|
val body: BodyIR
|
||||||
|
|||||||
+32
-31
@@ -1,48 +1,49 @@
|
|||||||
package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle
|
package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle
|
||||||
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.TaskIR
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.FreeIR
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.FreeIR
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.render
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
|
||||||
|
|
||||||
interface GradleTaskIR : GradleIR, TaskIR {
|
interface GradleTaskAccessIR : GradleIR {
|
||||||
val taskClass: String
|
val name: String
|
||||||
val body: BodyIR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CreateGradleTaskIR(
|
data class GradleByNameTaskAccessIR(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val taskClass: String,
|
val taskClass: String? = null
|
||||||
override val body: BodyIR
|
) : GradleTaskAccessIR {
|
||||||
) : GradleTaskIR {
|
|
||||||
override fun GradlePrinter.renderGradle() {
|
|
||||||
when (dsl) {
|
|
||||||
GradlePrinter.GradleDsl.GROOVY -> {
|
|
||||||
+"tasks.create('$name', $taskClass)"
|
|
||||||
}
|
|
||||||
GradlePrinter.GradleDsl.KOTLIN -> {
|
|
||||||
+"val $name by tasks.registering($taskClass::class)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+" "
|
|
||||||
body.renderIfNotEmpty(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class GetGradleTaskIR(
|
|
||||||
override val name: String,
|
|
||||||
override val taskClass: String,
|
|
||||||
override val body: BodyIR
|
|
||||||
) : GradleTaskIR {
|
|
||||||
override fun GradlePrinter.renderGradle() {
|
override fun GradlePrinter.renderGradle() {
|
||||||
when (dsl) {
|
when (dsl) {
|
||||||
GradlePrinter.GradleDsl.GROOVY -> {
|
GradlePrinter.GradleDsl.GROOVY -> {
|
||||||
+"tasks.getByName('$name')"
|
+"tasks.getByName('$name')"
|
||||||
}
|
}
|
||||||
GradlePrinter.GradleDsl.KOTLIN -> {
|
GradlePrinter.GradleDsl.KOTLIN -> {
|
||||||
+"tasks.getByName<$taskClass>(${name.quotified})"
|
+"tasks.getByName"
|
||||||
|
taskClass?.let { +"<$it>" }
|
||||||
|
+"(${name.quotified})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+" "
|
|
||||||
body.renderIfNotEmpty(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class GradleConfigureTaskIR(
|
||||||
|
val taskAccess: GradleTaskAccessIR,
|
||||||
|
val dependsOn: List<BuildSystemIR> = emptyList(),
|
||||||
|
val irs: List<BuildSystemIR> = emptyList()
|
||||||
|
) : GradleIR, FreeIR {
|
||||||
|
override fun GradlePrinter.renderGradle() {
|
||||||
|
taskAccess.render(this)
|
||||||
|
+" "
|
||||||
|
inBrackets {
|
||||||
|
if (dependsOn.isNotEmpty()) {
|
||||||
|
indent()
|
||||||
|
call("dependsOn", forceBrackets = true) {
|
||||||
|
dependsOn.list { it.render(this) }
|
||||||
|
}
|
||||||
|
nl()
|
||||||
|
}
|
||||||
|
irs.listNl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+6
-6
@@ -16,12 +16,12 @@ fun runTaskIrs(mainClass: String, classPath: BuildSystemIR? = null) = buildList<
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (classPath != null) {
|
if (classPath != null) {
|
||||||
+GetGradleTaskIR(
|
+GradleConfigureTaskIR(
|
||||||
name = "run",
|
GradleByNameTaskAccessIR(
|
||||||
taskClass = "JavaExec",
|
name = "run",
|
||||||
body = buildBody {
|
taskClass = "JavaExec"
|
||||||
classPath.let { +GradleAssignmentIR("classpath", it) }
|
),
|
||||||
}
|
irs = listOf(GradleAssignmentIR("classpath", classPath))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -7,6 +7,8 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemP
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.templates.*
|
import org.jetbrains.kotlin.tools.projectWizard.templates.*
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.TemplateInterceptor
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.fold
|
||||||
|
|
||||||
class TemplatesPlugin(context: Context) : Plugin(context) {
|
class TemplatesPlugin(context: Context) : Plugin(context) {
|
||||||
val templates by property<Map<String, Template>>(
|
val templates by property<Map<String, Template>>(
|
||||||
@@ -91,4 +93,20 @@ class TemplatesPlugin(context: Context) : Plugin(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val postApplyTemplatesToSourcesets by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
|
||||||
|
runBefore(BuildSystemPlugin::createModules)
|
||||||
|
runAfter(KotlinPlugin::createModules)
|
||||||
|
runAfter(TemplatesPlugin::addTemplatesToSourcesets)
|
||||||
|
|
||||||
|
withAction {
|
||||||
|
updateBuildFiles { buildFile ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val interceptors = buildFile.sourcesets.mapNotNull { sourceset ->
|
||||||
|
sourceset.template?.createInterceptors(sourceset) as? List<TemplateInterceptor>
|
||||||
|
}.flatten().fold()
|
||||||
|
interceptors.applyUntilConverge(buildFile).asSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+76
-11
@@ -7,17 +7,18 @@ package org.jetbrains.kotlin.tools.projectWizard.templates
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext
|
import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.buildList
|
import org.jetbrains.kotlin.tools.projectWizard.core.buildList
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.TemplateSetting
|
import org.jetbrains.kotlin.tools.projectWizard.core.safeAs
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
|
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.library.MavenArtifact
|
import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Repositories
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
|
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.Interceptor
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.interceptTemplate
|
||||||
|
|
||||||
class SimpleJsClientTemplate : Template() {
|
class SimpleJsClientTemplate : Template() {
|
||||||
override val title: String = "Simple JS client"
|
override val title: String = "Simple JS client"
|
||||||
@@ -39,23 +40,87 @@ class SimpleJsClientTemplate : Template() {
|
|||||||
FileTemplateDescriptor("$id/client.kt.vm", sourcesPath("client.kt"))
|
FileTemplateDescriptor("$id/client.kt.vm", sourcesPath("client.kt"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun createInterceptors(sourceset: SourcesetIR): List<Interceptor> = buildList {
|
||||||
|
+interceptTemplate(KtorServerTemplate()) {
|
||||||
|
applicableIf { buildFileIR ->
|
||||||
|
val tasks = buildFileIR.irsOfTypeOrNull<GradleConfigureTaskIR>() ?: return@applicableIf false
|
||||||
|
tasks.none { it.taskAccess.name.endsWith("Jar") }
|
||||||
|
}
|
||||||
|
|
||||||
|
transformBuildFile { buildFileIR ->
|
||||||
|
val jsSourcesetName = sourceset.safeAs<SourcesetModuleIR>()?.targetName ?: return@transformBuildFile null
|
||||||
|
val jvmTarget = buildFileIR.targets.firstOrNull { target ->
|
||||||
|
target.safeAs<DefaultTargetConfigurationIR>()?.targetAccess?.type == ModuleSubType.jvm
|
||||||
|
} as? DefaultTargetConfigurationIR ?: return@transformBuildFile null
|
||||||
|
val jvmTargetName = jvmTarget.name
|
||||||
|
val webPackTaskName = "${jsSourcesetName}BrowserWebpack"
|
||||||
|
val jvmJarTaskAccess = GradleByNameTaskAccessIR("${jvmTargetName}Jar", "Jar")
|
||||||
|
|
||||||
|
val jvmJarTaskConfiguration = run {
|
||||||
|
val webPackTaskVariable = CreateGradleValueIR(
|
||||||
|
webPackTaskName,
|
||||||
|
GradleByNameTaskAccessIR(webPackTaskName, WEBPACK_TASK_CLASS)
|
||||||
|
)
|
||||||
|
val from = GradleCallIr(
|
||||||
|
"from",
|
||||||
|
listOf(
|
||||||
|
GradleCallIr(
|
||||||
|
"File",
|
||||||
|
listOf(
|
||||||
|
GradlePropertyAccessIR("$webPackTaskName.destinationDirectory"),
|
||||||
|
GradlePropertyAccessIR("$webPackTaskName.outputFileName")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
GradleConfigureTaskIR(
|
||||||
|
jvmJarTaskAccess,
|
||||||
|
dependsOn = listOf(GradleByNameTaskAccessIR(webPackTaskName)),
|
||||||
|
irs = listOf(
|
||||||
|
webPackTaskVariable,
|
||||||
|
from
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val runTaskConfiguration = run {
|
||||||
|
val taskAccess = GradleByNameTaskAccessIR("run", "JavaExec")
|
||||||
|
val classpath = GradleCallIr("classpath", listOf(jvmJarTaskAccess))
|
||||||
|
GradleConfigureTaskIR(
|
||||||
|
taskAccess,
|
||||||
|
dependsOn = listOf(jvmJarTaskAccess),
|
||||||
|
irs = listOf(classpath)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFileIR.withIrs(jvmJarTaskConfiguration, runTaskConfiguration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun TaskRunningContext.getIrsToAddToBuildFile(sourceset: SourcesetIR): List<BuildSystemIR> = buildList {
|
override fun TaskRunningContext.getIrsToAddToBuildFile(sourceset: SourcesetIR): List<BuildSystemIR> = buildList {
|
||||||
+RepositoryIR(DefaultRepository.JCENTER)
|
+RepositoryIR(DefaultRepository.JCENTER)
|
||||||
if (sourceset is SourcesetModuleIR) {
|
if (sourceset is SourcesetModuleIR) {
|
||||||
+GradleImportIR("org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack")
|
+GradleImportIR("org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack")
|
||||||
val taskAccessIR = GetGradleTaskIR(
|
val taskAccessIR = GradleByNameTaskAccessIR(
|
||||||
"${sourceset.targetName}BrowserWebpack",
|
"${sourceset.targetName}BrowserWebpack",
|
||||||
"KotlinWebpack",
|
WEBPACK_TASK_CLASS
|
||||||
buildBody {
|
)
|
||||||
+GradleAssignmentIR("outputFileName", GradleStringConstIR(JS_OUTPUT_FILE_NAME))
|
|
||||||
}
|
+GradleConfigureTaskIR(
|
||||||
|
taskAccessIR,
|
||||||
|
irs = listOf(
|
||||||
|
GradleAssignmentIR(
|
||||||
|
"outputFileName", GradleStringConstIR(JS_OUTPUT_FILE_NAME)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
+CreateGradleValueIR(JS_BROWSER_WEBPACK_TASK_ALIAS, taskAccessIR)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val JS_OUTPUT_FILE_NAME = "output.js"
|
const val JS_OUTPUT_FILE_NAME = "output.js"
|
||||||
const val JS_BROWSER_WEBPACK_TASK_ALIAS = "jsBrowserWebpack"
|
const val WEBPACK_TASK_CLASS = "KotlinWebpack"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.tools.projectWizard.SettingsOwner
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.core.*
|
import org.jetbrains.kotlin.tools.projectWizard.core.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
|
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.Interceptor
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetConfigurationIR
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetConfigurationIR
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
|
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
|
||||||
@@ -78,6 +79,8 @@ abstract class Template : SettingsOwner {
|
|||||||
|
|
||||||
open fun TaskRunningContext.getFileTemplates(sourceset: SourcesetIR): List<FileTemplateDescriptor> = emptyList()
|
open fun TaskRunningContext.getFileTemplates(sourceset: SourcesetIR): List<FileTemplateDescriptor> = emptyList()
|
||||||
|
|
||||||
|
open fun createInterceptors(sourceset: SourcesetIR): List<Interceptor> = emptyList()
|
||||||
|
|
||||||
fun TaskRunningContext.applyToSourceset(
|
fun TaskRunningContext.applyToSourceset(
|
||||||
templateEngine: TemplateEngine,
|
templateEngine: TemplateEngine,
|
||||||
sourceset: SourcesetIR
|
sourceset: SourcesetIR
|
||||||
|
|||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.transformers.interceptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildFileIR
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.sourcesets
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.templates.Template
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.Predicate
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.transformers.TransformerFunction
|
||||||
|
|
||||||
|
interface Interceptor
|
||||||
|
|
||||||
|
data class TemplateInterceptor(
|
||||||
|
val applicabilityCheckers: List<Predicate<BuildFileIR>>,
|
||||||
|
val buildFileTransformers: List<TransformerFunction<BuildFileIR>>
|
||||||
|
) : Interceptor {
|
||||||
|
fun applyTo(buildFileIR: BuildFileIR): BuildFileIR? {
|
||||||
|
if (applicabilityCheckers.any { checker -> !checker(buildFileIR) }) return null
|
||||||
|
|
||||||
|
var isApplied = false
|
||||||
|
var result: BuildFileIR = buildFileIR
|
||||||
|
|
||||||
|
for (transformer in buildFileTransformers) {
|
||||||
|
val newResult = transformer(result)
|
||||||
|
if (newResult != null) {
|
||||||
|
result = newResult
|
||||||
|
isApplied = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.takeIf { isApplied }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyUntilConverge(buildFileIR: BuildFileIR) =
|
||||||
|
generateSequence(buildFileIR, { buildFile ->
|
||||||
|
applyTo(buildFile)
|
||||||
|
}).last()
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateInterceptorBuilder<T : Template>(private val template: T) {
|
||||||
|
private val buildFileTransformers = mutableListOf<TransformerFunction<BuildFileIR>>()
|
||||||
|
fun transformBuildFile(transform: TransformerFunction<BuildFileIR>) {
|
||||||
|
buildFileTransformers += transform
|
||||||
|
}
|
||||||
|
|
||||||
|
private val applicabilityCheckers = mutableListOf<Predicate<BuildFileIR>>()
|
||||||
|
fun applicableIf(checker: Predicate<BuildFileIR>) {
|
||||||
|
applicabilityCheckers += checker
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
applicableIf { buildFile ->
|
||||||
|
buildFile.sourcesets.any { it.template?.id == template.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() = TemplateInterceptor(applicabilityCheckers, buildFileTransformers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<TemplateInterceptor>.fold() =
|
||||||
|
TemplateInterceptor(
|
||||||
|
flatMap { it.applicabilityCheckers },
|
||||||
|
flatMap { it.buildFileTransformers }
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun <T : Template> interceptTemplate(template: T, builder: TemplateInterceptorBuilder<T>.() -> Unit) =
|
||||||
|
TemplateInterceptorBuilder(template).apply(builder).build()
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.transformers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.andThenNullable
|
||||||
|
|
||||||
|
typealias TransformerFunction<I> = (I) -> I?
|
||||||
|
typealias Predicate<T> = (T) -> Boolean
|
||||||
|
|
||||||
|
fun <T : Any> Iterable<TransformerFunction<T>>.foldTransformers() =
|
||||||
|
fold<TransformerFunction<T>, TransformerFunction<T>>({ null }) { acc, transformer ->
|
||||||
|
acc andThenNullable transformer
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Iterable<Predicate<T>>.foldPredicates() = { value: T ->
|
||||||
|
all { it.invoke(value) }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user