diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt index a83ea2f90b2..aa4c4e2be9e 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt @@ -165,13 +165,14 @@ private class ModuleTemplateComponent( private object NoneTemplate : Template() { override val title = KotlinNewProjectWizardUIBundle.message("module.settings.template.none") override val description: String = "" - override val moduleTypes: Set = ModuleType.ALL + override fun isSupportedByModuleType(module: Module): Boolean = true + override val id: String = "none" } fun Reader.availableTemplatesFor(module: Module) = TemplatesPlugin.templates.propertyValue.values.filter { template -> - module.configurator.moduleType in template.moduleTypes + template.isSupportedByModuleType(module) } 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 593d46c5e4a..2d66efb8925 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 @@ -17,6 +17,7 @@ version = '1.0-SNAPSHOT' allprojects { repositories { google() + jcenter() mavenCentral() maven { url 'KOTLIN_REPO' } } 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 c86b75c8dbc..7c6e8d937e5 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 @@ -17,6 +17,7 @@ version = "1.0-SNAPSHOT" allprojects { repositories { google() + jcenter() mavenCentral() maven { url = uri("KOTLIN_REPO") } } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle index 606d883a5fe..b4534b8a1c2 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle @@ -17,6 +17,7 @@ version = '1.0-SNAPSHOT' allprojects { repositories { google() + jcenter() mavenCentral() maven { url 'KOTLIN_REPO' } } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle.kts b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle.kts index ebe4fd6ee5d..af13723974b 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle.kts +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/multiplatformMobileApplication/expected/build.gradle.kts @@ -17,6 +17,7 @@ version = "1.0-SNAPSHOT" allprojects { repositories { google() + jcenter() mavenCentral() maven { url = uri("KOTLIN_REPO") } } diff --git a/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties b/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties index dc519cd75a6..d38fa0eb3e4 100644 --- a/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties +++ b/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties @@ -150,6 +150,10 @@ project.template.mpp.mobile.lib.description=Library that supports sharing code b module.template.console.jvm.title=Console Application module.template.console.jvm.description=Simple "Hello World!" Kotlin/JVM application that works in the console +module.template.mpp.mobile.title=Mobile Application +module.template.mpp.mobile.description=Mobile applications for iOS and Android with Kotlin Multiplatform Mobile, which supports sharing common code between platforms. + + module.template.ktor.server.title=Ktor server module.template.ktor.server.description=Configurable Ktor web server for building web applications module.template.ktor.server.setting.engine=Ktor server engine diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/Context.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/Context.kt index c2aa161098f..eb25c8bfae1 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/Context.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/Context.kt @@ -10,6 +10,10 @@ import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager import org.jetbrains.kotlin.tools.projectWizard.core.service.SettingSavingWizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase +import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.allIRModules +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleReference +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.path import kotlin.reflect.KClass @@ -239,6 +243,11 @@ fun Reader.getUnspecifiedSettings(phases: Set): List::path).toSet() return required.filterNot { it.path in provided } } +fun Reader.moduleByReference(reference: ModuleReference): Module = when (reference) { + is ModuleReference.ByModule -> reference.module + is ModuleReference.ByPath -> allIRModules.first { it.originalModule.path == reference.path }.originalModule +} + typealias Reader = Context.Reader 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 5eb2138f586..5a97376bf1a 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 @@ -12,6 +12,9 @@ import kotlin.reflect.KProperty inline infix fun ((A) -> B).andThen(crossinline then: (B) -> C): (A) -> C = { then(this(it)) } +inline fun compose(crossinline function: (A) -> B, crossinline then: (B) -> C): (A) -> C = + { then(function(it)) } + /** * Composes two function together like normal composition if first function returns non-null value; 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 e5ce4ba592c..6331efdb7e7 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 @@ -138,6 +138,7 @@ sealed class ModulesStructureIR : BuildSystemIR, IrsOwner { data class MultiplatformModulesStructureIR( val targets: List, + val multiplatformModule: FakeMultiplatformModuleIR, override val modules: List, override val irs: PersistentList ) : GradleIR, ModulesStructureIR() { @@ -173,6 +174,15 @@ fun MultiplatformModulesStructureIR.updateTargets( return copy(targets = newTargets) } +fun MultiplatformModulesStructureIR.updateSourceSets( + updater: (ModuleIR) -> ModuleIR +): MultiplatformModulesStructureIR { + val newModules = modules.map { updater(it) as MultiplatformModuleIR } + return copy(modules = newModules) +} + + + data class SingleplatformModulesStructureWithSingleModuleIR( val module: SingleplatformModuleIR, override val irs: PersistentList 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 f35e91053ab..9042294791b 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 @@ -16,6 +16,11 @@ fun I.withIrs(irs: List) = withReplacedIrs(irs = t @Suppress("UNCHECKED_CAST") fun I.withIrs(vararg irs: BuildSystemIR) = withReplacedIrs(irs = this.irs + irs) as I +@Suppress("UNCHECKED_CAST") +inline fun I.withoutIrs(filterNot: (BuildSystemIR) -> Boolean): I = + withReplacedIrs(irs = this.irs.filterNot(filterNot).toPersistentList()) as I + + inline fun IrsOwner.irsOfType(): List = irs.filterIsInstance().let { irs -> diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/ModuleIR.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/ModuleIR.kt index ab3ec8e8cc7..95b36274437 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/ModuleIR.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/ir/buildsystem/ModuleIR.kt @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.GradleIR import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.BuildFilePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter @@ -16,8 +17,26 @@ sealed class ModuleIR : IrsOwner, BuildSystemIR { abstract val template: Template? abstract val originalModule: Module abstract val sourcesets: List + + abstract override fun withReplacedIrs(irs: PersistentList): ModuleIR } +data class FakeMultiplatformModuleIR( + override val name: String, + override val path: Path, + override val template: Template?, + val targets: List, + override val originalModule: Module +) : ModuleIR() { + override val sourcesets: List = emptyList() + override val irs: PersistentList = persistentListOf() + + override fun withReplacedIrs(irs: PersistentList): FakeMultiplatformModuleIR = this + + override fun BuildFilePrinter.render() { + error("Should not be called") + } +} data class SingleplatformModuleIR( override val name: String, 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 d451d0bdc6b..78bc60166d8 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 @@ -66,6 +66,7 @@ object AndroidSinglePlatformModuleConfigurator : override fun createBuildFileIRs(reader: Reader, configurationData: ModulesToIrConversionData, module: Module) = irsList { +super.createBuildFileIRs(reader, configurationData, module) + +RepositoryIR((DefaultRepository.JCENTER)) +AndroidConfigIR( javaPackage = when (reader.createAndroidPlugin(module)) { AndroidGradlePlugin.APPLICATION -> module.javaPackage(configurationData.pomIr) diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/MppModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/MppModuleConfigurator.kt index 6e649b35cc1..e4302653085 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/MppModuleConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/MppModuleConfigurator.kt @@ -7,31 +7,20 @@ 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.* -import org.jetbrains.kotlin.tools.projectWizard.core.entity.properties.ModuleConfiguratorProperty -import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.ModuleConfiguratorSetting +import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult +import org.jetbrains.kotlin.tools.projectWizard.core.Writer +import org.jetbrains.kotlin.tools.projectWizard.core.compute import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.KotlinBuildSystemPluginIR import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle.GradlePlugin -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.kotlin.ModulesToIrConversionData -import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath -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.Module import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind -import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType -import org.jetbrains.kotlin.tools.projectWizard.templates.FileDescriptor -import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate -import org.jetbrains.kotlin.tools.projectWizard.templates.FileTextDescriptor import java.nio.file.Path object MppModuleConfigurator : ModuleConfigurator, ModuleConfiguratorWithSettings, - ModuleConfiguratorSettings(), - ModuleConfiguratorProperties, - ModuleConfiguratorWithProperties { + ModuleConfiguratorSettings() { override val moduleKind = ModuleKind.multiplatform @@ -49,11 +38,6 @@ object MppModuleConfigurator : ModuleConfigurator, version = configurationData.kotlinVersion ) - val mppSources by listProperty() - - override fun getConfiguratorProperties(): List> = - listOf(mppSources) - // TODO remove when be removed in KMM wizard val generateTests by booleanSetting("Generate Tests", GenerationPhase.PROJECT_GENERATION) { defaultValue = value(false) @@ -64,295 +48,6 @@ object MppModuleConfigurator : ModuleConfigurator, module: Module, modulePath: Path, ): TaskResult = compute { - createMppFiles(module, modulePath).ensure() - createSimpleFiles(module, modulePath).ensure() GradlePlugin.gradleProperties.addValues("kotlin.mpp.enableGranularSourceSetsMetadata" to true) } - - private fun Writer.createMppFiles( - module: Module, - modulePath: Path - ): TaskResult = inContextOfModuleConfigurator(module) { - val mppFiles = mppSources.reference.propertyValue.flatMap { it.mppFiles } - .distinctBy { it.fileNameWithPackage } // todo merge files with the same name here - mppFiles.mapSequenceIgnore { file -> - module.subModules.mapSequenceIgnore mapTargets@{ target -> - val moduleSubType = //TODO handle for non-simple target configurator - target.configurator.safeAs()?.moduleSubType ?: return@mapTargets UNIT_SUCCESS - val path = pathForFileInTarget(modulePath, module, file.javaPackage, file.filename, target, SourcesetType.main) - val fileTemplate = FileTemplate( - FileTextDescriptor(file.printForModuleSubType(moduleSubType), path), - projectPath, - ) - TemplatesPlugin.fileTemplatesToRender.addValues(fileTemplate) - } - } - } - - private fun Writer.createSimpleFiles( - module: Module, - modulePath: Path - ): TaskResult = inContextOfModuleConfigurator(module) { - val mppFiles = mppSources.reference.propertyValue - val filesWithPaths = module.subModules.flatMap { target -> - val moduleSubType = //TODO handle for non-simple target configurator - target.configurator.safeAs()?.moduleSubType ?: return@flatMap emptyList() - mppFiles - .flatMap { it.getFilesFor(moduleSubType) } - .distinctBy { it.uniqueIdentifier } - .map { file -> - val path = projectPath / pathForFileInTarget(modulePath, module, file.javaPackage, file.filename, target, file.type) - file to path - } - }.distinctBy { (_, path) -> path } - filesWithPaths.mapSequenceIgnore { (file, path) -> - val fileTemplate = FileTemplate(file.fileDescriptor, path, mapOf("package" to file.javaPackage?.asCodePackage())) - TemplatesPlugin.fileTemplatesToRender.addValues(fileTemplate) - } - } - - private fun pathForFileInTarget( - mppModulePath: Path, - mppModule: Module, - javaPackage: JavaPackage?, - filename: String, - target: Module, - sourcesetType: SourcesetType, - ) = mppModulePath / - Defaults.SRC_DIR / - "${target.name}${sourcesetType.name.capitalize()}" / - mppModule.configurator.kotlinDirectoryName / - javaPackage?.asPath() / - filename } - - -@DslMarker -annotation class ExpectFileDSL - -data class MppFile( - @NonNls val filename: String, - @NonNls val javaPackage: JavaPackage? = null, - val declarations: List -) { - - val fileNameWithPackage - get() = javaPackage?.let { "${it.asCodePackage()}." }.orEmpty() + filename - - fun printForModuleSubType(moduleSubType: ModuleSubType): String = buildString { - javaPackage?.let { appendLine("package ${it.asCodePackage()}"); appendLine() } - if (moduleSubType == ModuleSubType.common) { - declarations.joinTo(this, separator = "\n\n") { it.printExpect() } - } else { - printImports(declarations.flatMap { it.importsFor(moduleSubType) }) - declarations.joinTo(this, separator = "\n\n") { it.printActualFor(moduleSubType) } - } - }.trim() - - private fun StringBuilder.printImports(imports: List) { - if (imports.isEmpty()) return - imports.distinct().joinTo(this, separator = "\n", prefix = "\n", postfix = "\n\n") { import -> - "import $import" - } - } - - @ExpectFileDSL - class Builder(private val filename: String, val javaPackage: JavaPackage? = null) { - private val declarations = mutableListOf() - - fun function(signature: String, init: MppFunction.Builder.() -> Unit = {}) { - declarations += MppFunction.Builder(signature).apply(init).build() - } - - fun `class`(name: String, init: MppClass.Builder.() -> Unit = {}) { - declarations += MppClass.Builder(name).apply(init).build() - } - - fun build() = MppFile(filename, javaPackage, declarations) - } -} - - -@ExpectFileDSL -class MppSources(val mppFiles: List, val simpleFiles: List) { - - fun getFilesFor(moduleSubType: ModuleSubType): List = - simpleFiles.filter { moduleSubType in it.moduleSubTypes }.flatMap { it.files } - - class Builder(val javaPackage: JavaPackage?) { - private val mppFiles = mutableListOf() - private val simpleFiles = mutableListOf() - - fun mppFile(filename: String, init: MppFile.Builder.() -> Unit) { - mppFiles += MppFile.Builder(filename, javaPackage).apply(init).build() - } - - fun filesFor(vararg moduleSubTypes: ModuleSubType, init: SimpleFiles.Builder.() -> Unit) { - simpleFiles += SimpleFiles.Builder(moduleSubTypes.toList(), javaPackage).apply(init).build() - } - - fun build() = MppSources(mppFiles, simpleFiles) - } -} - - -data class SimpleFiles(val moduleSubTypes: List, val files: List) { - class Builder(private val moduleSubTypes: List, val filesPackage: JavaPackage?) { - private val files = mutableListOf() - - fun file(fileDescriptor: FileDescriptor, filename: String, type: SourcesetType, init: SimpleFile.Builder.() -> Unit = {}) { - files += SimpleFile.Builder(fileDescriptor, filename, type).apply(init).apply { - javaPackage = filesPackage - }.build() - } - - fun build() = SimpleFiles(moduleSubTypes, files) - } -} - -data class SimpleFile(val fileDescriptor: FileDescriptor, val javaPackage: JavaPackage?, val filename: String, val type: SourcesetType) { - val uniqueIdentifier get() = "${type}/${javaPackage}/${filename}" - - class Builder(private val fileDescriptor: FileDescriptor, private val filename: String, private val type: SourcesetType) { - var javaPackage: JavaPackage? = null - - fun build() = SimpleFile(fileDescriptor, javaPackage, filename, type) - } -} - - -fun mppSources(javaPackage: JavaPackage? = null, init: MppSources.Builder.() -> Unit): MppSources = - MppSources.Builder(javaPackage).apply(init).build() - -sealed class MppDeclaration { - @Suppress("SpellCheckingInspection") - abstract val actuals: Actuals - - abstract fun printExpect(): String - - abstract fun printActualFor(moduleSubType: ModuleSubType): String - - fun importsFor(moduleSubType: ModuleSubType): List = actuals.getBodyFor(moduleSubType).imports - - @ExpectFileDSL - abstract class Builder { - private var defaultActualDeclarationBody = DefaultActualDeclarationBody(text = "", imports = emptyList()) - - @Suppress("SpellCheckingInspection") - private val actuals = mutableMapOf() - - fun default(defaultText: String, init: DefaultActualDeclarationBody.Builder.() -> Unit = {}) { - defaultActualDeclarationBody = DefaultActualDeclarationBody.Builder(defaultText).also(init).build() - } - - fun actualFor(vararg moduleSubTypes: ModuleSubType, actualBody: String, init: ActualDeclarationBody.Builder.() -> Unit = {}) { - moduleSubTypes.forEach { moduleSubType -> - actuals[moduleSubType] = ActualDeclarationBody.Builder(actualBody).apply(init).build() - } - } - - protected fun buildActuals() = Actuals(defaultActualDeclarationBody, actuals) - } -} - -data class MppFunction( - val signature: String, - @Suppress("SpellCheckingInspection") - override val actuals: Actuals, -) : MppDeclaration() { - override fun printExpect(): String = - "expect fun $signature" - - override fun printActualFor(moduleSubType: ModuleSubType): String { - val body = actuals.getBodyFor(moduleSubType) - return buildString { - appendLine("actual fun $signature {") - appendLine(body.text.indented(4)) - append("}") - } - } - - @ExpectFileDSL - class Builder(private val signature: String) : MppDeclaration.Builder() { - fun build(): MppFunction = MppFunction( - signature, - buildActuals(), - ) - } -} - -data class MppClass( - val name: String, - val expectBody: String?, - @Suppress("SpellCheckingInspection") - override val actuals: Actuals, -) : MppDeclaration() { - override fun printExpect(): String = buildString { - append("expect class $name()") - expectBody?.let { body -> - appendLine(" {") - appendLine(body.indented(4)) - append("}") - } - } - - override fun printActualFor(moduleSubType: ModuleSubType): String { - val body = actuals.getBodyFor(moduleSubType) - return buildString { - appendLine("actual class $name actual constructor() {") - appendLine(body.text.indented(4)) - append("}") - } - } - - @ExpectFileDSL - class Builder(private val name: String) : MppDeclaration.Builder() { - var expectBody: String? = null - - fun build(): MppClass = MppClass( - name, - expectBody, - buildActuals(), - ) - } -} - - -private fun String.indented(indentValue: Int): String { - val indent = " ".repeat(indentValue) - return split('\n').joinToString(separator = "\n") { line -> indent + line.trim() } -} - -@Suppress("SpellCheckingInspection") -data class Actuals( - val defaultActualDeclarationBody: DefaultActualDeclarationBody, - val actuals: Map, -) { - fun getBodyFor(moduleSubType: ModuleSubType): DeclarationBody = - actuals[moduleSubType] ?: defaultActualDeclarationBody -} - -sealed class DeclarationBody { - abstract val text: String - abstract val imports: List - - abstract class Builder { - protected val imports = mutableListOf() - - fun import(import: String) { - imports += import - } - } -} - -data class ActualDeclarationBody(override val text: String, override val imports: List) : DeclarationBody() { - class Builder(private val text: String) : DeclarationBody.Builder() { - fun build() = ActualDeclarationBody(text, imports) - } -} - -data class DefaultActualDeclarationBody(override val text: String, override val imports: List) : DeclarationBody() { - class Builder(private val text: String) : DeclarationBody.Builder() { - fun build() = DefaultActualDeclarationBody(text, imports) - } -} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/mpp/mpp.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/mpp/mpp.kt new file mode 100644 index 00000000000..e8c990b37f5 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/mpp/mpp.kt @@ -0,0 +1,327 @@ +/* + * 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.mpp + +import org.jetbrains.annotations.NonNls +import org.jetbrains.kotlin.tools.projectWizard.core.* +import org.jetbrains.kotlin.tools.projectWizard.core.safeAs +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.SimpleTargetConfigurator +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.inContextOfModuleConfigurator +import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle.GradlePlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData +import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath +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.Module +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType +import org.jetbrains.kotlin.tools.projectWizard.templates.FileDescriptor +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTextDescriptor +import java.nio.file.Path + +@DslMarker +annotation class ExpectFileDSL + +data class MppFile( + @NonNls val filename: String, + @NonNls val javaPackage: JavaPackage? = null, + val declarations: List +) { + + val fileNameWithPackage + get() = javaPackage?.let { "${it.asCodePackage()}." }.orEmpty() + filename + + fun printForModuleSubType(moduleSubType: ModuleSubType): String = buildString { + javaPackage?.let { appendLine("package ${it.asCodePackage()}"); appendLine() } + if (moduleSubType == ModuleSubType.common) { + declarations.joinTo(this, separator = "\n\n") { it.printExpect() } + } else { + printImports(declarations.flatMap { it.importsFor(moduleSubType) }) + declarations.joinTo(this, separator = "\n\n") { it.printActualFor(moduleSubType) } + } + }.trim() + + private fun StringBuilder.printImports(imports: List) { + if (imports.isEmpty()) return + imports.distinct().joinTo(this, separator = "\n", prefix = "\n", postfix = "\n\n") { import -> + "import $import" + } + } + + @ExpectFileDSL + class Builder(private val filename: String, val javaPackage: JavaPackage? = null) { + private val declarations = mutableListOf() + + fun function(signature: String, init: MppFunction.Builder.() -> Unit = {}) { + declarations += MppFunction.Builder(signature).apply(init).build() + } + + fun `class`(name: String, init: MppClass.Builder.() -> Unit = {}) { + declarations += MppClass.Builder(name).apply(init).build() + } + + fun build() = MppFile(filename, javaPackage, declarations) + } +} + + +@ExpectFileDSL +class MppSources(val mppFiles: List, val simpleFiles: List) { + + fun getFilesFor(moduleSubType: ModuleSubType): List = + simpleFiles.filter { moduleSubType in it.moduleSubTypes }.flatMap { it.files } + + class Builder(val javaPackage: JavaPackage?) { + private val mppFiles = mutableListOf() + private val simpleFiles = mutableListOf() + + fun mppFile(filename: String, init: MppFile.Builder.() -> Unit) { + mppFiles += MppFile.Builder(filename, javaPackage).apply(init).build() + } + + fun filesFor(vararg moduleSubTypes: ModuleSubType, init: SimpleFiles.Builder.() -> Unit) { + simpleFiles += SimpleFiles.Builder(moduleSubTypes.toList(), javaPackage).apply(init).build() + } + + fun build() = MppSources(mppFiles, simpleFiles) + } +} + + +data class SimpleFiles(val moduleSubTypes: List, val files: List) { + class Builder(private val moduleSubTypes: List, val filesPackage: JavaPackage?) { + private val files = mutableListOf() + + fun file(fileDescriptor: FileDescriptor, filename: String, type: SourcesetType, init: SimpleFile.Builder.() -> Unit = {}) { + files += SimpleFile.Builder(fileDescriptor, filename, type).apply(init).apply { + javaPackage = filesPackage + }.build() + } + + fun build() = SimpleFiles(moduleSubTypes, files) + } +} + +data class SimpleFile(val fileDescriptor: FileDescriptor, val javaPackage: JavaPackage?, val filename: String, val type: SourcesetType) { + val uniqueIdentifier get() = "${type}/${javaPackage}/${filename}" + + class Builder(private val fileDescriptor: FileDescriptor, private val filename: String, private val type: SourcesetType) { + var javaPackage: JavaPackage? = null + + fun build() = SimpleFile(fileDescriptor, javaPackage, filename, type) + } +} + + +fun mppSources(javaPackage: JavaPackage? = null, init: MppSources.Builder.() -> Unit): MppSources = + MppSources.Builder(javaPackage).apply(init).build() + +sealed class MppDeclaration { + @Suppress("SpellCheckingInspection") + abstract val actuals: Actuals + + abstract fun printExpect(): String + + abstract fun printActualFor(moduleSubType: ModuleSubType): String + + fun importsFor(moduleSubType: ModuleSubType): List = actuals.getBodyFor(moduleSubType).imports + + @ExpectFileDSL + abstract class Builder { + private var defaultActualDeclarationBody = DefaultActualDeclarationBody(text = "", imports = emptyList()) + + @Suppress("SpellCheckingInspection") + private val actuals = mutableMapOf() + + fun default(defaultText: String, init: DefaultActualDeclarationBody.Builder.() -> Unit = {}) { + defaultActualDeclarationBody = DefaultActualDeclarationBody.Builder(defaultText).also(init).build() + } + + fun actualFor(vararg moduleSubTypes: ModuleSubType, actualBody: String, init: ActualDeclarationBody.Builder.() -> Unit = {}) { + moduleSubTypes.forEach { moduleSubType -> + actuals[moduleSubType] = ActualDeclarationBody.Builder(actualBody).apply(init).build() + } + } + + protected fun buildActuals() = Actuals(defaultActualDeclarationBody, actuals) + } +} + +data class MppFunction( + val signature: String, + @Suppress("SpellCheckingInspection") + override val actuals: Actuals, +) : MppDeclaration() { + override fun printExpect(): String = + "expect fun $signature" + + override fun printActualFor(moduleSubType: ModuleSubType): String { + val body = actuals.getBodyFor(moduleSubType) + return buildString { + appendLine("actual fun $signature {") + appendLine(body.text.indented(4)) + append("}") + } + } + + @ExpectFileDSL + class Builder(private val signature: String) : MppDeclaration.Builder() { + fun build(): MppFunction = MppFunction( + signature, + buildActuals(), + ) + } +} + +data class MppClass( + val name: String, + val expectBody: String?, + @Suppress("SpellCheckingInspection") + override val actuals: Actuals, +) : MppDeclaration() { + override fun printExpect(): String = buildString { + append("expect class $name()") + expectBody?.let { body -> + appendLine(" {") + appendLine(body.indented(4)) + append("}") + } + } + + override fun printActualFor(moduleSubType: ModuleSubType): String { + val body = actuals.getBodyFor(moduleSubType) + return buildString { + appendLine("actual class $name actual constructor() {") + appendLine(body.text.indented(4)) + append("}") + } + } + + @ExpectFileDSL + class Builder(private val name: String) : MppDeclaration.Builder() { + var expectBody: String? = null + + fun build(): MppClass = MppClass( + name, + expectBody, + buildActuals(), + ) + } +} + + +private fun String.indented(indentValue: Int): String { + val indent = " ".repeat(indentValue) + return split('\n').joinToString(separator = "\n") { line -> indent + line.trim() } +} + +@Suppress("SpellCheckingInspection") +data class Actuals( + val defaultActualDeclarationBody: DefaultActualDeclarationBody, + val actuals: Map, +) { + fun getBodyFor(moduleSubType: ModuleSubType): DeclarationBody = + actuals[moduleSubType] ?: defaultActualDeclarationBody +} + +sealed class DeclarationBody { + abstract val text: String + abstract val imports: List + + abstract class Builder { + protected val imports = mutableListOf() + + fun import(import: String) { + imports += import + } + } +} + +data class ActualDeclarationBody(override val text: String, override val imports: List) : DeclarationBody() { + class Builder(private val text: String) : DeclarationBody.Builder() { + fun build() = ActualDeclarationBody(text, imports) + } +} + +data class DefaultActualDeclarationBody(override val text: String, override val imports: List) : DeclarationBody() { + class Builder(private val text: String) : DeclarationBody.Builder() { + fun build() = DefaultActualDeclarationBody(text, imports) + } +} + +fun Writer.applyMppStructure( + mppSources: List, + module: Module, + modulePath: Path, +): TaskResult = compute { + createMppFiles(mppSources, module, modulePath).ensure() + createSimpleFiles(mppSources, module, modulePath).ensure() +} + +fun Writer.applyMppStructure( + mppSources: MppSources, + module: Module, + modulePath: Path, +): TaskResult = applyMppStructure(listOf(mppSources), module, modulePath) + +private fun Writer.createMppFiles( + mppSources: List, + module: Module, + modulePath: Path +): TaskResult = inContextOfModuleConfigurator(module) { + val mppFiles = mppSources.flatMap { it.mppFiles } + .distinctBy { it.fileNameWithPackage } // todo merge files with the same name here + mppFiles.mapSequenceIgnore { file -> + module.subModules.mapSequenceIgnore mapTargets@{ target -> + val moduleSubType = //TODO handle for non-simple target configurator + target.configurator.safeAs()?.moduleSubType ?: return@mapTargets UNIT_SUCCESS + val path = pathForFileInTarget(modulePath, module, file.javaPackage, file.filename, target, SourcesetType.main) + val fileTemplate = FileTemplate( + FileTextDescriptor(file.printForModuleSubType(moduleSubType), path), + projectPath, + ) + TemplatesPlugin.fileTemplatesToRender.addValues(fileTemplate) + } + } +} + +private fun Writer.createSimpleFiles( + mppSources: List, + module: Module, + modulePath: Path +): TaskResult = inContextOfModuleConfigurator(module) { + val mppFiles = mppSources + val filesWithPaths = module.subModules.flatMap { target -> + val moduleSubType = //TODO handle for non-simple target configurator + target.configurator.safeAs()?.moduleSubType ?: return@flatMap emptyList() + mppFiles + .flatMap { it.getFilesFor(moduleSubType) } + .distinctBy { it.uniqueIdentifier } + .map { file -> + val path = projectPath / pathForFileInTarget(modulePath, module, file.javaPackage, file.filename, target, file.type) + file to path + } + }.distinctBy { (_, path) -> path } + filesWithPaths.mapSequenceIgnore { (file, path) -> + val fileTemplate = FileTemplate(file.fileDescriptor, path, mapOf("package" to file.javaPackage?.asCodePackage())) + TemplatesPlugin.fileTemplatesToRender.addValues(fileTemplate) + } +} + +private fun pathForFileInTarget( + mppModulePath: Path, + mppModule: Module, + javaPackage: JavaPackage?, + filename: String, + target: Module, + sourcesetType: SourcesetType, +) = mppModulePath / + Defaults.SRC_DIR / + "${target.name}${sourcesetType.name.capitalize()}" / + mppModule.configurator.kotlinDirectoryName / + javaPackage?.asPath() / + filename \ No newline at end of file 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 70f819ac620..b4f3c584bb2 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 @@ -32,7 +32,8 @@ object Plugins { JsTemplatesPlugin(context), ReactJsTemplatesPlugin(context), SimpleNodeJsTemplatesPlugin(context), - NativeConsoleApplicationTemplatePlugin(context) + NativeConsoleApplicationTemplatePlugin(context), + MobileMppTemplatePlugin(context), ) } } \ No newline at end of file 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 73b23e89e9e..b2f82a3c233 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 @@ -230,6 +230,13 @@ class ModulesToIRsConverter( modulePath, MultiplatformModulesStructureIR( targetIrs, + FakeMultiplatformModuleIR( + module.name, + modulePath, + module.template, + targetModuleIrs, + module, + ), targetModuleIrs, persistentListOf() ), diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/MobileMppTemplatePlugin.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/MobileMppTemplatePlugin.kt new file mode 100644 index 00000000000..1ba67d482c2 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/MobileMppTemplatePlugin.kt @@ -0,0 +1,26 @@ +package org.jetbrains.kotlin.tools.projectWizard.plugins.templates + +import org.jetbrains.kotlin.tools.projectWizard.core.Context +import org.jetbrains.kotlin.tools.projectWizard.core.PluginSettingsOwner +import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask +import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase +import org.jetbrains.kotlin.tools.projectWizard.templates.mpp.MobileMppTemplate + +class MobileMppTemplatePlugin(context: Context) : TemplatePlugin(context) { + override val path = pluginPath + + override val pipelineTasks: List = super.pipelineTasks + + listOf( + addTemplate, + ) + + companion object : PluginSettingsOwner() { + override val pluginPath = "template.mobile.mpp" + + val addTemplate by pipelineTask(GenerationPhase.PREPARE) { + withAction { + TemplatesPlugin.addTemplate.execute(MobileMppTemplate()) + } + } + } +} \ 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 ffcecb98f1a..48d90350cf4 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 @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetti import org.jetbrains.kotlin.tools.projectWizard.core.service.TemplateEngineService import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.ModuleConfiguratorWithTests +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.MppModuleConfigurator.runArbitraryTask import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.isPresent import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin @@ -67,20 +68,31 @@ class TemplatesPlugin(context: Context) : Plugin(context) { withAction { updateBuildFiles { buildFile -> - buildFile.modules.modules.mapSequence { module -> + val moduleStructure = buildFile.modules + val moduleIRs = buildList { + if (moduleStructure is MultiplatformModulesStructureIR) { + +moduleStructure.multiplatformModule + } + +moduleStructure.modules + } + moduleIRs.mapSequence { module -> applyTemplateToModule( module.template, module - ).map { result -> module.withIrs(result.librariesToAdd) to result } + ).map { result -> result.updateModuleIR(module.withIrs(result.librariesToAdd)) to result } }.map { val (moduleIrs, results) = it.unzip() val foldedResults = results.fold() buildFile.copy( - modules = buildFile.modules.withModules(moduleIrs) + modules = buildFile.modules.withModules(moduleIrs.filterNot { it is FakeMultiplatformModuleIR }) ).withIrs(foldedResults.irsToAddToBuildFile).let { buildFile -> when (val structure = buildFile.modules) { is MultiplatformModulesStructureIR -> - buildFile.copy(modules = structure.updateTargets(foldedResults.updateTarget)) + buildFile.copy( + modules = structure + .updateTargets(foldedResults.updateTarget) + .updateSourceSets(foldedResults.updateModuleIR) + ) else -> buildFile } } @@ -164,6 +176,7 @@ class TemplatesPlugin(context: Context) : Plugin(context) { } SRC_DIR / "${module.name}${filePath.sourcesetType.name.capitalize()}" / directory } + is FakeMultiplatformModuleIR -> error("Not supported for FakeMultiplatformModuleIR") } } } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/projectTemplates/ProjectTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/projectTemplates/ProjectTemplate.kt index da95171e083..e5a4a756c67 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/projectTemplates/ProjectTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/projectTemplates/ProjectTemplate.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ProjectKind import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.templates.* +import org.jetbrains.kotlin.tools.projectWizard.templates.mpp.MobileMppTemplate sealed class ProjectTemplate : DisplayableSettingItem { abstract val title: String @@ -165,7 +166,7 @@ object MultiplatformApplicationProjectTemplate : ProjectTemplate() { override val setsPluginSettings: List> get() = listOf( KotlinPlugin.modules.reference withValue listOf( - MultiplatformModule("mainModule", listOf(ModuleType.common.createDefaultTarget())) + MultiplatformModule("mainModule", targets = listOf(ModuleType.common.createDefaultTarget())) ) ) } @@ -206,7 +207,7 @@ object MultiplatformLibraryProjectTemplate : ProjectTemplate() { KotlinPlugin.modules.reference withValue listOf( MultiplatformModule( "library", - listOf( + targets = listOf( ModuleType.common.createDefaultTarget(), ModuleType.jvm.createDefaultTarget(), ModuleType.js.createDefaultTarget().withConfiguratorSettings(JsBrowserTargetConfigurator) { @@ -231,7 +232,7 @@ object FullStackWebApplicationProjectTemplate : ProjectTemplate() { KotlinPlugin.modules.reference withValue listOf( MultiplatformModule( "application", - listOf( + targets = listOf( ModuleType.common.createDefaultTarget(), ModuleType.jvm.createDefaultTarget().apply { withTemplate(KtorServerTemplate()) { @@ -336,7 +337,8 @@ object MultiplatformMobileApplicationProjectTemplate : ProjectTemplate() { override val setsModules: List = buildList { val shared = MultiplatformModule( "shared", - listOf( + template = MobileMppTemplate(), + targets = listOf( ModuleType.common.createDefaultTarget(), Module( "android", @@ -390,7 +392,7 @@ object MultiplatformMobileLibraryProjectTemplate : ProjectTemplate() { KotlinPlugin.modules.reference withValue listOf( MultiplatformModule( "library", - listOf( + targets = listOf( ModuleType.common.createDefaultTarget(), Module( "android", diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Module.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Module.kt index c0622425642..b27f28e546f 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Module.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Module.kt @@ -185,11 +185,11 @@ fun MultiplatformTargetModule(@NonNls name: String, configurator: ModuleConfigur ) @Suppress("FunctionName") -fun MultiplatformModule(@NonNls name: String, targets: List = emptyList()) = +fun MultiplatformModule(@NonNls name: String, template: Template? = null, targets: List = emptyList()) = Module( name, MppModuleConfigurator, - null, + template, emptyList(), targets ) 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 4d49399ea95..69fe0970837 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.GradleRootProject 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.mpp.mppSources import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData @@ -78,14 +79,12 @@ sealed class ModuleDependencyType( object AndroidSinglePlatformToMPP : ModuleDependencyType( from = AndroidSinglePlatformModuleConfigurator::class, to = MppModuleConfigurator::class - ) { - override fun Writer.runArbitraryTask( - from: Module, - to: Module, - toModulePath: Path, - data: ModulesToIrConversionData - ): TaskResult = addExpectFilesForMppModuleForAndroidAndIos(to, data) - } + ) + + object JVMSinglePlatformToMPP : ModuleDependencyType( + from = JvmSinglePlatformModuleConfigurator::class, + to = MppModuleConfigurator::class + ) object IOSToMppSinglePlatformToMPP : ModuleDependencyType( from = IOSSinglePlatformModuleConfigurator::class, @@ -100,7 +99,6 @@ sealed class ModuleDependencyType( toModulePath: Path, data: ModulesToIrConversionData ): TaskResult = compute { - addExpectFilesForMppModuleForAndroidAndIos(to, data) inContextOfModuleConfigurator(from) { IOSSinglePlatformModuleConfigurator.dependentModule.reference.update { IOSSinglePlatformModuleConfigurator.DependentModuleReference(to).asSuccess() @@ -113,7 +111,7 @@ sealed class ModuleDependencyType( to: Module, toModulePath: Path, ): TaskResult { - val needDummyFile = inContextOfModuleConfigurator(to) { MppModuleConfigurator.mppSources.reference.propertyValue.isEmpty() } + val needDummyFile = false/*TODO*/ return if (needDummyFile) { val dummyFilePath = Defaults.SRC_DIR / "${to.iosTargetSafe()!!.name}Main" / to.configurator.kotlinDirectoryName / "dummyFile.kt" @@ -184,6 +182,7 @@ sealed class ModuleDependencyType( companion object { private val ALL = listOf( JVMSinglePlatformToJVMSinglePlatform, + JVMSinglePlatformToMPP, AndroidSinglePlatformToMPP, IOSToMppSinglePlatformToMPP ) @@ -194,42 +193,4 @@ sealed class ModuleDependencyType( fun isDependencyPossible(from: Module, to: Module): Boolean = getPossibleDependencyType(from, to) != null } -} - -private fun Writer.addExpectFilesForMppModuleForAndroidAndIos(mppModule: Module, data: ModulesToIrConversionData): TaskResult { - val javaPackage = mppModule.javaPackage(data.pomIr) - - val expectFiles = mppSources(javaPackage) { - mppFile("Platform.kt") { - `class`("Platform") { - expectBody = "val platform: String" - actualFor( - ModuleSubType.android, - actualBody = """actual val platform: String = "Android ${'$'}{android.os.Build.VERSION.SDK_INT}"""" - ) - - actualFor( - ModuleSubType.iosArm64, ModuleSubType.iosX64, ModuleSubType.ios, - actualBody = - """actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion""" - ) { - import("platform.UIKit.UIDevice") - } - } - } - - filesFor(ModuleSubType.common) { - file(FileTemplateDescriptor("mppCommon/Greeting.kt.vm", relativePath = null), "Greeting.kt", SourcesetType.main) - } - - filesFor(ModuleSubType.android) { - file(FileTemplateDescriptor("android/androidTest.kt.vm", relativePath = null), "androidTest.kt", SourcesetType.test) - } - - filesFor(ModuleSubType.iosArm64, ModuleSubType.iosX64, ModuleSubType.ios) { - file(FileTemplateDescriptor("ios/iosTest.kt.vm", relativePath = null), "iosTest.kt", SourcesetType.test) - } - - } - return inContextOfModuleConfigurator(mppModule) { MppModuleConfigurator.mppSources.reference.addValues(listOf(expectFiles)) } } \ No newline at end of file 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 2beb63c18e6..5fb3440b05f 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 @@ -13,6 +13,8 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.core.Reader +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module class ConsoleJvmApplicationTemplate : Template() { @NonNls @@ -21,7 +23,9 @@ class ConsoleJvmApplicationTemplate : Template() { override val title: String = KotlinNewProjectWizardBundle.message("module.template.console.jvm.title") override val description: String = KotlinNewProjectWizardBundle.message("module.template.console.jvm.description") - override val moduleTypes: Set = setOf(ModuleType.jvm) + + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator.moduleType == ModuleType.jvm override fun Writer.getIrsToAddToBuildFile( module: ModuleIR diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/JsClientTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/JsClientTemplate.kt index 66fdd0f4694..a347be9aaa9 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/JsClientTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/JsClientTemplate.kt @@ -20,7 +20,8 @@ import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.Templa import org.jetbrains.kotlin.tools.projectWizard.transformers.interceptors.interceptTemplate abstract class JsClientTemplate : Template() { - override val moduleTypes: Set = setOf(ModuleType.js) + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator.moduleType == ModuleType.js override fun isApplicableTo( reader: Reader, 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 index 55fe5158841..30dfbfcc403 100644 --- 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 @@ -18,23 +18,23 @@ 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.transformers.interceptors.InterceptionPoint import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.Versions import org.jetbrains.kotlin.tools.projectWizard.WizardGradleRunConfiguration import org.jetbrains.kotlin.tools.projectWizard.WizardRunConfiguration import org.jetbrains.kotlin.tools.projectWizard.core.Reader +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin -import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind +import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version class KtorServerTemplate : Template() { override val title: String = KotlinNewProjectWizardBundle.message("module.template.ktor.server.title") override val description: String = KotlinNewProjectWizardBundle.message("module.template.ktor.server.description") - override val moduleTypes: Set = setOf(ModuleType.jvm) + + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator.moduleType == ModuleType.jvm @NonNls override val id: String = "ktorServer" diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/NativeConsoleApplicationTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/NativeConsoleApplicationTemplate.kt index df78dccaea4..68dbfc9ca73 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/NativeConsoleApplicationTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/NativeConsoleApplicationTemplate.kt @@ -16,13 +16,16 @@ import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.safeAs import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.NativeTargetConfigurator +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module class NativeConsoleApplicationTemplate : Template() { override val title: String = KotlinNewProjectWizardBundle.message("module.template.native.console.title") override val description: String = KotlinNewProjectWizardBundle.message("module.template.native.console.description") - override val moduleTypes: Set = setOf(ModuleType.native) + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator.moduleType == ModuleType.native + override val id: String = "nativeConsoleApp" override fun isApplicableTo( diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleNodeJsTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleNodeJsTemplate.kt index e876011299c..12acda153c4 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleNodeJsTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleNodeJsTemplate.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.JsNodeTargetConfigurator import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.NodeJsSinglePlatformModuleConfigurator +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository.Companion.JCENTER @@ -26,7 +27,9 @@ class SimpleNodeJsTemplate : Template() { override val description: String = KotlinNewProjectWizardBundle.message("module.template.simple.nodejs.description") - override val moduleTypes: Set = setOf(ModuleType.js) + + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator.moduleType == ModuleType.js @NonNls override val id: String = "simpleNodeJs" 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 b5a50cc271d..48582653fb2 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 @@ -9,15 +9,13 @@ import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.* import org.jetbrains.kotlin.tools.projectWizard.enumSettingImpl -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.ModuleIR -import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.MultiplatformModuleIR +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.RunConfigurationsPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin 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.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version @@ -73,7 +71,8 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet abstract val title: String abstract val description: String - abstract val moduleTypes: Set + + abstract fun isSupportedByModuleType(module: Module): Boolean override val text: String get() = title @@ -100,6 +99,10 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet module: ModuleIR ): List = emptyList() + open fun Writer.runArbitratyTask( + module: ModuleIR + ): TaskResult = UNIT_SUCCESS + open fun updateTargetIr( module: ModuleIR, targetConfigurationIR: TargetConfigurationIR @@ -112,24 +115,39 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet open fun Reader.createRunConfigurations(module: ModuleIR): List = emptyList() + + open fun Reader.updateModuleIR(module: ModuleIR): ModuleIR = module + open fun Reader.updateBuildFileIRs(irs: List): List = irs + + open fun createRootBuildFileIrs(): List = emptyList() + fun Writer.applyToSourceset( module: ModuleIR - ): TaskResult { + ): TaskResult = compute { + val librariesToAdd = getRequiredLibraries(module) val irsToAddToBuildFile = getIrsToAddToBuildFile(module) + runArbitratyTask(module).ensure() val targetsUpdater = when (module) { is MultiplatformModuleIR -> { target: TargetConfigurationIR -> if (target.targetName == module.name) updateTargetIr(module, target) else target } + is FakeMultiplatformModuleIR -> { + module.targets.map { expectedTarget -> + { configurationIR: TargetConfigurationIR -> + if (configurationIR.targetName == expectedTarget.name) updateTargetIr(expectedTarget, configurationIR) + else configurationIR + } + }.reduce(::compose) + } else -> idFunction() } RunConfigurationsPlugin.configurations.addValues(createRunConfigurations(module)) - val result = TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile, targetsUpdater) - return result.asSuccess() + TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile, targetsUpdater) { updateModuleIR(it) } } fun Reader.settingsAsMap(module: Module): Map = mutableMapOf().apply { @@ -290,13 +308,15 @@ fun Writer.applyTemplateToModule( data class TemplateApplicationResult( val librariesToAdd: List, val irsToAddToBuildFile: List, - val updateTarget: (TargetConfigurationIR) -> TargetConfigurationIR + val updateTarget: (TargetConfigurationIR) -> TargetConfigurationIR, + val updateModuleIR: (ModuleIR) -> ModuleIR ) { companion object { val EMPTY = TemplateApplicationResult( librariesToAdd = emptyList(), irsToAddToBuildFile = emptyList(), - updateTarget = { it } + updateTarget = { it }, + updateModuleIR = { it }, ) } } @@ -308,5 +328,6 @@ operator fun TemplateApplicationResult.plus(other: TemplateApplicationResult) = TemplateApplicationResult( librariesToAdd + other.librariesToAdd, irsToAddToBuildFile + other.irsToAddToBuildFile, - updateTarget andThen other.updateTarget + updateTarget andThen other.updateTarget, + updateModuleIR andThen other.updateModuleIR, ) \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/mpp/MobileMppTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/mpp/MobileMppTemplate.kt new file mode 100644 index 00000000000..ac0d5eb8c99 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/mpp/MobileMppTemplate.kt @@ -0,0 +1,82 @@ +/* + * 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.templates.mpp + +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.TaskResult +import org.jetbrains.kotlin.tools.projectWizard.core.Writer +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildSystemIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.RepositoryIR +import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.irsList +import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.MppModuleConfigurator +import org.jetbrains.kotlin.tools.projectWizard.mpp.applyMppStructure +import org.jetbrains.kotlin.tools.projectWizard.mpp.mppSources +import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType +import org.jetbrains.kotlin.tools.projectWizard.plugins.pomIR +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.SourcesetType +import org.jetbrains.kotlin.tools.projectWizard.settings.javaPackage +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor +import org.jetbrains.kotlin.tools.projectWizard.templates.Template + +class MobileMppTemplate : Template() { + @NonNls + override val id: String = "mobileMppModule" + + override val title: String = KotlinNewProjectWizardBundle.message("module.template.mpp.mobile.title") + override val description: String = KotlinNewProjectWizardBundle.message("module.template.mpp.mobile.description") + + override fun isSupportedByModuleType(module: Module): Boolean = + module.configurator == MppModuleConfigurator + + + override fun Writer.getIrsToAddToBuildFile(module: ModuleIR): List = irsList { + +RepositoryIR(DefaultRepository.JCENTER) + } + + override fun Writer.runArbitratyTask(module: ModuleIR): TaskResult { + val javaPackage = module.originalModule.javaPackage(pomIR()) + + val mpp = mppSources(javaPackage) { + mppFile("Platform.kt") { + `class`("Platform") { + expectBody = "val platform: String" + actualFor( + ModuleSubType.android, + actualBody = """actual val platform: String = "Android ${'$'}{android.os.Build.VERSION.SDK_INT}"""" + ) + + actualFor( + ModuleSubType.iosArm64, ModuleSubType.iosX64, ModuleSubType.ios, + actualBody = + """actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion""" + ) { + import("platform.UIKit.UIDevice") + } + } + } + + filesFor(ModuleSubType.common) { + file(FileTemplateDescriptor("mppCommon/Greeting.kt.vm", relativePath = null), "Greeting.kt", SourcesetType.main) + } + + filesFor(ModuleSubType.android) { + file(FileTemplateDescriptor("android/androidTest.kt.vm", relativePath = null), "androidTest.kt", SourcesetType.test) + } + + filesFor(ModuleSubType.iosArm64, ModuleSubType.iosX64, ModuleSubType.ios) { + file(FileTemplateDescriptor("ios/iosTest.kt.vm", relativePath = null), "iosTest.kt", SourcesetType.test) + } + + } + + return applyMppStructure(mpp, module.originalModule, module.path) + } +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/tests/org/jetbrains/kotlin/tools/projectWizard/core/ExpectedFileTest.kt b/libraries/tools/new-project-wizard/tests/org/jetbrains/kotlin/tools/projectWizard/core/ExpectedFileTest.kt index 16418c455e7..49c198266bb 100644 --- a/libraries/tools/new-project-wizard/tests/org/jetbrains/kotlin/tools/projectWizard/core/ExpectedFileTest.kt +++ b/libraries/tools/new-project-wizard/tests/org/jetbrains/kotlin/tools/projectWizard/core/ExpectedFileTest.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.tools.projectWizard.core -import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.mppSources +import org.jetbrains.kotlin.tools.projectWizard.mpp.mppSources import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType import org.junit.Test import kotlin.test.assertEquals