MPP wizard: add common module at the same level with platform ones
Related to KT-23097
This commit is contained in:
+38
-25
@@ -21,7 +21,7 @@ import com.intellij.ide.util.projectWizard.WizardContext
|
|||||||
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep
|
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.roots.ModifiableRootModel
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.roots.ui.configuration.ModulesProvider
|
import com.intellij.openapi.roots.ui.configuration.ModulesProvider
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
@@ -31,40 +31,35 @@ import org.jetbrains.kotlin.idea.util.rootManager
|
|||||||
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
|
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
|
||||||
import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder
|
import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder
|
||||||
import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl
|
import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl
|
||||||
|
import javax.swing.Icon
|
||||||
|
|
||||||
class KotlinGradleMultiplatformModuleBuilder : GradleModuleBuilder() {
|
class KotlinGradleMultiplatformModuleBuilder : GradleModuleBuilder() {
|
||||||
|
var commonModuleName: String? = null
|
||||||
var jvmModuleName: String? = null
|
var jvmModuleName: String? = null
|
||||||
var jsModuleName: String? = null
|
var jsModuleName: String? = null
|
||||||
|
|
||||||
override fun getBuilderId() = "kotlin.gradle.multiplatform"
|
override fun getBuilderId() = "kotlin.gradle.multiplatform"
|
||||||
|
|
||||||
override fun getNodeIcon() = KotlinIcons.MPP
|
override fun getNodeIcon(): Icon = KotlinIcons.MPP
|
||||||
|
|
||||||
override fun getPresentableName() = "Kotlin (Multiplatform - Experimental)"
|
override fun getPresentableName() = "Kotlin (Multiplatform - Experimental)"
|
||||||
|
|
||||||
override fun getDescription() =
|
override fun getDescription() =
|
||||||
"Multiplatform projects allow reusing the same code between multiple platforms supported by Kotlin. Such projects are built with Gradle."
|
"Multiplatform projects allow reusing the same code between multiple platforms supported by Kotlin. Such projects are built with Gradle."
|
||||||
|
|
||||||
override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider): Array<ModuleWizardStep> {
|
override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider): Array<ModuleWizardStep> {
|
||||||
super.createWizardSteps(wizardContext, modulesProvider) // initializes GradleModuleBuilder.myWizardContext
|
super.createWizardSteps(wizardContext, modulesProvider) // initializes GradleModuleBuilder.myWizardContext
|
||||||
return arrayOf(KotlinGradleMultiplatformWizardStep(this, wizardContext),
|
return arrayOf(
|
||||||
ExternalModuleSettingsStep(
|
KotlinGradleMultiplatformWizardStep(this, wizardContext),
|
||||||
wizardContext, this, GradleProjectSettingsControl(externalProjectSettings))
|
ExternalModuleSettingsStep(wizardContext, this, GradleProjectSettingsControl(externalProjectSettings))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupRootModel(modifiableRootModel: ModifiableRootModel) {
|
|
||||||
super.setupRootModel(modifiableRootModel)
|
|
||||||
val module = modifiableRootModel.module
|
|
||||||
val buildScriptData = getBuildScriptData(module) ?: return
|
|
||||||
val sdk = modifiableRootModel.sdk
|
|
||||||
GradleKotlinMPPCommonFrameworkSupportProvider().addSupport(buildScriptData, sdk)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupModule(module: Module) {
|
override fun setupModule(module: Module) {
|
||||||
super.setupModule(module)
|
super.setupModule(module)
|
||||||
|
|
||||||
val contentRoot = module.rootManager.contentRoots.firstOrNull() ?: return
|
val contentRoot = module.rootManager.contentRoots.firstOrNull() ?: return
|
||||||
|
setupCommonModule(module, contentRoot)
|
||||||
setupPlatformModule(module, contentRoot, jvmModuleName, GradleKotlinMPPJavaFrameworkSupportProvider())
|
setupPlatformModule(module, contentRoot, jvmModuleName, GradleKotlinMPPJavaFrameworkSupportProvider())
|
||||||
setupPlatformModule(module, contentRoot, jsModuleName, GradleKotlinMPPJSFrameworkSupportProvider())
|
setupPlatformModule(module, contentRoot, jsModuleName, GradleKotlinMPPJSFrameworkSupportProvider())
|
||||||
|
|
||||||
@@ -72,24 +67,42 @@ class KotlinGradleMultiplatformModuleBuilder : GradleModuleBuilder() {
|
|||||||
settingsGradle?.let {
|
settingsGradle?.let {
|
||||||
module.project.executeCommand("Update settings.gradle") {
|
module.project.executeCommand("Update settings.gradle") {
|
||||||
val doc = FileDocumentManager.getInstance().getDocument(it) ?: return@executeCommand
|
val doc = FileDocumentManager.getInstance().getDocument(it) ?: return@executeCommand
|
||||||
doc.insertString(doc.textLength, "include '$jvmModuleName', '$jsModuleName'")
|
val commonPrefix = commonModuleName?.let { "'$it', " } ?: ""
|
||||||
|
doc.insertString(doc.textLength, "include $commonPrefix'$jvmModuleName', '$jsModuleName'")
|
||||||
FileDocumentManager.getInstance().saveDocument(doc)
|
FileDocumentManager.getInstance().saveDocument(doc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupPlatformModule(module: Module,
|
private fun setupChildModule(
|
||||||
contentRoot: VirtualFile,
|
rootModule: Module,
|
||||||
platformModuleName: String?,
|
contentRoot: VirtualFile,
|
||||||
supportProvider: GradleKotlinFrameworkSupportProvider) {
|
childModuleName: String?,
|
||||||
if (platformModuleName.isNullOrEmpty()) return
|
extendScript: (BuildScriptDataBuilder, Sdk?) -> Unit = { _, _ -> }
|
||||||
|
) {
|
||||||
val sdk = module.rootManager.sdk
|
if (childModuleName.isNullOrEmpty()) return
|
||||||
val moduleDir = contentRoot.createChildDirectory(this, platformModuleName!!)
|
val moduleDir = contentRoot.createChildDirectory(this, childModuleName!!)
|
||||||
val buildGradle = moduleDir.createChildData(null, "build.gradle")
|
val buildGradle = moduleDir.createChildData(null, "build.gradle")
|
||||||
val buildScriptData = BuildScriptDataBuilder(buildGradle)
|
val buildScriptData = BuildScriptDataBuilder(buildGradle)
|
||||||
supportProvider.addSupport(buildScriptData, sdk)
|
extendScript(buildScriptData, rootModule.rootManager.sdk)
|
||||||
buildScriptData.addDependencyNotation("expectedBy project(\":\")")
|
|
||||||
VfsUtil.saveText(buildGradle, buildScriptData.buildConfigurationPart() + buildScriptData.buildMainPart())
|
VfsUtil.saveText(buildGradle, buildScriptData.buildConfigurationPart() + buildScriptData.buildMainPart())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupCommonModule(
|
||||||
|
rootModule: Module,
|
||||||
|
contentRoot: VirtualFile
|
||||||
|
) = setupChildModule(rootModule, contentRoot, commonModuleName) { builder, sdk ->
|
||||||
|
GradleKotlinMPPCommonFrameworkSupportProvider().addSupport(builder, sdk)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupPlatformModule(
|
||||||
|
rootModule: Module,
|
||||||
|
contentRoot: VirtualFile,
|
||||||
|
platformModuleName: String?,
|
||||||
|
supportProvider: GradleKotlinFrameworkSupportProvider
|
||||||
|
) = setupChildModule(rootModule, contentRoot, platformModuleName) { builder, sdk ->
|
||||||
|
supportProvider.addSupport(builder, sdk)
|
||||||
|
val dependency = commonModuleName ?: ""
|
||||||
|
builder.addDependencyNotation("expectedBy project(\":$dependency\")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-18
@@ -37,8 +37,10 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
private val wizardContext: WizardContext
|
private val wizardContext: WizardContext
|
||||||
) : ModuleWizardStep() {
|
) : ModuleWizardStep() {
|
||||||
|
|
||||||
private val mainModuleNameComponent: LabeledComponent<JTextField> =
|
private val rootModuleNameComponent: LabeledComponent<JTextField> =
|
||||||
LabeledComponent.create(JTextField(), "Main module name:", BorderLayout.WEST)
|
LabeledComponent.create(JTextField(), "Root module name:", BorderLayout.WEST)
|
||||||
|
private val commonModuleNameComponent: LabeledComponent<JTextField> =
|
||||||
|
LabeledComponent.create(JTextField(), "Common module name:", BorderLayout.WEST)
|
||||||
private val jvmModuleNameComponent: LabeledComponent<JTextField> =
|
private val jvmModuleNameComponent: LabeledComponent<JTextField> =
|
||||||
LabeledComponent.create(JTextField(), "JVM module name:", BorderLayout.WEST)
|
LabeledComponent.create(JTextField(), "JVM module name:", BorderLayout.WEST)
|
||||||
private val jsModuleNameComponent: LabeledComponent<JTextField> =
|
private val jsModuleNameComponent: LabeledComponent<JTextField> =
|
||||||
@@ -50,13 +52,14 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
panel = object : JPanel(GridBagLayout()), PanelWithAnchor {
|
panel = object : JPanel(GridBagLayout()), PanelWithAnchor {
|
||||||
private var anchor: JComponent? = mainModuleNameComponent.anchor
|
private var anchor: JComponent? = rootModuleNameComponent.anchor
|
||||||
|
|
||||||
override fun getAnchor(): JComponent? = anchor
|
override fun getAnchor(): JComponent? = anchor
|
||||||
|
|
||||||
override fun setAnchor(anchor: JComponent?) {
|
override fun setAnchor(anchor: JComponent?) {
|
||||||
this.anchor = anchor
|
this.anchor = anchor
|
||||||
mainModuleNameComponent.anchor = anchor
|
rootModuleNameComponent.anchor = anchor
|
||||||
|
commonModuleNameComponent.anchor = anchor
|
||||||
jvmModuleNameComponent.anchor = anchor
|
jvmModuleNameComponent.anchor = anchor
|
||||||
jsModuleNameComponent.anchor = anchor
|
jsModuleNameComponent.anchor = anchor
|
||||||
}
|
}
|
||||||
@@ -64,12 +67,12 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
val baseDir = wizardContext.projectFileDirectory
|
val baseDir = wizardContext.projectFileDirectory
|
||||||
val projectName = wizardContext.projectName
|
val projectName = wizardContext.projectName
|
||||||
val initialProjectName = projectName ?: ProjectWizardUtil.findNonExistingFileName(baseDir, "untitled", "")
|
val initialProjectName = projectName ?: ProjectWizardUtil.findNonExistingFileName(baseDir, "untitled", "")
|
||||||
mainModuleNameComponent.component.text = initialProjectName
|
rootModuleNameComponent.component.text = initialProjectName
|
||||||
mainModuleNameComponent.component.select(0, initialProjectName.length)
|
rootModuleNameComponent.component.select(0, initialProjectName.length)
|
||||||
|
|
||||||
updateDerivedModuleNames()
|
updateDerivedModuleNames()
|
||||||
|
|
||||||
mainModuleNameComponent.component.document.addDocumentListener(object : DocumentAdapter() {
|
rootModuleNameComponent.component.document.addDocumentListener(object : DocumentAdapter() {
|
||||||
override fun textChanged(e: DocumentEvent?) {
|
override fun textChanged(e: DocumentEvent?) {
|
||||||
if (syncEditing) {
|
if (syncEditing) {
|
||||||
updateDerivedModuleNames()
|
updateDerivedModuleNames()
|
||||||
@@ -84,18 +87,27 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
commonModuleNameComponent.component.document.addDocumentListener(stopSyncEditingListener)
|
||||||
jvmModuleNameComponent.component.document.addDocumentListener(stopSyncEditingListener)
|
jvmModuleNameComponent.component.document.addDocumentListener(stopSyncEditingListener)
|
||||||
jsModuleNameComponent.component.document.addDocumentListener(stopSyncEditingListener)
|
jsModuleNameComponent.component.document.addDocumentListener(stopSyncEditingListener)
|
||||||
|
|
||||||
panel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
panel.border = BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
||||||
panel.add(
|
panel.add(
|
||||||
mainModuleNameComponent,
|
rootModuleNameComponent,
|
||||||
GridBagConstraints(
|
GridBagConstraints(
|
||||||
0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
|
0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
|
||||||
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
|
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
|
||||||
JBUI.insets(10, 0, 0, 0), 0, 0
|
JBUI.insets(10, 0, 0, 0), 0, 0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
panel.add(
|
||||||
|
commonModuleNameComponent,
|
||||||
|
GridBagConstraints(
|
||||||
|
0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
|
||||||
|
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
|
||||||
|
JBUI.emptyInsets(), 0, 0
|
||||||
|
)
|
||||||
|
)
|
||||||
panel.add(
|
panel.add(
|
||||||
jvmModuleNameComponent,
|
jvmModuleNameComponent,
|
||||||
GridBagConstraints(
|
GridBagConstraints(
|
||||||
@@ -126,8 +138,9 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
private fun updateDerivedModuleNames() {
|
private fun updateDerivedModuleNames() {
|
||||||
inSyncUpdate = true
|
inSyncUpdate = true
|
||||||
try {
|
try {
|
||||||
jvmModuleNameComponent.component.text = "$mainModuleName-jvm"
|
commonModuleNameComponent.component.text = "$rootModuleName-common"
|
||||||
jsModuleNameComponent.component.text = "$mainModuleName-js"
|
jvmModuleNameComponent.component.text = "$rootModuleName-jvm"
|
||||||
|
jsModuleNameComponent.component.text = "$rootModuleName-js"
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
inSyncUpdate = false
|
inSyncUpdate = false
|
||||||
@@ -136,30 +149,38 @@ class KotlinGradleMultiplatformWizardStep(
|
|||||||
|
|
||||||
override fun updateDataModel() {
|
override fun updateDataModel() {
|
||||||
wizardContext.projectBuilder = builder
|
wizardContext.projectBuilder = builder
|
||||||
wizardContext.projectName = mainModuleName
|
wizardContext.projectName = rootModuleName
|
||||||
|
|
||||||
builder.projectId = ProjectId("", mainModuleName, "")
|
builder.projectId = ProjectId("", rootModuleName, "")
|
||||||
|
builder.commonModuleName = commonModuleName
|
||||||
builder.jvmModuleName = jvmModuleName
|
builder.jvmModuleName = jvmModuleName
|
||||||
builder.jsModuleName = jsModuleName
|
builder.jsModuleName = jsModuleName
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getComponent() = panel
|
override fun getComponent() = panel
|
||||||
|
|
||||||
private val mainModuleName: String
|
private val rootModuleName: String
|
||||||
get() = mainModuleNameComponent.component.text
|
get() = rootModuleNameComponent.component.text
|
||||||
|
private val commonModuleName: String
|
||||||
|
get() = commonModuleNameComponent.component.text
|
||||||
private val jvmModuleName: String
|
private val jvmModuleName: String
|
||||||
get() = jvmModuleNameComponent.component.text
|
get() = jvmModuleNameComponent.component.text
|
||||||
private val jsModuleName: String
|
private val jsModuleName: String
|
||||||
get() = jsModuleNameComponent.component.text
|
get() = jsModuleNameComponent.component.text
|
||||||
|
|
||||||
override fun validate(): Boolean {
|
override fun validate(): Boolean {
|
||||||
if (mainModuleName.isEmpty()) {
|
if (rootModuleName.isEmpty()) {
|
||||||
throw ConfigurationException("Please specify the main module name")
|
throw ConfigurationException("Please specify the root module name")
|
||||||
}
|
}
|
||||||
if (jvmModuleName.isNotEmpty() && (jvmModuleName == mainModuleName || jvmModuleName == jsModuleName)) {
|
if (commonModuleName.isNotEmpty()
|
||||||
|
&& (commonModuleName == rootModuleName || commonModuleName == jvmModuleName || commonModuleName == jsModuleName)
|
||||||
|
) {
|
||||||
|
throw ConfigurationException("The common module name should be distinct")
|
||||||
|
}
|
||||||
|
if (jvmModuleName.isNotEmpty() && (jvmModuleName == rootModuleName || jvmModuleName == jsModuleName)) {
|
||||||
throw ConfigurationException("The JVM module name should be distinct")
|
throw ConfigurationException("The JVM module name should be distinct")
|
||||||
}
|
}
|
||||||
if (jsModuleName.isNotEmpty() && jsModuleName == mainModuleName) {
|
if (jsModuleName.isNotEmpty() && jsModuleName == rootModuleName) {
|
||||||
throw ConfigurationException("The IS module name should be distinct")
|
throw ConfigurationException("The IS module name should be distinct")
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
Reference in New Issue
Block a user