From 56fccce305c4fa789bee810285866dd1c1d7bacd Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 13 Dec 2019 15:42:24 +0300 Subject: [PATCH] Wizard: add basic ktor server template --- .../templates/ktorServer/server.kt.vm | 29 +++++++ .../kotlin/tools/projectWizard/core/utils.kt | 24 ++---- .../ir/buildsystem/BuildFileIR.kt | 14 ++++ .../ir/buildsystem/RepositoryIR.kt | 12 +++ .../ir/buildsystem/gradle/GradleIR.kt | 17 +++- .../ir/buildsystem/gradle/multiplatform/ir.kt | 21 ++++- .../projectWizard/ir/buildsystem/tasks.kt | 28 +++++++ .../tools/projectWizard/plugins/Plugins.kt | 8 +- .../plugins/templates/KtorTemplatesPlugin.kt | 8 ++ .../plugins/templates/TemplatesPlugin.kt | 22 ++++-- .../settings/buildsystem/Repository.kt | 15 +++- .../ConsoleJvmApplicationTemplate.kt | 53 ++----------- .../templates/KtorServerTemplate.kt | 79 +++++++++++++++++++ .../tools/projectWizard/templates/Template.kt | 51 ++++++++---- 14 files changed, 284 insertions(+), 97 deletions(-) create mode 100644 libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/ktorServer/server.kt.vm create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/tasks.kt create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/KtorTemplatesPlugin.kt create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt diff --git a/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/ktorServer/server.kt.vm b/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/ktorServer/server.kt.vm new file mode 100644 index 00000000000..a1f95fe073c --- /dev/null +++ b/libraries/tools/new-project-wizard/resources/org/jetbrains/kotlin/tools/projectWizard/templates/ktorServer/server.kt.vm @@ -0,0 +1,29 @@ +import io.ktor.application.call +import io.ktor.html.respondHtml +import io.ktor.http.HttpStatusCode +import io.ktor.routing.get +import io.ktor.routing.routing +import io.ktor.server.engine.embeddedServer +import ${serverEngine.getImport()} +import kotlinx.html.* + +fun HTML.index() { + head { + title("Hello from Ktor!") + } + body { + div { + +"Hello from Ktor" + } + } +} + +fun main() { + embeddedServer(${serverEngine.getEngineName()}, port = 8080, host = "127.0.0.1") { + routing { + get("/") { + call.respondHtml(HttpStatusCode.OK, HTML::index) + } + } + }.start(wait = true) +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/utils.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/utils.kt index d8e1c5261b8..58fc4ee8512 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/utils.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/utils.kt @@ -1,8 +1,5 @@ package org.jetbrains.kotlin.tools.projectWizard.core -import org.jetbrains.kotlin.tools.projectWizard.core.entity.Setting -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BodyIR import java.io.IOException import java.nio.file.Path import java.nio.file.Paths @@ -10,6 +7,12 @@ import kotlin.properties.ReadOnlyProperty import kotlin.random.Random import kotlin.reflect.KProperty +inline infix fun ((A) -> B).andThen(crossinline then: (B) -> C): (A) -> C = + { then(this(it)) } + +@Suppress("NOTHING_TO_INLINE") +inline fun idFunction(): (T) -> T = { it } + operator fun Path.div(other: String): Path = resolve(other) @@ -42,24 +45,11 @@ internal inline fun cached(crossinline createValue: (name: String) -> T) = o @PublishedApi internal inline fun Any?.safeAs(): T? = this as? T -@Suppress("NOTHING_TO_INLINE") +@Suppress("NOTHING_TO_INLINE", "unused") inline fun Any?.ignore() = Unit internal fun T.asSingletonList() = listOf(this) -inline fun Iterable<*>.filterIsInstanceWith(predicate: (R) -> Boolean): List { - val result = mutableListOf() - for (element in this) { - if (element is R && predicate(element)) { - result += element - } - } - return result -} - -fun Path.asAbsolute(prefix: Path) = - if (isAbsolute) this else prefix / this - @DslMarker annotation class Builder 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 879ad6476ec..283d7892f43 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 @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScrip import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScriptRepositoryIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.GradleIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.DefaultTargetConfigurationIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetConfigurationIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetIR import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.BuildFilePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter @@ -115,6 +117,18 @@ data class MultiplatformModulesStructureIR( } } +fun MultiplatformModulesStructureIR.updateTargets( + updater: (TargetConfigurationIR) -> TargetConfigurationIR +): MultiplatformModulesStructureIR { + val newTargets = targets.map { target -> + when (target) { + is TargetConfigurationIR -> updater(target) + else -> target + } + } + return copy(targets = newTargets) +} + data class SingleplatformModulesStructureWithSingleModuleIR( val module: SingleplatformModuleIR, override val irs: List diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/RepositoryIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/RepositoryIR.kt index 8c123053d8d..ddb501e5218 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/RepositoryIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/RepositoryIR.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.BuildFilePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.CustomMavenRepository import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Repository @@ -12,6 +13,17 @@ data class RepositoryIR(val repository: Repository) : BuildSystemIR { +repository.type.asGradleName() +"()" } + is CustomMavenRepository -> { + sectionCall("maven", needIndent = true) { + assignmentOrCall("url") { + val url = repository.url.quotified + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> call("uri") { +url } + GradlePrinter.GradleDsl.GROOVY -> +url + } + } + } + } else -> Unit } else -> Unit 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 6c11deae2c9..095c2ae1ac5 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 @@ -43,7 +43,7 @@ data class GradleCallIr( val name: String ) : GradleIR { override fun GradlePrinter.renderGradle() { - sectionCall(name) {} + call(name, forceBrackets = true) {} } } @@ -90,6 +90,21 @@ data class CompilationAccessIr( } } +data class GradleDynamicPropertyAccessIR(val qualifier: BuildSystemIR, val propertyName: String) : GradleIR { + override fun GradlePrinter.renderGradle() { + qualifier.render(this) + when (dsl) { + GradlePrinter.GradleDsl.KOTLIN -> +"[${propertyName.quotified}]" + GradlePrinter.GradleDsl.GROOVY -> +".$propertyName" + } + } +} + +data class GradlePropertyAccessIR(val propertyName: String) : GradleIR { + override fun GradlePrinter.renderGradle() { + +propertyName + } +} interface BuildScriptIR : BuildSystemIR diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/multiplatform/ir.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/multiplatform/ir.kt index b99d83f82ae..c423d63db63 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/multiplatform/ir.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/gradle/multiplatform/ir.kt @@ -3,13 +3,15 @@ package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplat 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.withIrs import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter interface MultiplatformIR : GradleIR, KotlinIR -interface TargetIR: MultiplatformIR +interface TargetIR : MultiplatformIR data class TargetAccessIR( val type: ModuleSubType, @@ -23,12 +25,23 @@ data class TargetAccessIR( } } -interface TargetConfigurationIR : MultiplatformIR, IrsOwner +interface TargetConfigurationIR : MultiplatformIR, IrsOwner { + val name: String +} + +fun TargetConfigurationIR.addWithJavaIntoJvmTarget() = when { + this is DefaultTargetConfigurationIR && targetAccess.type == ModuleSubType.jvm -> + withIrs(GradleCallIr("withJava")) + else -> this +} data class DefaultTargetConfigurationIR( val targetAccess: TargetAccessIR, override val irs: List ) : TargetConfigurationIR { + override val name: String + get() = targetAccess.nonDefaultName ?: targetAccess.type.name + override fun withReplacedIrs(irs: List): DefaultTargetConfigurationIR = copy(irs = irs) @@ -44,7 +57,7 @@ data class DefaultTargetConfigurationIR( } data class NonDefaultTargetConfigurationIR( - val name: String, + override val name: String, override val irs: List ) : TargetConfigurationIR { override fun withReplacedIrs(irs: List): NonDefaultTargetConfigurationIR = @@ -54,7 +67,7 @@ data class NonDefaultTargetConfigurationIR( +name when (dsl) { GradlePrinter.GradleDsl.KOTLIN -> +".apply" - GradlePrinter.GradleDsl.GROOVY-> +".with" + GradlePrinter.GradleDsl.GROOVY -> +".with" } +" "; inBrackets { irs.listNl() } } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/tasks.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/tasks.kt new file mode 100644 index 00000000000..1d0f9715f51 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/tasks.kt @@ -0,0 +1,28 @@ +/* + * 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.ir.buildsystem + +import org.jetbrains.kotlin.tools.projectWizard.core.buildList +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.* + +fun runTaskIrs(mainClass: String, classPath: BuildSystemIR? = null) = buildList { + +ApplicationPluginIR(mainClass) + + +GradleSectionIR("application", buildBody { + +GradleAssignmentIR("mainClassName", GradleStringConstIR(mainClass)) + }) + + if (classPath != null) { + +GetGradleTaskIR( + name = "run", + taskClass = "JavaExec", + body = buildBody { + classPath.let { +GradleAssignmentIR("classpath", it) } + } + ) + } +} + diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/Plugins.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/Plugins.kt index 905725b3cf0..d1d30fb559f 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/Plugins.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/Plugins.kt @@ -7,9 +7,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle.Groov import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle.KotlinDslPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin -import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.ConsoleJvmApplicationTemplatePlugin -import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.KotlinTestTemplatePlugin -import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.* object Plugins { val allPlugins = { context: Context -> @@ -27,7 +25,9 @@ object Plugins { // templates KotlinTestTemplatePlugin(context), - ConsoleJvmApplicationTemplatePlugin(context) + ConsoleJvmApplicationTemplatePlugin(context), + KtorTemplatesPlugin(context), + JsTemplatesPlugin(context) ) } } \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/KtorTemplatesPlugin.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/KtorTemplatesPlugin.kt new file mode 100644 index 00000000000..4926c4b1a55 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/KtorTemplatesPlugin.kt @@ -0,0 +1,8 @@ +package org.jetbrains.kotlin.tools.projectWizard.plugins.templates + +import org.jetbrains.kotlin.tools.projectWizard.core.* +import org.jetbrains.kotlin.tools.projectWizard.templates.* + +class KtorTemplatesPlugin(context: Context) : TemplatePlugin(context) { + val addTemplate by addTemplateTask(KtorServerTemplate()) +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt index 792ea7a86d0..ff45cab29d3 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt @@ -65,20 +65,28 @@ class TemplatesPlugin(context: Context) : Plugin(context) { } ) } - }.map { it.fold() } + }.map(List::fold) + } + is SourcesetModuleIR -> { + applyTemplateToSourceset( + module.template, + module, + templateEngine + ) } - is SourcesetModuleIR -> applyTemplateToSourceset( - module.template, - module, - templateEngine - ) }.map { result -> module.withIrs(result.librariesToAdd) to result } }.map { val (moduleIrs, results) = it.unzip() val foldedResults = results.fold() buildFile.copy( modules = buildFile.modules.withModules(moduleIrs) - ).withIrs(foldedResults.irsToAddToBuildFile) + ).withIrs(foldedResults.irsToAddToBuildFile).let { buildFile -> + when (val structure = buildFile.modules) { + is MultiplatformModulesStructureIR -> + buildFile.copy(modules = structure.updateTargets(foldedResults.updateTarget)) + else -> buildFile + } + } } } } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt index 2da15c08e95..8b437d3caa4 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt @@ -7,10 +7,23 @@ data class DefaultRepository(val type: Type) : Repository { JCENTER, MAVEN_CENTRAL, GOOGLE, GRADLE_PLUGIN_PORTAL } - companion object { + companion object { val JCENTER = DefaultRepository(Type.JCENTER) val MAVEN_CENTRAL = DefaultRepository(Type.MAVEN_CENTRAL) val GOOGLE = DefaultRepository(Type.GOOGLE) val GRADLE_PLUGIN_PORTAL = DefaultRepository(Type.GRADLE_PLUGIN_PORTAL) } } + + +interface CustomMavenRepository : Repository { + val url: String +} + +data class BintrayRepository(val repository: String) : CustomMavenRepository { + override val url: String = "https://dl.bintray.com/$repository" +} + +object Repositories { + val KTOR_BINTRAY = BintrayRepository("ktor/ktor") +} diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/ConsoleJvmApplicationTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/ConsoleJvmApplicationTemplate.kt index 220b662fc5c..25744ec92a4 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/ConsoleJvmApplicationTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/ConsoleJvmApplicationTemplate.kt @@ -3,11 +3,9 @@ package org.jetbrains.kotlin.tools.projectWizard.templates import org.jetbrains.kotlin.tools.projectWizard.core.buildList import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.* -import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.buildSystemType -import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetConfigurationIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.addWithJavaIntoJvmTarget import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType -import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType class ConsoleJvmApplicationTemplate : Template() { @@ -22,51 +20,12 @@ class ConsoleJvmApplicationTemplate : Template() { override fun TaskRunningContext.getIrsToAddToBuildFile( sourceset: SourcesetIR ) = buildList { - +ApplicationPluginIR("MainKt") - - if (buildSystemType.isGradle) { - +GradleSectionIR("application", buildBody { - +GradleAssignmentIR("mainClassName", GradleStringConstIR("MainKt")) - }) - } - - if (sourceset is SourcesetModuleIR) { - +GetGradleTaskIR( - "run", - "JavaExec", - buildBody { - val compilationAccess = - CompilationAccessIr(sourceset.type.name, sourceset.sourcesetType.name, null) - val classPath = RawGradleIR { - when (dsl) { - GradlePrinter.GradleDsl.KOTLIN -> { - +"with(" - compilationAccess.render(this) - +") " - inBrackets { - indent() - +"output.allOutputs + compileDependencyFiles + runtimeDependencyFiles" - } - } - GradlePrinter.GradleDsl.GROOVY -> { - compilationAccess.render(this); +".output.allOutputs + "; nl() - indented { - indent(); compilationAccess.render(this); +".compileDependencyFiles + "; nl() - indent(); compilationAccess.render(this); +".runtimeDependencyFiles" - } - } - } - } - - +GradleAssignmentIR( - "classpath", - classPath - ) - } - ) - } + +runTaskIrs("MainKt") } + override fun updateTargetIr(sourceset: SourcesetIR, targetConfigurationIR: TargetConfigurationIR): TargetConfigurationIR = + targetConfigurationIR.addWithJavaIntoJvmTarget() + override fun TaskRunningContext.getFileTemplates(sourceset: SourcesetIR) = buildList { +FileTemplateDescriptor("$id/main.kt.vm", sourcesPath("main.kt")) diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt new file mode 100644 index 00000000000..52698768722 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt @@ -0,0 +1,79 @@ +/* + * 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.templates + +import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext +import org.jetbrains.kotlin.tools.projectWizard.core.buildList +import org.jetbrains.kotlin.tools.projectWizard.core.entity.TemplateSetting +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.addWithJavaIntoJvmTarget +import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact +import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase +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.Repositories +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType +import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version + +class KtorServerTemplate : Template() { + override val title: String = "Ktor-based Server" + override val htmlDescription: String = title + override val moduleTypes: Set = setOf(ModuleType.jvm) + override val sourcesetTypes: Set = setOf(SourcesetType.main) + override val id: String = "ktorServer" + + override fun TaskRunningContext.getRequiredLibraries(sourceset: SourcesetIR): List = + withSettingsOf(sourceset.original) { + buildList { + +ktorArtifactDependency(serverEngine.reference.settingValue.dependencyName) + +ktorArtifactDependency("ktor-html-builder") + +ArtifactBasedLibraryDependencyIR( + MavenArtifact(DefaultRepository.JCENTER, "org.jetbrains.kotlinx", "kotlinx-html-jvm"), + Version.fromString("0.6.12"), + DependencyType.MAIN + ) + } + } + + override fun TaskRunningContext.getIrsToAddToBuildFile(sourceset: SourcesetIR): List = buildList { + +RepositoryIR(Repositories.KTOR_BINTRAY) + +RepositoryIR(DefaultRepository.JCENTER) + +runTaskIrs(mainClass = "ServerKt") + } + + override fun updateTargetIr(sourceset: SourcesetIR, targetConfigurationIR: TargetConfigurationIR): TargetConfigurationIR = + targetConfigurationIR.addWithJavaIntoJvmTarget() + + override fun TaskRunningContext.getFileTemplates(sourceset: SourcesetIR): List = listOf( + FileTemplateDescriptor("$id/server.kt.vm", sourcesPath("server.kt")) + ) + + val serverEngine by enumSetting("Ktor Server", GenerationPhase.PROJECT_GENERATION) + + override val settings: List> = listOf(serverEngine) +} + +private fun ktorArtifactDependency(name: String) = ArtifactBasedLibraryDependencyIR( + MavenArtifact(Repositories.KTOR_BINTRAY, "io.ktor", name), + Version.fromString("1.2.6"), + DependencyType.MAIN +) + + +@Suppress("MemberVisibilityCanBePrivate") +enum class KtorServerEngine(val engineName: String, val dependencyName: String) : DisplayableSettingItem { + Netty("Netty", dependencyName = "ktor-server-netty"), + Tomcat("Tomcat", dependencyName = "ktor-server-tomcat"), + Jetty("Jetty", dependencyName = "ktor-server-jetty"); + + override val text: String + get() = engineName.capitalize() + + val import: String + get() = "io.ktor.server.${engineName.decapitalize()}.${engineName.capitalize()}" +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/Template.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/Template.kt index 415af1b458a..9feca8969b5 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/Template.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/Template.kt @@ -5,9 +5,8 @@ import org.jetbrains.kotlin.tools.projectWizard.SettingsOwner import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.* 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.DependencyIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.SourcesetIR +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.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType @@ -52,7 +51,7 @@ fun withSettingsOf( abstract class Template : SettingsOwner { - override fun > settingDelegate( + final override fun > settingDelegate( create: (path: String) -> SettingBuilder ): ReadOnlyProperty> = cached { name -> TemplateSetting(create(name).buildInternal()) @@ -72,6 +71,11 @@ abstract class Template : SettingsOwner { sourceset: SourcesetIR ): List = emptyList() + open fun updateTargetIr( + sourceset: SourcesetIR, + targetConfigurationIR: TargetConfigurationIR + ): TargetConfigurationIR = targetConfigurationIR + open fun TaskRunningContext.getFileTemplates(sourceset: SourcesetIR): List = emptyList() fun TaskRunningContext.applyToSourceset( @@ -85,7 +89,16 @@ abstract class Template : SettingsOwner { val librariesToAdd = getRequiredLibraries(sourceset) val irsToAddToBuildFile = getIrsToAddToBuildFile(sourceset) - val result = TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile) + val targetsUpdater = when (sourceset) { + is SourcesetModuleIR -> { target: TargetConfigurationIR -> + val targetName = sourceset.name.removeSuffix(sourceset.sourcesetType.name.capitalize()) + if (target.name == targetName) updateTargetIr(sourceset, target) + else target + } + else -> idFunction() + } + + val result = TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile, targetsUpdater) return getFileTemplates(sourceset).map { fileTemplate -> val fileText = templateEngine.renderTemplate(fileTemplate, allSettings) @@ -107,7 +120,7 @@ abstract class Template : SettingsOwner { ) @Suppress("UNCHECKED_CAST") - override fun dropDownSetting( + final override fun dropDownSetting( title: String, neededAtPhase: GenerationPhase, parser: Parser, @@ -121,7 +134,7 @@ abstract class Template : SettingsOwner { ) as ReadOnlyProperty>> @Suppress("UNCHECKED_CAST") - override fun stringSetting( + final override fun stringSetting( title: String, neededAtPhase: GenerationPhase, init: StringSettingType.Builder.() -> Unit @@ -133,7 +146,7 @@ abstract class Template : SettingsOwner { ) as ReadOnlyProperty> @Suppress("UNCHECKED_CAST") - override fun booleanSetting( + final override fun booleanSetting( title: String, neededAtPhase: GenerationPhase, init: BooleanSettingType.Builder.() -> Unit @@ -145,7 +158,7 @@ abstract class Template : SettingsOwner { ) as ReadOnlyProperty> @Suppress("UNCHECKED_CAST") - override fun valueSetting( + final override fun valueSetting( title: String, neededAtPhase: GenerationPhase, parser: Parser, @@ -159,7 +172,7 @@ abstract class Template : SettingsOwner { ) as ReadOnlyProperty>> @Suppress("UNCHECKED_CAST") - override fun versionSetting( + final override fun versionSetting( title: String, neededAtPhase: GenerationPhase, init: VersionSettingType.Builder.() -> Unit @@ -171,7 +184,7 @@ abstract class Template : SettingsOwner { ) as ReadOnlyProperty> @Suppress("UNCHECKED_CAST") - override fun listSetting( + final override fun listSetting( title: String, neededAtPhase: GenerationPhase, parser: Parser, @@ -186,7 +199,7 @@ abstract class Template : SettingsOwner { @Suppress("UNCHECKED_CAST") - override fun pathSetting( + final override fun pathSetting( title: String, neededAtPhase: GenerationPhase, init: PathSettingType.Builder.() -> Unit @@ -233,7 +246,7 @@ fun TaskRunningContext.applyTemplateToSourceset( sourceset: SourcesetIR, templateEngine: TemplateEngine ): TaskResult = when (template) { - null -> TemplateApplicationResult(emptyList(), emptyList()).asSuccess() + null -> TemplateApplicationResult.EMPTY.asSuccess() else -> with(template) { applyToSourceset(templateEngine, sourceset) } @@ -242,10 +255,15 @@ fun TaskRunningContext.applyTemplateToSourceset( data class TemplateApplicationResult( val librariesToAdd: List, - val irsToAddToBuildFile: List + val irsToAddToBuildFile: List, + val updateTarget: (TargetConfigurationIR) -> TargetConfigurationIR ) { companion object { - val EMPTY = TemplateApplicationResult(emptyList(), emptyList()) + val EMPTY = TemplateApplicationResult( + librariesToAdd = emptyList(), + irsToAddToBuildFile = emptyList(), + updateTarget = { it } + ) } } @@ -255,5 +273,6 @@ fun List.fold() = operator fun TemplateApplicationResult.plus(other: TemplateApplicationResult) = TemplateApplicationResult( librariesToAdd + other.librariesToAdd, - irsToAddToBuildFile + other.irsToAddToBuildFile + irsToAddToBuildFile + other.irsToAddToBuildFile, + updateTarget andThen other.updateTarget ) \ No newline at end of file