Wizard: introduce ServicesManager & correctly handle disabled gradle & maven Idea plugins

This commit is contained in:
Ilya Kirillov
2019-12-12 20:22:30 +03:00
parent 9011eecfdf
commit f927fb3471
41 changed files with 361 additions and 279 deletions
@@ -4,16 +4,24 @@ import org.jetbrains.kotlin.tools.projectWizard.core.PluginsCreator
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.Service import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
import org.jetbrains.kotlin.tools.projectWizard.wizard.service.IdeaWizardService
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class IdeWizard( class IdeWizard(
createPlugins: PluginsCreator, createPlugins: PluginsCreator,
initialServices: List<Service> initialServices: List<WizardService>
) : Wizard(createPlugins, initialServices) { ) : Wizard(
createPlugins,
ServicesManager(initialServices) { services ->
services.firstOrNull { it is IdeaWizardService }
?: services.firstOrNull()
}
) {
private val allSettings = plugins.flatMap { it.declaredSettings } private val allSettings = plugins.flatMap { it.declaredSettings }
init { init {
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.Plugins import org.jetbrains.kotlin.tools.projectWizard.plugins.Plugins
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin
import org.jetbrains.kotlin.tools.projectWizard.wizard.service.*
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.PomWizardStepComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.PomWizardStepComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep.FirstWizardStepComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep.FirstWizardStepComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.SecondStepWizardComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.SecondStepWizardComponent
@@ -34,7 +35,7 @@ import com.intellij.openapi.module.Module as IdeaModule
class NewProjectWizardModuleBuilder : ModuleBuilder() { class NewProjectWizardModuleBuilder : ModuleBuilder() {
private val wizard = IdeWizard(Plugins.allPlugins, listOf(IdeaAndroidService())) private val wizard = IdeWizard(Plugins.allPlugins, IdeaServices.PROJECT_INDEPENDENT)
companion object { companion object {
const val MODULE_BUILDER_ID = "kotlin.newProjectWizard.builder" const val MODULE_BUILDER_ID = "kotlin.newProjectWizard.builder"
@@ -62,13 +63,8 @@ class NewProjectWizardModuleBuilder : ModuleBuilder() {
): List<IdeaModule>? { ): List<IdeaModule>? {
val modulesModel = model ?: ModuleManager.getInstance(project).modifiableModel val modulesModel = model ?: ModuleManager.getInstance(project).modifiableModel
val success = wizard.apply( val success = wizard.apply(
services = listOf( services = IdeaServices.createScopeDependent(project, modulesModel) +
IdeaMavenService(project), IdeaServices.PROJECT_INDEPENDENT,
IdeaGradleService(project),
IdeaJpsService(project, modulesModel),
IdeaFileSystemService(),
IdeaAndroidService()
),
phases = GenerationPhase.startingFrom(GenerationPhase.FIRST_STEP) phases = GenerationPhase.startingFrom(GenerationPhase.FIRST_STEP)
).onFailure { errors -> ).onFailure { errors ->
val errorMessages = errors.joinToString(separator = "\n") { it.message } val errorMessages = errors.joinToString(separator = "\n") { it.message }
@@ -1,91 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.android.sdk.AndroidSdkData
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.*
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import org.jetbrains.plugins.gradle.action.ImportProjectFromScriptAction
import java.nio.file.Path
class IdeaFileSystemService : FileSystemService {
override fun createDirectory(path: Path): TaskResult<Unit> = safe {
runWriteAction<Unit> {
VfsUtil.createDirectoryIfMissing(path.toString())
}
}
override fun createFile(path: Path, text: String): TaskResult<Unit> = safe {
runWriteAction {
val directoryPath = path.parent
val directory = VfsUtil.createDirectoryIfMissing(directoryPath.toFile().toString())!!
val virtualFile = directory.createChildData(this, path.fileName.toString())
VfsUtil.saveText(virtualFile, text)
}
}
}
class IdeaGradleService(private val project: Project) : GradleService {
// We have to call action directly as there is no common way
// to import Gradle project in all IDEAs from 183 to 193
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
): TaskResult<Unit> = safe {
val virtualFile = LocalFileSystem.getInstance().findFileByPath(path.toString())!!
val dataContext = SimpleDataContext.getSimpleContext(
mapOf(
CommonDataKeys.PROJECT.name to project,
CommonDataKeys.VIRTUAL_FILE.name to virtualFile
),
null
)
val action = ImportProjectFromScriptAction()
val event = AnActionEvent.createFromAnAction(action, null, ActionPlaces.UNKNOWN, dataContext)
action.actionPerformed(event)
}
}
class IdeaMavenService(private val project: Project) : MavenService {
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
): TaskResult<Unit> = safe {
val mavenProjectManager = MavenProjectsManager.getInstance(project)
val rootFile = LocalFileSystem.getInstance().findFileByPath(path.toString())!!
mavenProjectManager.addManagedFilesOrUnignore(rootFile.findAllPomFiles())
}
private fun VirtualFile.findAllPomFiles(): List<VirtualFile> {
val result = mutableListOf<VirtualFile>()
fun VirtualFile.find() {
when {
!isDirectory && name == "pom.xml" -> result += this
isDirectory -> children.forEach(VirtualFile::find)
}
}
find()
return result
}
}
class IdeaAndroidService : AndroidService {
override fun isValidAndroidSdk(path: Path): Boolean =
//todo use android plugin for that?
AndroidServiceImpl().isValidAndroidSdk(path)
}
@@ -0,0 +1,19 @@
/*
* 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.wizard.service
import com.intellij.ide.plugins.PluginManagerCore
import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemAvailabilityWizardService
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
class IdeaBuildSystemAvailabilityWizardService : BuildSystemAvailabilityWizardService, IdeaWizardService {
override fun isAvailable(buildSystemType: BuildSystemType): Boolean = when {
buildSystemType.isGradle -> !PluginManagerCore.isDisabled("org.jetbrains.plugins.gradle")
buildSystemType == BuildSystemType.Maven -> !PluginManagerCore.isDisabled("org.jetbrains.idea.maven")
else -> true
}
}
@@ -0,0 +1,31 @@
/*
* 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.wizard.service
import com.intellij.openapi.vfs.VfsUtil
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import java.nio.file.Path
class IdeaFileSystemWizardService : FileSystemWizardService, IdeaWizardService {
override fun createDirectory(path: Path): TaskResult<Unit> = safe {
runWriteAction<Unit> {
VfsUtil.createDirectoryIfMissing(path.toString())
}
}
override fun createFile(path: Path, text: String): TaskResult<Unit> = safe {
runWriteAction {
val directoryPath = path.parent
val directory =
VfsUtil.createDirectoryIfMissing(directoryPath.toFile().toString())!!
val virtualFile = directory.createChildData(this, path.fileName.toString())
VfsUtil.saveText(virtualFile, text)
}
}
}
@@ -0,0 +1,51 @@
/*
* 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.wizard.service
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
import org.jetbrains.plugins.gradle.action.ImportProjectFromScriptAction
import java.nio.file.Path
class IdeaGradleWizardService(private val project: Project) : ProjectImportingWizardService,
IdeaWizardService {
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
buildSystemType.isGradle
// We have to call action directly as there is no common way
// to import Gradle project in all IDEAs from 183 to 193
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
): TaskResult<Unit> = safe {
val virtualFile = LocalFileSystem.getInstance().findFileByPath(path.toString())!!
val dataContext = SimpleDataContext.getSimpleContext(
mapOf(
CommonDataKeys.PROJECT.name to project,
CommonDataKeys.VIRTUAL_FILE.name to virtualFile
),
null
)
val action = ImportProjectFromScriptAction()
val event = AnActionEvent.createFromAnAction(
action,
null,
ActionPlaces.UNKNOWN,
dataContext
)
action.actionPerformed(event)
}
}
@@ -1,4 +1,9 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard /*
* 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.wizard.service
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix
import com.intellij.jarRepository.JarRepositoryManager import com.intellij.jarRepository.JarRepositoryManager
@@ -9,7 +14,6 @@ import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.PathUtil import com.intellij.util.PathUtil
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties
@@ -19,19 +23,24 @@ import org.jetbrains.kotlin.config.TestResourceKotlinRootType
import org.jetbrains.kotlin.config.TestSourceKotlinRootType import org.jetbrains.kotlin.config.TestSourceKotlinRootType
import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.JpsService import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact import org.jetbrains.kotlin.tools.projectWizard.library.MavenArtifact
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetType
import java.nio.file.Path import java.nio.file.Path
import com.intellij.openapi.module.Module as IdeaModule import com.intellij.openapi.module.Module as IdeaModule
class IdeaJpsService( class IdeaJpsWizardService(
private val project: Project, private val project: Project,
private val modulesModel: ModifiableModuleModel private val modulesModel: ModifiableModuleModel
) : JpsService { ) : ProjectImportingWizardService, IdeaWizardService {
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
buildSystemType == BuildSystemType.Jps
override fun importProject(path: Path, modulesIrs: List<ModuleIR>): TaskResult<Unit> = runWriteAction { override fun importProject(path: Path, modulesIrs: List<ModuleIR>): TaskResult<Unit> = runWriteAction {
ProjectImporter(project, modulesModel, path, modulesIrs).import() ProjectImporter(project, modulesModel, path, modulesIrs)
.import()
} }
} }
@@ -47,7 +56,6 @@ private class ProjectImporter(
fun import() = modulesIrs.mapSequence { convertModule(it) } andThen fun import() = modulesIrs.mapSequence { convertModule(it) } andThen
safe { modulesModel.commit() } safe { modulesModel.commit() }
private fun convertModule(moduleIr: ModuleIR): TaskResult<IdeaModule> { private fun convertModule(moduleIr: ModuleIR): TaskResult<IdeaModule> {
val module = modulesModel.newModule( val module = modulesModel.newModule(
(moduleIr.path / "${moduleIr.name}.iml").toString(), (moduleIr.path / "${moduleIr.name}.iml").toString(),
@@ -0,0 +1,47 @@
/*
* 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.wizard.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import java.nio.file.Path
class IdeaMavenWizardService(private val project: Project) : ProjectImportingWizardService,
IdeaWizardService {
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
buildSystemType == BuildSystemType.Maven
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
): TaskResult<Unit> = safe {
val mavenProjectManager = MavenProjectsManager.getInstance(project)
val rootFile = LocalFileSystem.getInstance().findFileByPath(path.toString())!!
mavenProjectManager.addManagedFilesOrUnignore(rootFile.findAllPomFiles())
}
private fun VirtualFile.findAllPomFiles(): List<VirtualFile> {
val result = mutableListOf<VirtualFile>()
fun VirtualFile.find() {
when {
!isDirectory && name == "pom.xml" -> result += this
isDirectory -> children.forEach(VirtualFile::find)
}
}
find()
return result
}
}
@@ -0,0 +1,27 @@
/*
* 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.wizard.service
import com.intellij.openapi.module.ModifiableModuleModel
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService
interface IdeaWizardService : WizardService
object IdeaServices {
val PROJECT_INDEPENDENT: List<IdeaWizardService> = listOf(
IdeaFileSystemWizardService(),
IdeaBuildSystemAvailabilityWizardService()
)
fun createScopeDependent(project: Project, model: ModifiableModuleModel) = listOf(
IdeaGradleWizardService(project),
IdeaMavenWizardService(project),
IdeaJpsWizardService(project, model)
)
}
@@ -22,8 +22,9 @@ import javax.swing.JList
class DropDownComponent<T : DisplayableSettingItem>( class DropDownComponent<T : DisplayableSettingItem>(
private val valuesReadingContext: ValuesReadingContext, private val valuesReadingContext: ValuesReadingContext,
initialValues: List<T> = emptyList(), private val initialValues: List<T> = emptyList(),
labelText: String? = null, labelText: String? = null,
private val filter: (T) -> Boolean = { true },
private val validator: SettingValidator<T> = settingValidator { ValidationResult.OK }, private val validator: SettingValidator<T> = settingValidator { ValidationResult.OK },
private val iconProvider: (T) -> Icon? = { null }, private val iconProvider: (T) -> Icon? = { null },
private val onAnyValueUpdate: (T) -> Unit = {} private val onAnyValueUpdate: (T) -> Unit = {}
@@ -42,7 +43,7 @@ class DropDownComponent<T : DisplayableSettingItem>(
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private val comboBox = ComboBox<T>(initialValues.toTypedArray<DisplayableSettingItem>() as Array<T>).apply { private val comboBox = ComboBox<T>().apply {
renderer = object : ColoredListCellRenderer<T>() { renderer = object : ColoredListCellRenderer<T>() {
override fun customizeCellRenderer( override fun customizeCellRenderer(
list: JList<out T>, list: JList<out T>,
@@ -76,13 +77,23 @@ class DropDownComponent<T : DisplayableSettingItem>(
} }
} }
fun updateValues(newValues: List<T>) = withoutActionFiring { override fun onInit() {
val oldValue = comboBox.selectedItem super.onInit()
@Suppress("UNCHECKED_CAST") updateValues(initialValues)
comboBox.model = DefaultComboBoxModel(newValues.toTypedArray<DisplayableSettingItem>() as Array<T>) }
if (newValues.isNotEmpty() && oldValue !in newValues) { fun updateValues(newValues: List<T>) {
value = newValues.first() val newValuesFiltered = newValues.filter(filter)
val oldValue = comboBox.selectedItem
withoutActionFiring {
@Suppress("UNCHECKED_CAST")
comboBox.model = DefaultComboBoxModel(newValuesFiltered.toTypedArray<DisplayableSettingItem>() as Array<T>)
}
if (oldValue !in newValuesFiltered) {
newValuesFiltered.firstOrNull()?.let { newValue ->
value = newValuesFiltered.first()
}
} }
} }
@@ -106,13 +117,6 @@ class DropDownComponent<T : DisplayableSettingItem>(
} }
} }
init {
initialValues.firstOrNull()?.let { first ->
value = first
validate(first)
}
}
fun validate(value: T = this.value) { fun validate(value: T = this.value) {
validationIndicator.validationState = validator.validate(valuesReadingContext, value) validationIndicator.validationState = validator.validate(valuesReadingContext, value)
} }
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import icons.GradleIcons import icons.GradleIcons
import icons.MavenIcons import icons.MavenIcons
import icons.OpenapiIcons
import org.jetbrains.kotlin.tools.projectWizard.core.entity.DropDownSettingType import org.jetbrains.kotlin.tools.projectWizard.core.entity.DropDownSettingType
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
@@ -18,7 +19,7 @@ import java.awt.BorderLayout
class BuildSystemTypeSettingComponent( class BuildSystemTypeSettingComponent(
valuesReadingContext: ValuesReadingContext private val valuesReadingContext: ValuesReadingContext
) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>( ) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
BuildSystemPlugin::type.reference, BuildSystemPlugin::type.reference,
valuesReadingContext valuesReadingContext
@@ -28,6 +29,7 @@ class BuildSystemTypeSettingComponent(
valuesReadingContext, valuesReadingContext,
setting.type.values, setting.type.values,
labelText = "Build System", labelText = "Build System",
filter = { value -> setting.type.filter(valuesReadingContext, reference, value) },
validator = setting.validator, validator = setting.validator,
iconProvider = BuildSystemType::icon, iconProvider = BuildSystemType::icon,
onAnyValueUpdate = { value = it } onAnyValueUpdate = { value = it }
@@ -51,6 +53,6 @@ private val BuildSystemType.icon
get() = when (this) { get() = when (this) {
BuildSystemType.GradleKotlinDsl -> GradleIcons.Gradle BuildSystemType.GradleKotlinDsl -> GradleIcons.Gradle
BuildSystemType.GradleGroovyDsl -> GradleIcons.Gradle BuildSystemType.GradleGroovyDsl -> GradleIcons.Gradle
BuildSystemType.Maven -> MavenIcons.MavenLogo BuildSystemType.Maven -> OpenapiIcons.RepositoryLibraryLogo
BuildSystemType.Jps -> AllIcons.Nodes.Module BuildSystemType.Jps -> AllIcons.Nodes.Module
} }
@@ -100,7 +100,7 @@ class VersionSettingComponent(
class DropdownSettingComponent( class DropdownSettingComponent(
reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>, reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
valuesReadingContext: ValuesReadingContext private val valuesReadingContext: ValuesReadingContext
) : DefaultSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>( ) : DefaultSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>(
reference, reference,
valuesReadingContext valuesReadingContext
@@ -108,22 +108,13 @@ class DropdownSettingComponent(
private val dropDownComponent = DropDownComponent( private val dropDownComponent = DropDownComponent(
valuesReadingContext, valuesReadingContext,
setting.type.values, setting.type.values,
filter = { value -> setting.type.filter(valuesReadingContext, reference, value) },
labelText = setting.title, labelText = setting.title,
onAnyValueUpdate = { newValue -> onAnyValueUpdate = { newValue ->
value = newValue value = newValue
} }
).asSubComponent() ).asSubComponent()
override fun onInit() {
super.onInit()
val valuesFiltered = setting.type.values.filter { setting.type.filter(reference, it) }
dropDownComponent.updateValues(valuesFiltered)
if (valuesFiltered.isNotEmpty()) {
value = valuesFiltered.first()
}
}
override val validationIndicator: ValidationIndicator? = null override val validationIndicator: ValidationIndicator? = null
override val component: JComponent = dropDownComponent.component override val component: JComponent = dropDownComponent.component
} }
@@ -5,8 +5,7 @@ import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask
import org.jetbrains.kotlin.tools.projectWizard.core.entity.PluginSettingReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.PluginSettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.AndroidServiceImpl import org.jetbrains.kotlin.tools.projectWizard.core.service.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.Service
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
@@ -16,9 +15,14 @@ class YamlWizard(
private val yaml: String, private val yaml: String,
private val path: String, private val path: String,
createPlugins: (Context) -> List<Plugin> createPlugins: (Context) -> List<Plugin>
) : Wizard(createPlugins, listOf(AndroidServiceImpl())) { ) : Wizard(
createPlugins,
ServicesManager(Services.IDEA_INDEPENDENT_SERVICES) { services ->
services.firstOrNull { it is IdeaIndependentWizardService }
}
) {
override fun apply( override fun apply(
services: List<Service>, services: List<WizardService>,
phases: Set<GenerationPhase>, phases: Set<GenerationPhase>,
onTaskExecuting: (PipelineTask) -> Unit onTaskExecuting: (PipelineTask) -> Unit
): TaskResult<Unit> = computeM { ): TaskResult<Unit> = computeM {
@@ -38,5 +42,5 @@ class YamlWizard(
get() = pluginSettings.mapNotNull { setting -> get() = pluginSettings.mapNotNull { setting ->
val defaultValue = setting.defaultValue ?: return@mapNotNull null val defaultValue = setting.defaultValue ?: return@mapNotNull null
PluginSettingReference(setting) to defaultValue PluginSettingReference(setting) to defaultValue
} .toMap() }.toMap()
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.tools.projectWizard.cli package org.jetbrains.kotlin.tools.projectWizard.cli
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.kotlin.tools.projectWizard.core.ExceptionError import org.jetbrains.kotlin.tools.projectWizard.core.ExceptionError
import org.jetbrains.kotlin.tools.projectWizard.core.div import org.jetbrains.kotlin.tools.projectWizard.core.div
import org.jetbrains.kotlin.tools.projectWizard.core.onFailure import org.jetbrains.kotlin.tools.projectWizard.core.onFailure
@@ -20,7 +19,6 @@ import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
abstract class AbstractBuildFileGenerationTest : AbstractPluginBasedTest() { abstract class AbstractBuildFileGenerationTest : AbstractPluginBasedTest() {
fun doTest(directoryPath: String) { fun doTest(directoryPath: String) {
val directory = Paths.get(directoryPath) val directory = Paths.get(directoryPath)
val testData = init(directory) val testData = init(directory)
@@ -41,7 +39,7 @@ abstract class AbstractBuildFileGenerationTest : AbstractPluginBasedTest() {
buildSystem.yaml buildSystem.yaml
val tempDir = Files.createTempDirectory(null) val tempDir = Files.createTempDirectory(null)
val wizard = YamlWizard(yaml, tempDir.toString(), testData.createPlugins) val wizard = YamlWizard(yaml, tempDir.toString(), testData.createPlugins)
val result = wizard.apply(Services.osServices, GenerationPhase.ALL) val result = wizard.apply(Services.IDEA_INDEPENDENT_SERVICES, GenerationPhase.ALL)
result.onFailure { errors -> result.onFailure { errors ->
errors.forEach { error -> errors.forEach { error ->
if (error is ExceptionError) { if (error is ExceptionError) {
@@ -3,7 +3,6 @@ package org.jetbrains.kotlin.tools.projectWizard.core
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
@@ -3,11 +3,12 @@ package org.jetbrains.kotlin.tools.projectWizard.core
import org.jetbrains.kotlin.tools.projectWizard.core.entity.PropertyReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.PropertyReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.Task1 import org.jetbrains.kotlin.tools.projectWizard.core.entity.Task1
import org.jetbrains.kotlin.tools.projectWizard.core.entity.Task1Reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.Task1Reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.Service import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
class TaskRunningContext(context: Context, services: List<Service>) : ValuesReadingContext(context, services) { class TaskRunningContext(
context: Context,
servicesManager: ServicesManager
) : ValuesReadingContext(context, servicesManager) {
fun <A, B : Any> Task1Reference<A, B>.execute(value: A): TaskResult<B> { fun <A, B : Any> Task1Reference<A, B>.execute(value: A): TaskResult<B> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val task = context.taskContext.getEntity(this) as Task1<A, B> val task = context.taskContext.getEntity(this) as Task1<A, B>
@@ -30,4 +31,3 @@ class TaskRunningContext(context: Context, services: List<Service>) : ValuesRead
values: List<T> values: List<T>
): TaskResult<Unit> = update { oldValues -> success(oldValues + values) } ): TaskResult<Unit> = update { oldValues -> success(oldValues + values) }
} }
@@ -1,19 +1,17 @@
package org.jetbrains.kotlin.tools.projectWizard.core package org.jetbrains.kotlin.tools.projectWizard.core
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.Service import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.jvm.jvmName
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
open class ValuesReadingContext(val context: Context, private val services: List<Service>) { open class ValuesReadingContext(val context: Context, private val servicesManager: ServicesManager) {
inline fun <reified S : Service> service() = serviceByClass(S::class) inline fun <reified S : WizardService> service(noinline filter: (S) -> Boolean = { true }) = serviceByClass(S::class, filter)
@Suppress("UNCHECKED_CAST") fun <S : WizardService> serviceByClass(klass: KClass<S>, filter: (S) -> Boolean = { true }) =
fun <S : Service> serviceByClass(klass: KClass<S>) = servicesManager.serviceByClass(klass, filter)
services.firstOrNull { it::class.isSubclassOf(klass) } as? S ?: error("No service ${klass.jvmName}")
inline val <reified T : Any> PropertyReference<T>.propertyValue: T inline val <reified T : Any> PropertyReference<T>.propertyValue: T
get() = context.propertyContext[this] as T get() = context.propertyContext[this] as T
@@ -277,7 +277,7 @@ class DropDownSettingType<V : DisplayableSettingItem>(
} }
} }
typealias DropDownSettingTypeFilter<V> = (SettingReference<V, DropDownSettingType<V>>, V) -> Boolean typealias DropDownSettingTypeFilter<V> = ValuesReadingContext.(SettingReference<V, DropDownSettingType<V>>, V) -> Boolean
class ValueSettingType<V : Any>( class ValueSettingType<V : Any>(
@@ -2,11 +2,11 @@ package org.jetbrains.kotlin.tools.projectWizard.core.service
import java.nio.file.Path import java.nio.file.Path
interface AndroidService : Service { interface AndroidWizardService : WizardService {
fun isValidAndroidSdk(path: Path): Boolean fun isValidAndroidSdk(path: Path): Boolean
} }
class AndroidServiceImpl : AndroidService { class AndroidWizardServiceImpl : AndroidWizardService, IdeaIndependentWizardService {
//TODO use some heuristics //TODO use some heuristics
override fun isValidAndroidSdk(path: Path): Boolean = true override fun isValidAndroidSdk(path: Path): Boolean = true
} }
@@ -0,0 +1,16 @@
/*
* 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.core.service
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
interface BuildSystemAvailabilityWizardService : WizardService {
fun isAvailable(buildSystemType: BuildSystemType): Boolean
}
class BuildSystemAvailabilityWizardServiceImpl : BuildSystemAvailabilityWizardService, IdeaIndependentWizardService {
override fun isAvailable(buildSystemType: BuildSystemType) = true
}
@@ -1,12 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import java.nio.file.Path
interface BuildSystemService : Service {
fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
): TaskResult<Unit>
}
@@ -0,0 +1,7 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
interface BuildSystemWizardService : WizardService {
fun isSuitableFor(buildSystemType: BuildSystemType): Boolean
}
@@ -1,29 +1,22 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.core.computeM import org.jetbrains.kotlin.tools.projectWizard.core.computeM
import org.jetbrains.kotlin.tools.projectWizard.core.safe import org.jetbrains.kotlin.tools.projectWizard.core.safe
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
interface FileSystemService : Service { interface FileSystemWizardService : WizardService {
fun createFile(path: Path, text: String): TaskResult<Unit> fun createFile(path: Path, text: String): TaskResult<Unit>
fun createDirectory(path: Path): TaskResult<Unit> fun createDirectory(path: Path): TaskResult<Unit>
object DUMMY : FileSystemService {
override fun createFile(path: Path, text: String): TaskResult<Unit> = UNIT_SUCCESS
override fun createDirectory(path: Path): TaskResult<Unit> = UNIT_SUCCESS
}
} }
class OsFileSystemService : FileSystemService { class OsFileSystemWizardService : FileSystemWizardService, IdeaIndependentWizardService {
override fun createFile(path: Path, text: String) = computeM { override fun createFile(path: Path, text: String) = computeM {
createDirectory(path.parent).ensure() createDirectory(path.parent).ensure()
safe { Files.createFile(path.normalize()).toFile().writeText(text) } safe { Files.createFile(path.normalize()).toFile().writeText(text) }
} }
override fun createDirectory(path: Path) = safe { override fun createDirectory(path: Path) = safe {
@Suppress("NAME_SHADOWING") val path = path.normalize() @Suppress("NAME_SHADOWING") val path = path.normalize()
if (Files.notExists(path)) { if (Files.notExists(path)) {
@@ -1,14 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import java.nio.file.Path
interface GradleService : BuildSystemService
class OsGradleIntegration : GradleService {
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
) = UNIT_SUCCESS
}
@@ -1,14 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import java.nio.file.Path
interface JpsService : BuildSystemService
class OsJpsService : JpsService {
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
) = UNIT_SUCCESS
}
@@ -1,14 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import java.nio.file.Path
interface MavenService : BuildSystemService
class OsMavenService : MavenService {
override fun importProject(
path: Path,
modulesIrs: List<ModuleIR>
) = UNIT_SUCCESS
}
@@ -0,0 +1,16 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import java.nio.file.Path
interface ProjectImportingWizardService : BuildSystemWizardService {
fun importProject(path: Path, modulesIrs: List<ModuleIR>): TaskResult<Unit>
}
class ProjectImportingWizardServiceImpl : ProjectImportingWizardService, IdeaIndependentWizardService {
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean = true
override fun importProject(path: Path, modulesIrs: List<ModuleIR>) = UNIT_SUCCESS
}
@@ -1,13 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
interface Service
object Services {
val osServices = listOf(
OsGradleIntegration(),
OsMavenService(),
OsFileSystemService(),
OsJpsService(),
AndroidServiceImpl()
)
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.core.service
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
class ServicesManager(private val services: List<WizardService>, private val serviceSelector: (List<WizardService>) -> WizardService?) {
@Suppress("UNCHECKED_CAST")
fun <S : WizardService> serviceByClass(klass: KClass<S>, filter: (S) -> Boolean): S? =
services.filter { service ->
service::class.isSubclassOf(klass) && filter(service as S)
}.let(serviceSelector) as? S
fun withServices(services: List<WizardService>) =
ServicesManager(this.services + services, serviceSelector)
}
@@ -0,0 +1,15 @@
package org.jetbrains.kotlin.tools.projectWizard.core.service
interface WizardService
interface IdeaIndependentWizardService : WizardService
object Services {
val IDEA_INDEPENDENT_SERVICES: List<IdeaIndependentWizardService> = listOf(
ProjectImportingWizardServiceImpl(),
OsFileSystemWizardService(),
AndroidWizardServiceImpl(),
BuildSystemAvailabilityWizardServiceImpl()
)
}
@@ -3,7 +3,7 @@ package org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ModuleConfiguratorSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.ModuleConfiguratorSetting
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.service.AndroidService import org.jetbrains.kotlin.tools.projectWizard.core.service.AndroidWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.AndroidConfigIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.AndroidConfigIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScriptDependencyIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.BuildScriptDependencyIR
@@ -14,7 +14,6 @@ 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.buildSystem.gradle.GradlePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleConfigurationData import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleConfigurationData
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
import org.jetbrains.kotlin.tools.projectWizard.plugins.pomIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
import org.jetbrains.kotlin.tools.projectWizard.settings.JavaPackage import org.jetbrains.kotlin.tools.projectWizard.settings.JavaPackage
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.DefaultRepository
@@ -38,7 +37,7 @@ object AndroidSinglePlatformModuleConfigurator : ModuleConfiguratorWithSettings(
validate { path -> validate { path ->
ValidationResult.create( ValidationResult.create(
service<AndroidService>().isValidAndroidSdk( service<AndroidWizardService>()!!.isValidAndroidSdk(
path path
), ),
"Path should point to valid Android SDK location" "Path should point to valid Android SDK location"
@@ -5,7 +5,7 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Plugin
import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
import org.jetbrains.kotlin.tools.projectWizard.core.pathParser import org.jetbrains.kotlin.tools.projectWizard.core.pathParser
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemService import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.PomIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.PomIR
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
@@ -31,7 +31,7 @@ class StructurePlugin(context: Context) : Plugin(context) {
val createProjectDir by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val createProjectDir by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
withAction { withAction {
service<FileSystemService>().createDirectory(StructurePlugin::projectPath.reference.settingValue) service<FileSystemWizardService>()!!.createDirectory(StructurePlugin::projectPath.reference.settingValue)
} }
} }
} }
@@ -3,8 +3,9 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemService import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemAvailabilityWizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemService import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildFileIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildFileIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.MultiplatformModulesStructureIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.MultiplatformModulesStructureIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.render import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.render
@@ -16,13 +17,17 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.BuildFilePrinter
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.printBuildFile import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.printBuildFile
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import kotlin.reflect.KClass
abstract class BuildSystemPlugin(context: Context) : Plugin(context) { abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
val type by enumSetting<BuildSystemType>("Build System", GenerationPhase.FIRST_STEP) { val type by enumSetting<BuildSystemType>("Build System", GenerationPhase.FIRST_STEP) {
filter = { _, type ->
val service = service<BuildSystemAvailabilityWizardService>()!!
service.isAvailable(type)
}
validate { buildSystemType -> validate { buildSystemType ->
if (!buildSystemType.isGradle if (!buildSystemType.isGradle
&& KotlinPlugin::projectKind.settingValue() == ProjectKind.Multiplatform && KotlinPlugin::projectKind.reference.notRequiredSettingValue == ProjectKind.Multiplatform
) { ) {
ValidationResult.ValidationError("Multiplatform project cannot be generated using ${buildSystemType.text}") ValidationResult.ValidationError("Multiplatform project cannot be generated using ${buildSystemType.text}")
} else ValidationResult.OK } else ValidationResult.OK
@@ -36,7 +41,7 @@ abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
val createModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val createModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runAfter(StructurePlugin::createProjectDir) runAfter(StructurePlugin::createProjectDir)
withAction { withAction {
val fileSystem = service<FileSystemService>() val fileSystem = service<FileSystemWizardService>()!!
val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType } val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType }
val buildFileData = data.buildFileData ?: return@withAction UNIT_SUCCESS val buildFileData = data.buildFileData ?: return@withAction UNIT_SUCCESS
BuildSystemPlugin::buildFiles.propertyValue.mapSequenceIgnore { buildFile -> BuildSystemPlugin::buildFiles.propertyValue.mapSequenceIgnore { buildFile ->
@@ -52,7 +57,7 @@ abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
runAfter(BuildSystemPlugin::createModules) runAfter(BuildSystemPlugin::createModules)
withAction { withAction {
val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType } val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType }
serviceByClass(data.buildSystemServiceClass) service<ProjectImportingWizardService> { service -> service.isSuitableFor(data.type) }!!
.importProject(StructurePlugin::projectPath.reference.settingValue, allModules) .importProject(StructurePlugin::projectPath.reference.settingValue, allModules)
} }
} }
@@ -61,14 +66,13 @@ abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
runBefore(BuildSystemPlugin::createModules) runBefore(BuildSystemPlugin::createModules)
activityChecker = Checker.ALWAYS_AVAILABLE activityChecker = Checker.ALWAYS_AVAILABLE
withAction { withAction {
BuildSystemPlugin::buildSystemData.update { Success(it + data) } BuildSystemPlugin::buildSystemData.addValues(data)
} }
} }
} }
data class BuildSystemData( data class BuildSystemData(
val type: BuildSystemType, val type: BuildSystemType,
val buildSystemServiceClass: KClass<out BuildSystemService>,
val buildFileData: BuildFileData? val buildFileData: BuildFileData?
) )
@@ -1,7 +1,6 @@
package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.service.JpsService
class JpsPlugin(context: Context) : BuildSystemPlugin(context) { class JpsPlugin(context: Context) : BuildSystemPlugin(context) {
override val title: String = "IDEA" override val title: String = "IDEA"
@@ -9,7 +8,6 @@ class JpsPlugin(context: Context) : BuildSystemPlugin(context) {
val addBuildSystemData by addBuildSystemData( val addBuildSystemData by addBuildSystemData(
BuildSystemData( BuildSystemData(
type = BuildSystemType.Jps, type = BuildSystemType.Jps,
buildSystemServiceClass = JpsService::class,
buildFileData = null buildFileData = null
) )
) )
@@ -4,7 +4,6 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.asSuccess import org.jetbrains.kotlin.tools.projectWizard.core.asSuccess
import org.jetbrains.kotlin.tools.projectWizard.core.checker import org.jetbrains.kotlin.tools.projectWizard.core.checker
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.MavenService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.RootFileModuleStructureIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.RootFileModuleStructureIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.ModulesDependencyMavenIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.ModulesDependencyMavenIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.withIrs import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.withIrs
@@ -42,7 +41,6 @@ class MavenPlugin(context: Context) : BuildSystemPlugin(context) {
val addBuildSystemData by addBuildSystemData( val addBuildSystemData by addBuildSystemData(
BuildSystemData( BuildSystemData(
type = BuildSystemType.Maven, type = BuildSystemType.Maven,
buildSystemServiceClass = MavenService::class,
buildFileData = BuildFileData( buildFileData = BuildFileData(
createPrinter = { MavenPrinter() }, createPrinter = { MavenPrinter() },
buildFileName = "pom.xml" buildFileName = "pom.xml"
@@ -1,15 +1,10 @@
package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.checker
import org.jetbrains.kotlin.tools.projectWizard.core.service.GradleService
import org.jetbrains.kotlin.tools.projectWizard.core.service.MavenService
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildFileData import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildFileData
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemData import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemData
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.MavenPrinter
class GroovyDslPlugin(context: Context) : GradlePlugin(context) { class GroovyDslPlugin(context: Context) : GradlePlugin(context) {
override val title: String = "Gradle (Groovy DSL)" override val title: String = "Gradle (Groovy DSL)"
@@ -17,7 +12,6 @@ class GroovyDslPlugin(context: Context) : GradlePlugin(context) {
val addBuildSystemData by addBuildSystemData( val addBuildSystemData by addBuildSystemData(
BuildSystemData( BuildSystemData(
type = BuildSystemType.GradleGroovyDsl, type = BuildSystemType.GradleGroovyDsl,
buildSystemServiceClass = GradleService::class,
buildFileData = BuildFileData( buildFileData = BuildFileData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.GROOVY) }, createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.GROOVY) },
buildFileName = "build.gradle" buildFileName = "build.gradle"
@@ -1,11 +1,8 @@
package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.checker
import org.jetbrains.kotlin.tools.projectWizard.core.service.GradleService
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildFileData import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildFileData
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemData import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemData
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
@@ -15,7 +12,6 @@ class KotlinDslPlugin(context: Context) : GradlePlugin(context) {
val addBuildSystemData by addBuildSystemData( val addBuildSystemData by addBuildSystemData(
BuildSystemData( BuildSystemData(
type = BuildSystemType.GradleKotlinDsl, type = BuildSystemType.GradleKotlinDsl,
buildSystemServiceClass = GradleService::class,
buildFileData = BuildFileData( buildFileData = BuildFileData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.KOTLIN) }, createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.KOTLIN) },
buildFileName = "build.gradle.kts" buildFileName = "build.gradle.kts"
@@ -2,7 +2,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemService import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
@@ -82,9 +82,10 @@ class KotlinPlugin(context: Context) : Plugin(context) {
val createSourcesetDirectories by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val createSourcesetDirectories by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createModules) runAfter(KotlinPlugin::createModules)
withAction { withAction {
fun Path.createKotlinAndResourceDirectories() = fun Path.createKotlinAndResourceDirectories() = with(service<FileSystemWizardService>()!!) {
service<FileSystemService>().createDirectory(this / Defaults.KOTLIN_DIR) andThen createDirectory(this@createKotlinAndResourceDirectories / Defaults.KOTLIN_DIR) andThen
service<FileSystemService>().createDirectory(this / Defaults.RESOURCES_DIR) createDirectory(this@createKotlinAndResourceDirectories / Defaults.RESOURCES_DIR)
}
forEachModule { moduleIR -> forEachModule { moduleIR ->
when (moduleIR) { when (moduleIR) {
@@ -4,11 +4,10 @@ import org.jetbrains.kotlin.tools.projectWizard.Identificator
import org.jetbrains.kotlin.tools.projectWizard.SettingsOwner import org.jetbrains.kotlin.tools.projectWizard.SettingsOwner
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemService 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.BuildSystemIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.DependencyIR 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.SourcesetIR
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.ModuleConfigurator
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin 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.ModuleType
@@ -79,7 +78,7 @@ abstract class Template : SettingsOwner {
templateEngine: TemplateEngine, templateEngine: TemplateEngine,
sourceset: SourcesetIR sourceset: SourcesetIR
): TaskResult<TemplateApplicationResult> { ): TaskResult<TemplateApplicationResult> {
val fileSystemService = service<FileSystemService>() val fileSystemService = service<FileSystemWizardService>()!!
val allSettings = createDefaultSettings() + settingsAsMap(sourceset.original) val allSettings = createDefaultSettings() + settingsAsMap(sourceset.original)
@@ -8,7 +8,7 @@ import org.apache.velocity.runtime.log.LogChute
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext
import org.jetbrains.kotlin.tools.projectWizard.core.div import org.jetbrains.kotlin.tools.projectWizard.core.div
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemService import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import java.io.StringWriter import java.io.StringWriter
@@ -17,7 +17,7 @@ interface TemplateEngine {
fun TaskRunningContext.writeTemplate(template: FileTemplate): TaskResult<Unit> { fun TaskRunningContext.writeTemplate(template: FileTemplate): TaskResult<Unit> {
val text = renderTemplate(template.descriptor, template.data) val text = renderTemplate(template.descriptor, template.data)
return service<FileSystemService>().createFile(template.rootPath / template.descriptor.relativePath, text) return service<FileSystemWizardService>()!!.createFile(template.rootPath / template.descriptor.relativePath, text)
} }
} }
@@ -2,12 +2,13 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.core.service.Service import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
abstract class Wizard(createPlugins: PluginsCreator, initialServices: List<Service>) { abstract class Wizard(createPlugins: PluginsCreator, val servicesManager: ServicesManager) {
val context = Context(createPlugins, EventManager()) val context = Context(createPlugins, EventManager())
val valuesReadingContext = ValuesReadingContext(context, initialServices) val valuesReadingContext = ValuesReadingContext(context, servicesManager)
protected val plugins = context.plugins protected val plugins = context.plugins
protected val pluginSettings = plugins.flatMap { it.declaredSettings }.distinctBy { it.path } protected val pluginSettings = plugins.flatMap { it.declaredSettings }.distinctBy { it.path }
@@ -28,12 +29,12 @@ abstract class Wizard(createPlugins: PluginsCreator, initialServices: List<Servi
}.fold(ValidationResult.OK, ValidationResult::and).toResult() }.fold(ValidationResult.OK, ValidationResult::and).toResult()
open fun apply( open fun apply(
services: List<Service>, services: List<WizardService>,
phases: Set<GenerationPhase>, phases: Set<GenerationPhase>,
onTaskExecuting: (PipelineTask) -> Unit = {} onTaskExecuting: (PipelineTask) -> Unit = {}
): TaskResult<Unit> = computeM { ): TaskResult<Unit> = computeM {
context.checkAllRequiredSettingPresent(phases).ensure() context.checkAllRequiredSettingPresent(phases).ensure()
val taskRunningContext = TaskRunningContext(context, services) val taskRunningContext = TaskRunningContext(context, servicesManager.withServices(services))
taskRunningContext.validate(phases).ensure() taskRunningContext.validate(phases).ensure()
val (tasksSorted) = context.sortTasks().map { tasks -> val (tasksSorted) = context.sortTasks().map { tasks ->
tasks.groupBy { it.phase }.toList().sortedBy { it.first }.flatMap { it.second } tasks.groupBy { it.phase }.toList().sortedBy { it.first }.flatMap { it.second }