Get rid of reflection in new project wizard core: manually specify properties in plugins

This commit is contained in:
aleksandrina-streltsova
2020-07-22 13:56:41 +03:00
committed by Kirill Shmakov
parent cc35529b9a
commit 63e2d771b3
55 changed files with 998 additions and 1009 deletions
@@ -4,7 +4,6 @@ import com.intellij.facet.impl.ui.libraries.LibraryOptionsPanel
import com.intellij.framework.library.FrameworkLibraryVersionFilter import com.intellij.framework.library.FrameworkLibraryVersionFilter
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory
import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription
@@ -43,14 +42,14 @@ class IdeWizard(
) )
var jdk: Sdk? = null var jdk: Sdk? = null
var projectPath by setting(StructurePlugin::projectPath.reference) var projectPath by setting(StructurePlugin.projectPath.reference)
var projectName by setting(StructurePlugin::name.reference) var projectName by setting(StructurePlugin.name.reference)
var groupId by setting(StructurePlugin::groupId.reference) var groupId by setting(StructurePlugin.groupId.reference)
var artifactId by setting(StructurePlugin::artifactId.reference) var artifactId by setting(StructurePlugin.artifactId.reference)
var buildSystemType by setting(BuildSystemPlugin::type.reference) var buildSystemType by setting(BuildSystemPlugin.type.reference)
var projectTemplate by setting(ProjectTemplatesPlugin::template.reference) var projectTemplate by setting(ProjectTemplatesPlugin.template.reference)
private fun <V : Any, T : SettingType<V>> setting(reference: SettingReference<V, T>) = private fun <V : Any, T : SettingType<V>> setting(reference: SettingReference<V, T>) =
object : ReadWriteProperty<Any?, V?> { object : ReadWriteProperty<Any?, V?> {
@@ -3,7 +3,6 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard
import com.intellij.ide.RecentProjectsManager import com.intellij.ide.RecentProjectsManager
import com.intellij.ide.actions.NewProjectAction import com.intellij.ide.actions.NewProjectAction
import com.intellij.ide.impl.NewProjectUtil import com.intellij.ide.impl.NewProjectUtil
import com.intellij.ide.projectWizard.NewProjectWizard
import com.intellij.ide.util.projectWizard.* import com.intellij.ide.util.projectWizard.*
import com.intellij.ide.wizard.AbstractWizard import com.intellij.ide.wizard.AbstractWizard
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
@@ -14,11 +13,9 @@ import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.options.ConfigurationException import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ui.configuration.ModulesProvider import com.intellij.openapi.roots.ui.configuration.ModulesProvider
import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.Messages
import com.intellij.util.SystemProperties import com.intellij.util.SystemProperties
import org.jetbrains.kotlin.idea.configuration.ExperimentalFeatures
import org.jetbrains.kotlin.idea.framework.KotlinTemplatesFactory import org.jetbrains.kotlin.idea.framework.KotlinTemplatesFactory
import org.jetbrains.kotlin.idea.projectWizard.ProjectCreationStats import org.jetbrains.kotlin.idea.projectWizard.ProjectCreationStats
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
@@ -201,12 +198,12 @@ class ModuleNewWizardFirstStep(wizard: IdeWizard) : WizardStep(wizard, Generatio
val suggestedProjectParentLocation = suggestProjectLocation() val suggestedProjectParentLocation = suggestProjectLocation()
val suggestedProjectName = ProjectWizardUtil.findNonExistingFileName(suggestedProjectParentLocation, "untitled", "") val suggestedProjectName = ProjectWizardUtil.findNonExistingFileName(suggestedProjectParentLocation, "untitled", "")
wizard.context.writeSettings { wizard.context.writeSettings {
StructurePlugin::name.reference.setValue(suggestedProjectName) StructurePlugin.name.reference.setValue(suggestedProjectName)
StructurePlugin::projectPath.reference.setValue(suggestedProjectParentLocation / suggestedProjectName) StructurePlugin.projectPath.reference.setValue(suggestedProjectParentLocation / suggestedProjectName)
StructurePlugin::artifactId.reference.setValue(suggestedProjectName) StructurePlugin.artifactId.reference.setValue(suggestedProjectName)
if (StructurePlugin::groupId.reference.notRequiredSettingValue == null) { if (StructurePlugin.groupId.notRequiredSettingValue == null) {
StructurePlugin::groupId.reference.setValue(suggestGroupId()) StructurePlugin.groupId.reference.setValue(suggestGroupId())
} }
} }
} }
@@ -6,10 +6,8 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Reader
import org.jetbrains.kotlin.tools.projectWizard.core.SettingsWriter import org.jetbrains.kotlin.tools.projectWizard.core.SettingsWriter
import org.jetbrains.kotlin.tools.projectWizard.core.Writer import org.jetbrains.kotlin.tools.projectWizard.core.Writer
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.settings.PluginSettingPropertyReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingType import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingType
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
abstract class Component : Displayable, ErrorNavigatable { abstract class Component : Displayable, ErrorNavigatable {
private val subComponents = mutableListOf<Component>() private val subComponents = mutableListOf<Component>()
@@ -45,10 +43,6 @@ abstract class DynamicComponent(private val context: Context) : Component() {
value?.let { setValue(it) } value?.let { setValue(it) }
} }
inline val <V : Any, reified T : SettingType<V>> PluginSettingPropertyReference<V, T>.value: V?
get() = reference.value
init { init {
write { write {
eventManager.addSettingUpdaterEventListener { reference -> eventManager.addSettingUpdaterEventListener { reference ->
@@ -29,7 +29,7 @@ import javax.swing.JComponent
class BuildSystemTypeSettingComponent( class BuildSystemTypeSettingComponent(
context: Context context: Context
) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>( ) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
BuildSystemPlugin::type.reference, BuildSystemPlugin.type.reference,
context context
) { ) {
@@ -12,7 +12,6 @@ import com.intellij.ui.layout.panel
import com.intellij.util.ui.JBUI import com.intellij.util.ui.JBUI
import com.intellij.util.ui.components.BorderLayoutPanel import com.intellij.util.ui.components.BorderLayoutPanel
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.entity.path
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
@@ -53,8 +52,8 @@ class ProjectSettingsComponent(ideWizard: IdeWizard) : DynamicComponent(ideWizar
private val nameAndLocationComponent = TitledComponentsList( private val nameAndLocationComponent = TitledComponentsList(
listOf( listOf(
StructurePlugin::name.reference.createSettingComponent(context), StructurePlugin.name.reference.createSettingComponent(context),
StructurePlugin::projectPath.reference.createSettingComponent(context), StructurePlugin.projectPath.reference.createSettingComponent(context),
projectTemplateComponent, projectTemplateComponent,
buildSystemSetting, buildSystemSetting,
jdkComponent jdkComponent
@@ -84,17 +83,17 @@ class ProjectSettingsComponent(ideWizard: IdeWizard) : DynamicComponent(ideWizar
override fun onValueUpdated(reference: SettingReference<*, *>?) { override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference) super.onValueUpdated(reference)
when (reference?.path) { when (reference?.path) {
StructurePlugin::name.path -> { StructurePlugin.name.path -> {
val isNameValid = read { StructurePlugin::name.reference.validate().isOk } val isNameValid = read { StructurePlugin.name.reference.validate().isOk }
if (isNameValid) { if (isNameValid) {
tryUpdateLocationByProjectName() tryUpdateLocationByProjectName()
tryArtifactIdByProjectName() tryArtifactIdByProjectName()
} }
} }
StructurePlugin::artifactId.path -> { StructurePlugin.artifactId.path -> {
artifactIdWasUpdatedByHand = true artifactIdWasUpdatedByHand = true
} }
StructurePlugin::projectPath.path -> { StructurePlugin.projectPath.path -> {
locationWasUpdatedByHand = true locationWasUpdatedByHand = true
} }
} }
@@ -102,9 +101,9 @@ class ProjectSettingsComponent(ideWizard: IdeWizard) : DynamicComponent(ideWizar
private fun tryUpdateLocationByProjectName() { private fun tryUpdateLocationByProjectName() {
if (!locationWasUpdatedByHand) { if (!locationWasUpdatedByHand) {
val location = read { StructurePlugin::projectPath.settingValue } val location = read { StructurePlugin.projectPath.settingValue }
if (location.parent != null) modify { if (location.parent != null) modify {
StructurePlugin::projectPath.reference.setValue(location.parent.resolve(StructurePlugin::name.settingValue)) StructurePlugin.projectPath.reference.setValue(location.parent.resolve(StructurePlugin.name.settingValue))
locationWasUpdatedByHand = false locationWasUpdatedByHand = false
} }
} }
@@ -112,7 +111,7 @@ class ProjectSettingsComponent(ideWizard: IdeWizard) : DynamicComponent(ideWizar
private fun tryArtifactIdByProjectName() { private fun tryArtifactIdByProjectName() {
if (!artifactIdWasUpdatedByHand) modify { if (!artifactIdWasUpdatedByHand) modify {
StructurePlugin::artifactId.reference.setValue(StructurePlugin::name.settingValue) StructurePlugin.artifactId.reference.setValue(StructurePlugin.name.settingValue)
artifactIdWasUpdatedByHand = false artifactIdWasUpdatedByHand = false
} }
} }
@@ -124,7 +123,7 @@ class BuildSystemAdditionalSettingsComponent(ideWizard: IdeWizard) : DynamicComp
override fun onValueUpdated(reference: SettingReference<*, *>?) { override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference) super.onValueUpdated(reference)
if (reference == BuildSystemPlugin::type.reference) { if (reference == BuildSystemPlugin.type.reference) {
updateBuildSystemComponent() updateBuildSystemComponent()
} }
} }
@@ -135,7 +134,7 @@ class BuildSystemAdditionalSettingsComponent(ideWizard: IdeWizard) : DynamicComp
} }
private fun updateBuildSystemComponent() { private fun updateBuildSystemComponent() {
val buildSystemType = read { BuildSystemPlugin::type.settingValue() } val buildSystemType = read { BuildSystemPlugin.type.settingValue }
val state = buildSystemType.state() val state = buildSystemType.state()
section.updateTitleAndComponent(state.sectionTitle, state.component) section.updateTitleAndComponent(state.sectionTitle, state.component)
} }
@@ -162,9 +161,9 @@ class BuildSystemAdditionalSettingsComponent(ideWizard: IdeWizard) : DynamicComp
private class PomSettingsComponent(context: Context) : TitledComponentsList( private class PomSettingsComponent(context: Context) : TitledComponentsList(
listOf( listOf(
StructurePlugin::groupId.reference.createSettingComponent(context), StructurePlugin.groupId.reference.createSettingComponent(context),
StructurePlugin::artifactId.reference.createSettingComponent(context), StructurePlugin.artifactId.reference.createSettingComponent(context),
StructurePlugin::version.reference.createSettingComponent(context) StructurePlugin.version.reference.createSettingComponent(context)
), ),
context, context,
stretchY = true stretchY = true
@@ -257,7 +256,7 @@ class ProjectPreviewComponent(context: Context) : DynamicComponent(context) {
override fun onValueUpdated(reference: SettingReference<*, *>?) { override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference) super.onValueUpdated(reference)
if (reference == ProjectTemplatesPlugin::template.reference) { if (reference == ProjectTemplatesPlugin.template.reference) {
modulesEditorComponent.updateModel() modulesEditorComponent.updateModel()
} }
} }
@@ -23,7 +23,7 @@ import javax.swing.JComponent
class ProjectTemplateSettingComponent( class ProjectTemplateSettingComponent(
context: Context context: Context
) : SettingComponent<ProjectTemplate, DropDownSettingType<ProjectTemplate>>( ) : SettingComponent<ProjectTemplate, DropDownSettingType<ProjectTemplate>>(
ProjectTemplatesPlugin::template.reference, ProjectTemplatesPlugin.template.reference,
context context
) { ) {
override val validationIndicator: ValidationIndicator? get() = null override val validationIndicator: ValidationIndicator? get() = null
@@ -58,7 +58,7 @@ class ProjectTemplateSettingComponent(
override fun onValueUpdated(reference: SettingReference<*, *>?) { override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference) super.onValueUpdated(reference)
if (reference == ProjectTemplatesPlugin::template.reference) { if (reference == ProjectTemplatesPlugin.template.reference) {
applySelectedTemplate() applySelectedTemplate()
value?.let { template -> value?.let { template ->
list.setSelectedValue(template, true) list.setSelectedValue(template, true)
@@ -61,7 +61,7 @@ class ModuleDependenciesComponent(
} }
private fun possibleDependencies(): List<Module> = private fun possibleDependencies(): List<Module> =
read { KotlinPlugin::modules.settingValue }.withAllSubModules().toMutableList().apply { read { KotlinPlugin.modules.settingValue }.withAllSubModules().toMutableList().apply {
module?.let(::remove) module?.let(::remove)
removeAll( removeAll(
module module
@@ -90,7 +90,7 @@ private class ModuleNameComponent(context: Context, private val module: Module)
override fun onInit() { override fun onInit() {
super.onInit() super.onInit()
val isSingleRootMode = read { KotlinPlugin::modules.settingValue }.size == 1 val isSingleRootMode = read { KotlinPlugin.modules.settingValue }.size == 1
when { when {
isSingleRootMode && module.isRootModule -> { isSingleRootMode && module.isRootModule -> {
textField.disable(KotlinNewProjectWizardUIBundle.message("module.settings.name.same.as.project")) textField.disable(KotlinNewProjectWizardUIBundle.message("module.settings.name.same.as.project"))
@@ -168,7 +168,7 @@ private object NoneTemplate : Template() {
} }
fun Reader.availableTemplatesFor(module: Module) = fun Reader.availableTemplatesFor(module: Module) =
TemplatesPlugin::templates.propertyValue.values.filter { template -> TemplatesPlugin.templates.propertyValue.values.filter { template ->
module.configurator.moduleType in template.moduleTypes module.configurator.moduleType in template.moduleTypes
} }
@@ -26,14 +26,14 @@ class ModulesEditorComponent(
needBorder: Boolean, needBorder: Boolean,
private val editable: Boolean, private val editable: Boolean,
oneEntrySelected: (data: DisplayableSettingItem?) -> Unit oneEntrySelected: (data: DisplayableSettingItem?) -> Unit
) : SettingComponent<List<Module>, ListSettingType<Module>>(KotlinPlugin::modules.reference, context) { ) : SettingComponent<List<Module>, ListSettingType<Module>>(KotlinPlugin.modules.reference, context) {
private val tree: ModulesEditorTree = private val tree: ModulesEditorTree =
ModulesEditorTree( ModulesEditorTree(
onSelected = { oneEntrySelected(it) }, onSelected = { oneEntrySelected(it) },
context = context, context = context,
isTreeEditable = editable, isTreeEditable = editable,
addModule = { component -> addModule = { component ->
val isMppProject = KotlinPlugin::projectKind.value == ProjectKind.Singleplatform val isMppProject = KotlinPlugin.projectKind.reference.value == ProjectKind.Singleplatform
moduleCreator.create( moduleCreator.create(
target = null, // The empty tree case target = null, // The empty tree case
allowMultiplatform = isMppProject, allowMultiplatform = isMppProject,
@@ -77,7 +77,7 @@ class ModulesEditorComponent(
moduleCreator = moduleCreator, moduleCreator = moduleCreator,
model = model, model = model,
getModules = { value ?: emptyList() }, getModules = { value ?: emptyList() },
isMultiplatformProject = { KotlinPlugin::projectKind.value != ProjectKind.Singleplatform } isMultiplatformProject = { KotlinPlugin.projectKind.reference.value != ProjectKind.Singleplatform }
) else null ) else null
override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) { override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) {
@@ -59,7 +59,7 @@ class GradleProjectImportingTestWizardService(private val project: Project) : Pr
return importingErrorMessage?.let { message -> return importingErrorMessage?.let { message ->
Failure( Failure(
ProjectImportingError( ProjectImportingError(
reader { KotlinPlugin::version.propertyValue.version.toString() }, reader { KotlinPlugin.version.propertyValue.version.toString() },
message, message,
) )
) )
@@ -32,7 +32,7 @@ class YamlWizard(
context.writeSettings { context.writeSettings {
settingsValuesFromYaml.forEach { (reference, value) -> reference.setValue(value) } settingsValuesFromYaml.forEach { (reference, value) -> reference.setValue(value) }
StructurePlugin::projectPath.reference.setValue(projectPath) StructurePlugin.projectPath.reference.setValue(projectPath)
} }
super.apply(services, phases, onTaskExecuting) super.apply(services, phases, onTaskExecuting)
@@ -49,7 +49,7 @@ fun Reader.parseYaml(
yaml: String, yaml: String,
pluginSettings: List<PluginSetting<*, *>> pluginSettings: List<PluginSetting<*, *>>
): TaskResult<Map<SettingReference<*, *>, Any>> { ): TaskResult<Map<SettingReference<*, *>, Any>> {
val parsingData = ParsingState(TemplatesPlugin::templates.propertyValue, emptyMap()) val parsingData = ParsingState(TemplatesPlugin.templates.propertyValue, emptyMap())
val yamlParser = YamlSettingsParser(pluginSettings, parsingData) val yamlParser = YamlSettingsParser(pluginSettings, parsingData)
return yamlParser.parseYamlText(yaml) return yamlParser.parseYamlText(yaml)
} }
@@ -43,11 +43,11 @@ class ProjectTemplateBasedTestWizard(
super.apply(services, setOf(GenerationPhase.PREPARE), onTaskExecuting).ensure() super.apply(services, setOf(GenerationPhase.PREPARE), onTaskExecuting).ensure()
context.writeSettings { context.writeSettings {
applyProjectTemplate(projectTemplate) applyProjectTemplate(projectTemplate)
BuildSystemPlugin::type.reference.setValue(buildSystem.buildSystemType) BuildSystemPlugin.type.reference.setValue(buildSystem.buildSystemType)
StructurePlugin::projectPath.reference.setValue(projectDirectory) StructurePlugin.projectPath.reference.setValue(projectDirectory)
StructurePlugin::name.reference.setValue(projectTemplate.id) StructurePlugin.name.reference.setValue(projectTemplate.id)
StructurePlugin::groupId.reference.setValue(GROUP_ID) StructurePlugin.groupId.reference.setValue(GROUP_ID)
StructurePlugin::artifactId.reference.setValue(ARTIFACT_ID) StructurePlugin.artifactId.reference.setValue(ARTIFACT_ID)
} }
applyAdditionalSettingsFromYaml().ensure() applyAdditionalSettingsFromYaml().ensure()
@@ -10,6 +10,7 @@ import kotlin.properties.ReadOnlyProperty
interface SettingsOwner { interface SettingsOwner {
fun <V : Any, T : SettingType<V>> settingDelegate( fun <V : Any, T : SettingType<V>> settingDelegate(
prefix: String,
create: (path: String) -> SettingBuilder<V, T> create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, Setting<V, T>> ): ReadOnlyProperty<Any, Setting<V, T>>
@@ -21,24 +22,27 @@ interface SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String = "",
init: DropDownSettingType.Builder<V>.() -> Unit = {} init: DropDownSettingType.Builder<V>.() -> Unit = {}
): ReadOnlyProperty<Any, Setting<V, DropDownSettingType<V>>> = settingDelegate { path -> ): ReadOnlyProperty<Any, Setting<V, DropDownSettingType<V>>> = settingDelegate(prefix) { path ->
DropDownSettingType.Builder(path, title, neededAtPhase, parser).apply(init) DropDownSettingType.Builder(path, title, neededAtPhase, parser).apply(init)
} }
fun stringSetting( fun stringSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
init: StringSettingType.Builder.() -> Unit = {} init: StringSettingType.Builder.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
StringSettingType.Builder(path, title, neededAtPhase).apply(init) StringSettingType.Builder(path, title, neededAtPhase).apply(init)
} }
fun booleanSetting( fun booleanSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
init: BooleanSettingType.Builder.() -> Unit = {} init: BooleanSettingType.Builder.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
BooleanSettingType.Builder(path, title, neededAtPhase).apply(init) BooleanSettingType.Builder(path, title, neededAtPhase).apply(init)
} }
@@ -46,16 +50,18 @@ interface SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String = "",
init: ValueSettingType.Builder<V>.() -> Unit = {} init: ValueSettingType.Builder<V>.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
ValueSettingType.Builder(path, title, neededAtPhase, parser).apply(init) ValueSettingType.Builder(path, title, neededAtPhase, parser).apply(init)
} }
fun versionSetting( fun versionSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
init: VersionSettingType.Builder.() -> Unit = {} init: VersionSettingType.Builder.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
VersionSettingType.Builder(path, title, neededAtPhase).apply(init) VersionSettingType.Builder(path, title, neededAtPhase).apply(init)
} }
@@ -63,16 +69,18 @@ interface SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String = "",
init: ListSettingType.Builder<V>.() -> Unit = {} init: ListSettingType.Builder<V>.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
ListSettingType.Builder(path, title, neededAtPhase, parser).apply(init) ListSettingType.Builder(path, title, neededAtPhase, parser).apply(init)
} }
fun pathSetting( fun pathSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
init: PathSettingType.Builder.() -> Unit = {} init: PathSettingType.Builder.() -> Unit = {}
) = settingDelegate { path -> ) = settingDelegate(prefix) { path ->
PathSettingType.Builder(path, title, neededAtPhase).apply(init) PathSettingType.Builder(path, title, neededAtPhase).apply(init)
} }
} }
@@ -81,8 +89,9 @@ interface SettingsOwner {
inline fun <reified E> SettingsOwner.enumSettingImpl( inline fun <reified E> SettingsOwner.enumSettingImpl(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {} crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {}
) where E : Enum<E>, E : DisplayableSettingItem = dropDownSetting<E>(title, neededAtPhase, enumParser()) { ) where E : Enum<E>, E : DisplayableSettingItem = dropDownSetting<E>(title, neededAtPhase, enumParser(), prefix) {
values = enumValues<E>().asList() values = enumValues<E>().asList()
// //
init() init()
@@ -6,19 +6,14 @@ 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.SettingSavingWizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberProperties
class Context private constructor( class Context private constructor(
private val servicesManager: ServicesManager, val servicesManager: ServicesManager,
private val isUnitTestMode: Boolean, private val isUnitTestMode: Boolean,
private val settingContext: SettingContext, private val settingContext: SettingContext,
private val propertyContext: PropertyContext, private val propertyContext: PropertyContext
private val taskContext: TaskContext
) { ) {
private lateinit var plugins: List<Plugin> private lateinit var plugins: List<Plugin>
@@ -47,8 +42,7 @@ class Context private constructor(
servicesManager, servicesManager,
isUnitTestMode, isUnitTestMode,
SettingContext(), SettingContext(),
PropertyContext(), PropertyContext()
TaskContext()
) { ) {
plugins = pluginsCreator(this).onEach(::initPlugin) plugins = pluginsCreator(this).onEach(::initPlugin)
} }
@@ -58,50 +52,17 @@ class Context private constructor(
servicesManager.withAdditionalServices(services), servicesManager.withAdditionalServices(services),
isUnitTestMode, isUnitTestMode,
settingContext, settingContext,
propertyContext, propertyContext
taskContext
).also { ).also {
it.plugins = plugins it.plugins = plugins
} }
fun <V : Any, T : SettingType<V>> pluginSettingDelegate(
create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, PluginSetting<V, T>> =
settingContext.settingDelegate(create)
fun <T : Any> propertyDelegate(
init: Property.Builder<T>.() -> Unit,
defaultValue: T
) = entityDelegate(propertyContext) { name ->
Property.Builder(name, defaultValue).apply(init).build()
}
fun pipelineTaskDelegate(
phase: GenerationPhase,
init: PipelineTask.Builder.() -> Unit
) = entityDelegate(taskContext) { name ->
PipelineTask.Builder(name, phase).apply(init).build()
}
fun <A, B : Any> task1Delegate(
init: Task1.Builder<A, B>.() -> Unit
) = entityDelegate(taskContext) { name ->
Task1.Builder<A, B>(name).apply(init).build()
}
private fun initPlugin(plugin: Plugin) { private fun initPlugin(plugin: Plugin) {
for (entityReference in plugin::class.memberProperties) { for (property in plugin.properties) {
val type = entityReference.returnType.classifier.safeAs<KClass<*>>() ?: continue propertyContext[property] = property.defaultValue
if (type.isSubclassOf(Entity::class)) { }
when (val entity = entityReference.getter.call(plugin)) { for (setting in plugin.settings) {
is Property<*> -> { settingContext.setPluginSetting(setting.reference, setting)
@Suppress("UNCHECKED_CAST")
propertyContext[entityReference as PropertyReference<Any>] = entity.defaultValue
}
}
}
} }
} }
@@ -110,17 +71,14 @@ class Context private constructor(
get() = plugins get() = plugins
.flatMap { it.pipelineTasks } .flatMap { it.pipelineTasks }
private fun task(reference: PipelineTaskReference) =
taskContext.getEntity(reference) as? PipelineTask ?: error(reference.path)
private val dependencyList: Map<PipelineTask, List<PipelineTask>> private val dependencyList: Map<PipelineTask, List<PipelineTask>>
get() { get() {
val dependeeMap = pipelineLineTasks.flatMap { task -> val dependeeMap = pipelineLineTasks.flatMap { task ->
task.after.map { after -> task to task(after) } task.after.map { after -> task to after }
} }
val dependencyMap = pipelineLineTasks.flatMap { task -> val dependencyMap = pipelineLineTasks.flatMap { task ->
task.before.map { before -> task(before) to task } task.before.map { before -> before to task }
} }
return (dependeeMap + dependencyMap) return (dependeeMap + dependencyMap)
@@ -151,18 +109,17 @@ class Context private constructor(
fun <S : WizardService> serviceByClass(klass: KClass<S>, filter: (S) -> Boolean = { true }): S = fun <S : WizardService> serviceByClass(klass: KClass<S>, filter: (S) -> Boolean = { true }): S =
servicesManager.serviceByClass(klass, filter) ?: error("Service ${klass.simpleName} was not found") servicesManager.serviceByClass(klass, filter) ?: error("Service ${klass.simpleName} was not found")
@Suppress("UNCHECKED_CAST") val <T : Any> Property<T>.propertyValue: T
val <T : Any> PropertyReference<T>.propertyValue: T get() = propertyContext[this] ?: error("No value is present for property `$this`")
get() = propertyContext[this] as T
val <V : Any, T : SettingType<V>> SettingReference<V, T>.settingValue: V val <V : Any, T : SettingType<V>> SettingReference<V, T>.settingValue: V
get() = settingContext[this] ?: error("No value is present for setting `$this`") get() = settingContext[this] ?: error("No value is present for setting `$this`")
inline val <reified V : Any> KProperty1<out Plugin, PluginSetting<V, SettingType<V>>>.settingValue: V val <V : Any> PluginSetting<V, SettingType<V>>.settingValue: V
get() = reference.settingValue get() = settingContext[this.reference] ?: error("No value is present for setting `$this`")
inline fun <reified V : Any> KProperty1<out Plugin, PluginSetting<V, SettingType<V>>>.settingValue(): V = val <V : Any> PluginSetting<V, SettingType<V>>.notRequiredSettingValue: V?
this.reference.settingValue get() = settingContext[this.reference]
fun <V : Any, T : SettingType<V>> SettingReference<V, T>.settingValue(): V = fun <V : Any, T : SettingType<V>> SettingReference<V, T>.settingValue(): V =
settingContext[this] ?: error("No value is present for setting `$this`") settingContext[this] ?: error("No value is present for setting `$this`")
@@ -207,24 +164,23 @@ class Context private constructor(
val eventManager: EventManager val eventManager: EventManager
get() = settingContext.eventManager get() = settingContext.eventManager
fun <A, B : Any> Task1Reference<A, B>.execute(value: A): TaskResult<B> { fun <A, B : Any> Task1<A, B>.execute(value: A): TaskResult<B> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val task = taskContext.getEntity(this) as Task1<A, B> return action(this@Writer, value)
return task.action(this@Writer, value)
} }
fun <T : Any> PropertyReference<T>.update( fun <T : Any> Property<T>.update(
updater: suspend ComputeContext<*>.(T) -> TaskResult<T> updater: suspend ComputeContext<*>.(T) -> TaskResult<T>
): TaskResult<Unit> = compute { ): TaskResult<Unit> = compute {
val (newValue) = updater(propertyValue) val (newValue) = updater(propertyValue)
propertyContext[this@update] = newValue propertyContext[this@update] = newValue
} }
fun <T : Any> PropertyReference<List<T>>.addValues( fun <T : Any> Property<List<T>>.addValues(
vararg values: T vararg values: T
): TaskResult<Unit> = update { oldValues -> success(oldValues + values) } ): TaskResult<Unit> = update { oldValues -> success(oldValues + values) }
fun <T : Any> PropertyReference<List<T>>.addValues( fun <T : Any> Property<List<T>>.addValues(
values: List<T> values: List<T>
): TaskResult<Unit> = update { oldValues -> success(oldValues + values) } ): TaskResult<Unit> = update { oldValues -> success(oldValues + values) }
@@ -6,7 +6,6 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.tools.projectWizard.templates.Template import org.jetbrains.kotlin.tools.projectWizard.templates.Template
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
data class ParsingState( data class ParsingState(
val idToTemplate: Map<String, Template>, val idToTemplate: Map<String, Template>,
@@ -87,10 +86,6 @@ fun <T : Any> valueParserM(parser: suspend ParsingContext.(value: Any?, path: St
} }
} }
inline fun <reified T : Any> valueParser() = valueParser { value, path ->
value.parseAs(path, T::class).get()
}
fun Any?.classMismatchError(@NonNls path: String, expected: KClass<*>): ParseError { fun Any?.classMismatchError(@NonNls path: String, expected: KClass<*>): ParseError {
val classpath = this?.let { it::class.simpleName } ?: "null" val classpath = this?.let { it::class.simpleName } ?: "null"
return ParseError("Expected ${expected.simpleName!!} for `$path` but $classpath was found") return ParseError("Expected ${expected.simpleName!!} for `$path` but $classpath was found")
@@ -100,11 +95,6 @@ inline fun <reified V : Any> Any?.parseAs(@NonNls path: String) =
safeAs<V>().toResult { classMismatchError(path, V::class) } safeAs<V>().toResult { classMismatchError(path, V::class) }
inline fun <reified T : Any> Any?.parseAs(@NonNls path: String, klass: KClass<T>): TaskResult<T> =
this?.takeIf { it::class.isSubclassOf(klass) }?.safeAs<T>()
.toResult { classMismatchError(path, klass) }
inline fun <reified V : Any> Map<*, *>.parseValue(@NonNls path: String, @NonNls name: String) = inline fun <reified V : Any> Map<*, *>.parseValue(@NonNls path: String, @NonNls name: String) =
get(name).parseAs<V>("$path.$name") get(name).parseAs<V>("$path.$name")
@@ -124,13 +114,6 @@ inline fun <reified V : Any, R : Any> Map<*, *>.parseValue(
} }
} }
inline fun <reified T : Any> Map<*, *>.parseValue(
@NonNls path: String,
@NonNls name: String,
klass: KClass<T>
) = get(path).parseAs("$path.$name", klass)
fun <R : Any> Map<*, *>.parseValue( fun <R : Any> Map<*, *>.parseValue(
context: ParsingContext, context: ParsingContext,
@NonNls path: String, @NonNls path: String,
@@ -9,163 +9,163 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import java.nio.file.Path import java.nio.file.Path
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
typealias PluginReference = KClass<out Plugin>
typealias PluginsCreator = (Context) -> List<Plugin> typealias PluginsCreator = (Context) -> List<Plugin>
abstract class Plugin(override val context: Context) : EntityBase(), abstract class Plugin(override val context: Context) : EntityBase(),
SettingsOwner,
ContextOwner, ContextOwner,
EntitiesOwnerDescriptor, EntitiesOwnerDescriptor,
EntitiesOwner<Plugin> { EntitiesOwner<Plugin> {
override val descriptor get() = this override val descriptor get() = this
override val id: String get() = path override val id: String get() = path
override fun <V : Any, T : SettingType<V>> settingDelegate(
create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, PluginSetting<V, T>> = context.pluginSettingDelegate(create)
val reference = this::class val reference = this::class
abstract override val path: String abstract override val path: String
abstract val properties: List<Property<*>>
abstract val settings: List<PluginSetting<*, *>> abstract val settings: List<PluginSetting<*, *>>
abstract val pipelineTasks: List<PipelineTask> abstract val pipelineTasks: List<PipelineTask>
fun pipelineTask(phase: GenerationPhase, init: PipelineTask.Builder.() -> Unit) = companion object : SettingsOwner {
context.pipelineTaskDelegate(phase, init) fun pipelineTask(
prefix: String,
phase: GenerationPhase,
init: PipelineTask.Builder.() -> Unit
): ReadOnlyProperty<Any, PipelineTask> =
cached { name -> PipelineTask.Builder(withPrefix(prefix, name), phase).apply(init).build() }
fun <A, B : Any> task1(init: Task1.Builder<A, B>.() -> Unit) = fun <A, B : Any> task1(
context.task1Delegate(init) prefix: String,
init: Task1.Builder<A, B>.() -> Unit
): ReadOnlyProperty<Any, Task1<A, B>> = cached { name -> Task1.Builder<A, B>(withPrefix(prefix, name)).apply(init).build() }
fun <T : Any> property(defaultValue: T, init: Property.Builder<T>.() -> Unit = {}) = fun <T : Any> property(
context.propertyDelegate(init, defaultValue) prefix: String,
defaultValue: T,
init: Property.Builder<T>.() -> Unit = {}
): ReadOnlyProperty<Any, Property<T>> =
cached { name -> Property.Builder(withPrefix(prefix, name), defaultValue).apply(init).build() }
fun <T : Any> listProperty(vararg defaultValues: T, init: Property.Builder<List<T>>.() -> Unit = {}) = fun <T : Any> listProperty(prefix: String, vararg defaultValues: T, init: Property.Builder<List<T>>.() -> Unit = {}) =
property(defaultValues.toList(), init) property(prefix, defaultValues.toList(), init)
private fun withPrefix(name: String, prefix: String): String = if (prefix.isNotEmpty()) "$prefix.$name" else name
// setting types override fun <V : Any, T : SettingType<V>> settingDelegate(
prefix: String,
create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, PluginSetting<V, T>> = cached { name -> PluginSetting(create(withPrefix(name, prefix)).buildInternal()) }
@Suppress("UNCHECKED_CAST") // setting types
final override fun <V : DisplayableSettingItem> dropDownSetting(
title: String,
neededAtPhase: GenerationPhase,
parser: Parser<V>,
init: DropDownSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, PluginSetting<V, DropDownSettingType<V>>> =
super.dropDownSetting(
title,
neededAtPhase,
parser,
init
) as ReadOnlyProperty<Any, PluginSetting<V, DropDownSettingType<V>>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun stringSetting( override fun <V : DisplayableSettingItem> dropDownSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
init: StringSettingType.Builder.() -> Unit parser: Parser<V>,
): ReadOnlyProperty<Any, PluginSetting<String, StringSettingType>> = prefix: String,
super.stringSetting( init: DropDownSettingType.Builder<V>.() -> Unit
title, ): ReadOnlyProperty<Any, PluginSetting<V, DropDownSettingType<V>>> =
neededAtPhase, super.dropDownSetting(
init title,
) as ReadOnlyProperty<Any, PluginSetting<String, StringSettingType>> neededAtPhase,
parser,
prefix,
init
) as ReadOnlyProperty<Any, PluginSetting<V, DropDownSettingType<V>>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun booleanSetting( override fun stringSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
init: BooleanSettingType.Builder.() -> Unit prefix: String,
): ReadOnlyProperty<Any, PluginSetting<Boolean, BooleanSettingType>> = init: StringSettingType.Builder.() -> Unit
super.booleanSetting( ): ReadOnlyProperty<Any, PluginSetting<String, StringSettingType>> =
title, super.stringSetting(
neededAtPhase, title,
init neededAtPhase,
) as ReadOnlyProperty<Any, PluginSetting<Boolean, BooleanSettingType>> prefix,
init
) as ReadOnlyProperty<Any, PluginSetting<String, StringSettingType>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun <V : Any> valueSetting( override fun booleanSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, prefix: String,
init: ValueSettingType.Builder<V>.() -> Unit init: BooleanSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, PluginSetting<V, ValueSettingType<V>>> = ): ReadOnlyProperty<Any, PluginSetting<Boolean, BooleanSettingType>> =
super.valueSetting( super.booleanSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, prefix,
init init
) as ReadOnlyProperty<Any, PluginSetting<V, ValueSettingType<V>>> ) as ReadOnlyProperty<Any, PluginSetting<Boolean, BooleanSettingType>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun versionSetting( override fun <V : Any> valueSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
init: VersionSettingType.Builder.() -> Unit parser: Parser<V>,
): ReadOnlyProperty<Any, PluginSetting<Version, VersionSettingType>> = prefix: String,
super.versionSetting( init: ValueSettingType.Builder<V>.() -> Unit
title, ): ReadOnlyProperty<Any, PluginSetting<V, ValueSettingType<V>>> =
neededAtPhase, super.valueSetting(
init title,
) as ReadOnlyProperty<Any, PluginSetting<Version, VersionSettingType>> neededAtPhase,
parser,
prefix,
init
) as ReadOnlyProperty<Any, PluginSetting<V, ValueSettingType<V>>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun <V : Any> listSetting( override fun versionSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, prefix: String,
init: ListSettingType.Builder<V>.() -> Unit init: VersionSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, PluginSetting<List<V>, ListSettingType<V>>> = ): ReadOnlyProperty<Any, PluginSetting<Version, VersionSettingType>> =
super.listSetting( super.versionSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, prefix,
init init
) as ReadOnlyProperty<Any, PluginSetting<List<V>, ListSettingType<V>>> ) as ReadOnlyProperty<Any, PluginSetting<Version, VersionSettingType>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
final override fun pathSetting( override fun <V : Any> listSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
init: PathSettingType.Builder.() -> Unit parser: Parser<V>,
): ReadOnlyProperty<Any, PluginSetting<Path, PathSettingType>> = prefix: String,
super.pathSetting(title, neededAtPhase, init) as ReadOnlyProperty<Any, PluginSetting<Path, PathSettingType>> init: ListSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, PluginSetting<List<V>, ListSettingType<V>>> =
super.listSetting(
title,
neededAtPhase,
parser,
prefix,
init
) as ReadOnlyProperty<Any, PluginSetting<List<V>, ListSettingType<V>>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
inline fun <reified E> enumSetting( override fun pathSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {} prefix: String,
): ReadOnlyProperty<Any, PluginSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem = init: PathSettingType.Builder.() -> Unit
enumSettingImpl(title, neededAtPhase, init) as ReadOnlyProperty<Any, PluginSetting<E, DropDownSettingType<E>>> ): ReadOnlyProperty<Any, PluginSetting<Path, PathSettingType>> =
super.pathSetting(title, neededAtPhase, prefix, init) as ReadOnlyProperty<Any, PluginSetting<Path, PathSettingType>>
@Suppress("UNCHECKED_CAST")
inline fun <reified E> enumSetting(
title: String,
neededAtPhase: GenerationPhase,
prefix: String,
crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {}
): ReadOnlyProperty<Any, PluginSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem =
enumSettingImpl(title, neededAtPhase, prefix, init) as ReadOnlyProperty<Any, PluginSetting<E, DropDownSettingType<E>>>
}
} }
val PluginReference.withParentPlugins
get() = generateSequence(this) { klass ->
klass.supertypes.firstOrNull { supertype ->
supertype.classifier?.safeAs<KClass<Plugin>>()
?.isSubclassOf(Plugin::class) == true
}?.classifier
?.safeAs<KClass<Plugin>>()
?.takeIf { superClass ->
superClass.simpleName != null
}
}
val PluginReference.name
get() = simpleName
?.removeSuffix("Plugin")
?.decapitalize()
.orEmpty()
val PluginReference.path
get() = withParentPlugins.mapNotNull { klass ->
klass.name.takeIf { it.isNotEmpty() }
}.toList()
.reversed()
.joinToString(".")
@@ -1,12 +1,6 @@
package org.jetbrains.kotlin.tools.projectWizard.core.entity package org.jetbrains.kotlin.tools.projectWizard.core.entity
import org.jetbrains.kotlin.tools.projectWizard.SettingsOwner
import org.jetbrains.kotlin.tools.projectWizard.core.PluginReference
import org.jetbrains.kotlin.tools.projectWizard.core.path
import org.jetbrains.kotlin.tools.projectWizard.core.safeAs import org.jetbrains.kotlin.tools.projectWizard.core.safeAs
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.javaGetter
interface Entity { interface Entity {
val path: String val path: String
@@ -18,17 +12,3 @@ abstract class EntityBase: Entity {
} }
abstract class EntityWithValue<out T : Any> : EntityBase() abstract class EntityWithValue<out T : Any> : EntityBase()
typealias EntityReference = KProperty1<out SettingsOwner, Entity>
val EntityReference.path
get() = "${plugin.path}.$name"
@Suppress("UNCHECKED_CAST")
val <EP : EntityReference> EP.original
get() = plugin.declaredMemberProperties.first { it.name == name } as EP
@Suppress("UNCHECKED_CAST")
val EntityReference.plugin: PluginReference
get() = javaGetter!!.declaringClass.kotlin as PluginReference
@@ -1,47 +0,0 @@
package org.jetbrains.kotlin.tools.projectWizard.core.entity
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
abstract class EntityContext<E : Entity, ER : EntityReference> {
private val entities = mutableMapOf<ER, E>()
open fun addEntity(entityReference: ER, createEntityByName: (String) -> E): E =
createEntityByName(entityReference.original.path).also {
entities[entityReference.original] = it
}
fun getEntity(entityReference: ER): E? = entities[entityReference.original]
fun getAll(): List<E> = entities.values.toList()
}
abstract class ValuedEntityContext<E : EntityWithValue<Any>, ER : EntityReference> : EntityContext<E, ER>() {
private val values = mutableMapOf<String, Any>()
operator fun get(entityReference: ER) =
values[entityReference.original.path]
operator fun get(entityPath: String) =
values[entityPath]
open operator fun set(entityReference: ER, value: Any) {
values[entityReference.original.path] = value
}
open operator fun set(entityPath: String, value: Any) {
values[entityPath] = value
}
val allValues: Map<String, Any> = values
}
@Suppress("UNCHECKED_CAST")
fun <E : Entity, A : E, ER : EntityReference> entityDelegate(
entityContext: EntityContext<E, ER>,
createEntityByPath: (String) -> A
) = object : ReadOnlyProperty<Any, A> {
override fun getValue(thisRef: Any, property: KProperty<*>): A =
entityContext.getEntity(property as ER) as? A
?: entityContext.addEntity(property, createEntityByPath) as A
}
@@ -1,12 +1,6 @@
package org.jetbrains.kotlin.tools.projectWizard.core.entity package org.jetbrains.kotlin.tools.projectWizard.core.entity
import org.jetbrains.kotlin.tools.projectWizard.core.Plugin class PropertyContext : ValuedEntityContext<Property<Any>>()
import kotlin.reflect.KProperty1
typealias PropertyReference<T> = KProperty1<out Plugin, Property<T>>
class PropertyContext : ValuedEntityContext<Property<Any>, PropertyReference<Any>>()
data class Property<out T : Any>( data class Property<out T : Any>(
override val path: String, override val path: String,
@@ -6,12 +6,6 @@ import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
typealias TaskReference = KProperty1<out Plugin, Task>
typealias Task1Reference<A, B> = KProperty1<out Plugin, Task1<A, B>>
typealias PipelineTaskReference = KProperty1<out Plugin, PipelineTask>
class TaskContext : EntityContext<Task, TaskReference>()
sealed class Task : EntityBase() sealed class Task : EntityBase()
data class Task1<A, B : Any>( data class Task1<A, B : Any>(
@@ -32,8 +26,8 @@ data class Task1<A, B : Any>(
data class PipelineTask( data class PipelineTask(
override val path: String, override val path: String,
val action: Writer.() -> TaskResult<Unit>, val action: Writer.() -> TaskResult<Unit>,
val before: List<PipelineTaskReference>, val before: List<PipelineTask>,
val after: List<PipelineTaskReference>, val after: List<PipelineTask>,
val phase: GenerationPhase, val phase: GenerationPhase,
val isAvailable: Checker, val isAvailable: Checker,
val title: String? val title: String?
@@ -43,8 +37,8 @@ data class PipelineTask(
private val phase: GenerationPhase private val phase: GenerationPhase
) { ) {
private var action: Writer.() -> TaskResult<Unit> = { UNIT_SUCCESS } private var action: Writer.() -> TaskResult<Unit> = { UNIT_SUCCESS }
private val before = mutableListOf<PipelineTaskReference>() private val before = mutableListOf<PipelineTask>()
private val after = mutableListOf<PipelineTaskReference>() private val after = mutableListOf<PipelineTask>()
var isAvailable: Checker = ALWAYS_AVAILABLE_CHECKER var isAvailable: Checker = ALWAYS_AVAILABLE_CHECKER
@@ -55,11 +49,11 @@ data class PipelineTask(
this.action = action this.action = action
} }
fun runBefore(vararg before: PipelineTaskReference) { fun runBefore(vararg before: PipelineTask) {
this.before.addAll(before) this.before.addAll(before)
} }
fun runAfter(vararg after: PipelineTaskReference) { fun runAfter(vararg after: PipelineTask) {
this.after.addAll(after) this.after.addAll(after)
} }
@@ -0,0 +1,15 @@
package org.jetbrains.kotlin.tools.projectWizard.core.entity
abstract class ValuedEntityContext<E : EntityWithValue<Any>> {
private val values = mutableMapOf<String, Any>()
@Suppress("UNCHECKED_CAST")
operator fun <V : Any> get(entity: E) =
values[entity.path] as? V
open operator fun set(entity: E, value: Any) {
values[entity.path] = value
}
}
@@ -6,9 +6,6 @@
package org.jetbrains.kotlin.tools.projectWizard.core.entity.settings package org.jetbrains.kotlin.tools.projectWizard.core.entity.settings
import org.jetbrains.kotlin.tools.projectWizard.core.EventManager import org.jetbrains.kotlin.tools.projectWizard.core.EventManager
import org.jetbrains.kotlin.tools.projectWizard.core.entity.path
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class SettingContext { class SettingContext {
private val values = mutableMapOf<String, Any>() private val values = mutableMapOf<String, Any>()
@@ -32,27 +29,10 @@ class SettingContext {
fun <V : Any, T : SettingType<V>> getPluginSetting(pluginSettingReference: PluginSettingReference<V, T>) = fun <V : Any, T : SettingType<V>> getPluginSetting(pluginSettingReference: PluginSettingReference<V, T>) =
pluginSettings[pluginSettingReference.path] as PluginSetting<V, T> pluginSettings[pluginSettingReference.path] as PluginSetting<V, T>
@Suppress("UNCHECKED_CAST") fun <V : Any, T : SettingType<V>> setPluginSetting(
private fun <V : Any, T : SettingType<V>> getPluginSetting(pluginSettingReference: PluginSettingPropertyReference<V, T>) = pluginSettingReference: PluginSettingReference<V, T>,
pluginSettings[pluginSettingReference.path] as? PluginSetting<V, T>
private fun <V : Any, T : SettingType<V>> setPluginSetting(
pluginSettingReference: PluginSettingPropertyReference<V, T>,
setting: PluginSetting<V, T> setting: PluginSetting<V, T>
) { ) {
pluginSettings[pluginSettingReference.path] = setting pluginSettings[pluginSettingReference.path] = setting
} }
fun <V : Any, T : SettingType<V>> settingDelegate(
create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, PluginSetting<V, T>> = object : ReadOnlyProperty<Any, PluginSetting<V, T>> {
override fun getValue(thisRef: Any, property: KProperty<*>): PluginSetting<V, T> {
@Suppress("UNCHECKED_CAST")
val reference = property as PluginSettingPropertyReference<V, T>
getPluginSetting(reference)?.let { return it }
val setting = PluginSetting(create(reference.path).buildInternal())
setPluginSetting(reference, setting)
return setting
}
}
} }
@@ -7,15 +7,12 @@ package org.jetbrains.kotlin.tools.projectWizard.core.entity.settings
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.Identificator import org.jetbrains.kotlin.tools.projectWizard.Identificator
import org.jetbrains.kotlin.tools.projectWizard.core.Plugin
import org.jetbrains.kotlin.tools.projectWizard.core.Reader import org.jetbrains.kotlin.tools.projectWizard.core.Reader
import org.jetbrains.kotlin.tools.projectWizard.core.entity.path
import org.jetbrains.kotlin.tools.projectWizard.core.safeAs import org.jetbrains.kotlin.tools.projectWizard.core.safeAs
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.ModuleConfigurator import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.ModuleConfigurator
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
import org.jetbrains.kotlin.tools.projectWizard.templates.Template import org.jetbrains.kotlin.tools.projectWizard.templates.Template
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
sealed class SettingReference<out V : Any, out T : SettingType<V>> { sealed class SettingReference<out V : Any, out T : SettingType<V>> {
@@ -35,9 +32,6 @@ data class PluginSettingReference<out V : Any, out T : SettingType<V>>(
override val type: KClass<@UnsafeVariance T> override val type: KClass<@UnsafeVariance T>
) : SettingReference<V, T>() { ) : SettingReference<V, T>() {
constructor(kProperty: KProperty1<out Plugin, PluginSetting<V, T>>, type: KClass<T>) :
this(kProperty.path, type)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
constructor(setting: PluginSetting<V, T>) : constructor(setting: PluginSetting<V, T>) :
this(setting.path, setting.type::class as KClass<T>) this(setting.path, setting.type::class as KClass<T>)
@@ -112,8 +106,8 @@ data class IdBasedTemplateSettingReference<V : Any, T : SettingType<V>>(
override val module: Module? = null override val module: Module? = null
} }
inline val <V : Any, reified T : SettingType<V>> PluginSettingPropertyReference<V, T>.reference: PluginSettingReference<V, T> /*inline val <V : Any, reified T : SettingType<V>> PluginSettingPropertyReference<V, T>.reference: PluginSettingReference<V, T>
get() = PluginSettingReference(this, T::class) get() = PluginSettingReference(this, T::class)
typealias PluginSettingPropertyReference<V, T> = KProperty1<out Plugin, PluginSetting<V, T>> typealias PluginSettingPropertyReference<V, T> = KProperty1<out Plugin, PluginSetting<V, T>>*/
@@ -3,7 +3,6 @@ package org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.plus import kotlinx.collections.immutable.plus
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
import kotlin.reflect.full.isSubclassOf
interface IrsOwner { interface IrsOwner {
@@ -20,7 +19,7 @@ fun <I : IrsOwner> I.withIrs(vararg irs: BuildSystemIR) = withReplacedIrs(irs =
inline fun <reified I : BuildSystemIR> IrsOwner.irsOfType(): List<I> = inline fun <reified I : BuildSystemIR> IrsOwner.irsOfType(): List<I> =
irs.filterIsInstance<I>().let { irs -> irs.filterIsInstance<I>().let { irs ->
if (I::class.isSubclassOf(BuildSystemIRWithPriority::class)) if (irs.all { it is BuildSystemIRWithPriority })
irs.sortedBy { (it as BuildSystemIRWithPriority).priority } irs.sortedBy { (it as BuildSystemIRWithPriority).priority }
else irs else irs
} }
@@ -44,7 +44,7 @@ interface AndroidModuleConfigurator : ModuleConfigurator,
get() = ModuleType.android get() = ModuleType.android
override fun getPluginSettings(): List<PluginSettingReference<Any, SettingType<Any>>> = override fun getPluginSettings(): List<PluginSettingReference<Any, SettingType<Any>>> =
listOf(AndroidPlugin::androidSdkPath.reference) listOf(AndroidPlugin.androidSdkPath.reference)
override fun createBuildFileIRs( override fun createBuildFileIRs(
reader: Reader, reader: Reader,
@@ -66,7 +66,7 @@ interface AndroidModuleConfigurator : ModuleConfigurator,
fun Reader.createAndroidPlugin(module: Module): AndroidGradlePlugin fun Reader.createAndroidPlugin(module: Module): AndroidGradlePlugin
override fun Reader.createSettingsGradleIRs(module: Module) = buildList<BuildSystemIR> { override fun Reader.createSettingsGradleIRs(module: Module) = buildList<BuildSystemIR> {
+createRepositories(KotlinPlugin::version.propertyValue).map { PluginManagementRepositoryIR(RepositoryIR(it)) } +createRepositories(KotlinPlugin.version.propertyValue).map { PluginManagementRepositoryIR(RepositoryIR(it)) }
+AndroidResolutionStrategyIR(Versions.GRADLE_PLUGINS.ANDROID) +AndroidResolutionStrategyIR(Versions.GRADLE_PLUGINS.ANDROID)
} }
@@ -154,7 +154,7 @@ object AndroidTargetConfigurator : TargetConfigurator,
): TaskResult<Unit> = computeM { ): TaskResult<Unit> = computeM {
val javaPackage = module.javaPackage(configurationData.pomIr) val javaPackage = module.javaPackage(configurationData.pomIr)
val settings = mapOf("package" to javaPackage.asCodePackage()) val settings = mapOf("package" to javaPackage.asCodePackage())
TemplatesPlugin::addFileTemplates.execute( TemplatesPlugin.addFileTemplates.execute(
listOf( listOf(
FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidManifestForLibraryXml, modulePath, settings) FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidManifestForLibraryXml, modulePath, settings)
) )
@@ -96,7 +96,7 @@ object AndroidSinglePlatformModuleConfigurator :
): TaskResult<Unit> = computeM { ): TaskResult<Unit> = computeM {
val javaPackage = module.javaPackage(configurationData.pomIr) val javaPackage = module.javaPackage(configurationData.pomIr)
val settings = mapOf("package" to javaPackage.asCodePackage()) val settings = mapOf("package" to javaPackage.asCodePackage())
TemplatesPlugin::addFileTemplates.execute( TemplatesPlugin.addFileTemplates.execute(
listOf( listOf(
FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.activityMainXml, modulePath, settings), FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.activityMainXml, modulePath, settings),
FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidManifestXml, modulePath, settings), FileTemplate(AndroidModuleConfigurator.FileTemplateDescriptors.androidManifestXml, modulePath, settings),
@@ -36,7 +36,7 @@ object IOSSinglePlatformModuleConfigurator : SinglePlatformModuleConfigurator, M
module: Module, module: Module,
modulePath: Path modulePath: Path
): TaskResult<Unit> = ): TaskResult<Unit> =
GradlePlugin::gradleProperties.addValues("xcodeproj" to "./${module.name}") GradlePlugin.gradleProperties.addValues("xcodeproj" to "./${module.name}")
override fun Reader.createTemplates( override fun Reader.createTemplates(
configurationData: ModulesToIrConversionData, configurationData: ModulesToIrConversionData,
@@ -62,6 +62,7 @@ fun <V : Any, T : SettingType<V>> Reader.settingValue(module: Module, setting: M
abstract class ModuleConfiguratorSettings : SettingsOwner { abstract class ModuleConfiguratorSettings : SettingsOwner {
final override fun <V : Any, T : SettingType<V>> settingDelegate( final override fun <V : Any, T : SettingType<V>> settingDelegate(
prefix: String,
create: (path: String) -> SettingBuilder<V, T> create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any?, ModuleConfiguratorSetting<V, T>> = cached { name -> ): ReadOnlyProperty<Any?, ModuleConfiguratorSetting<V, T>> = cached { name ->
ModuleConfiguratorSetting(create(name).buildInternal()) ModuleConfiguratorSetting(create(name).buildInternal())
@@ -72,12 +73,14 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: DropDownSettingType.Builder<V>.() -> Unit init: DropDownSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, DropDownSettingType<V>>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, DropDownSettingType<V>>> =
super.dropDownSetting( super.dropDownSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, DropDownSettingType<V>>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, DropDownSettingType<V>>>
@@ -85,11 +88,13 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
final override fun stringSetting( final override fun stringSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: StringSettingType.Builder.() -> Unit init: StringSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<String, StringSettingType>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<String, StringSettingType>> =
super.stringSetting( super.stringSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<String, StringSettingType>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<String, StringSettingType>>
@@ -97,11 +102,13 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
final override fun booleanSetting( final override fun booleanSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: BooleanSettingType.Builder.() -> Unit init: BooleanSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Boolean, BooleanSettingType>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Boolean, BooleanSettingType>> =
super.booleanSetting( super.booleanSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Boolean, BooleanSettingType>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Boolean, BooleanSettingType>>
@@ -110,12 +117,14 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: ValueSettingType.Builder<V>.() -> Unit init: ValueSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, ValueSettingType<V>>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, ValueSettingType<V>>> =
super.valueSetting( super.valueSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, ValueSettingType<V>>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<V, ValueSettingType<V>>>
@@ -123,11 +132,13 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
final override fun versionSetting( final override fun versionSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: VersionSettingType.Builder.() -> Unit init: VersionSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Version, VersionSettingType>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Version, VersionSettingType>> =
super.versionSetting( super.versionSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Version, VersionSettingType>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Version, VersionSettingType>>
@@ -136,12 +147,14 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: ListSettingType.Builder<V>.() -> Unit init: ListSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<List<V>, ListSettingType<V>>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<List<V>, ListSettingType<V>>> =
super.listSetting( super.listSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<List<V>, ListSettingType<V>>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<List<V>, ListSettingType<V>>>
@@ -149,11 +162,13 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
final override fun pathSetting( final override fun pathSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: PathSettingType.Builder.() -> Unit init: PathSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Path, PathSettingType>> = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<Path, PathSettingType>> =
super.pathSetting( super.pathSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Path, PathSettingType>> ) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<Path, PathSettingType>>
@@ -161,9 +176,10 @@ abstract class ModuleConfiguratorSettings : SettingsOwner {
inline fun <reified E> enumSetting( inline fun <reified E> enumSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {} crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {}
): ReadOnlyProperty<Any, ModuleConfiguratorSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem = ): ReadOnlyProperty<Any, ModuleConfiguratorSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem =
enumSettingImpl(title, neededAtPhase, init) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<E, DropDownSettingType<E>>> enumSettingImpl(title, neededAtPhase, prefix, init) as ReadOnlyProperty<Any, ModuleConfiguratorSetting<E, DropDownSettingType<E>>>
} }
interface ModuleConfiguratorWithSettings : ModuleConfigurator { interface ModuleConfiguratorWithSettings : ModuleConfigurator {
@@ -63,7 +63,7 @@ interface ModuleConfiguratorWithTests : ModuleConfiguratorWithSettings {
dependencyName, dependencyName,
isInMppModule = module.kind isInMppModule = module.kind
.let { it == ModuleKind.multiplatform || it == ModuleKind.target }, .let { it == ModuleKind.multiplatform || it == ModuleKind.target },
kotlinVersion = KotlinPlugin::version.propertyValue, kotlinVersion = KotlinPlugin.version.propertyValue,
dependencyType = DependencyType.TEST dependencyType = DependencyType.TEST
) )
} }
@@ -1,6 +1,7 @@
package org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators package org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators
import kotlinx.collections.immutable.toPersistentList
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.core.Reader import org.jetbrains.kotlin.tools.projectWizard.core.Reader
@@ -10,10 +11,15 @@ import org.jetbrains.kotlin.tools.projectWizard.core.safeAs
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.KotlinBuildSystemPluginIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.KotlinBuildSystemPluginIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.DefaultTargetConfigurationIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.multiplatform.TargetAccessIR
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.maven.MavenPropertyIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.maven.MavenPropertyIR
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
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.buildSystem.gradle.GradlePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle 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.ModuleType
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
@@ -11,9 +11,8 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Plugin
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
import org.jetbrains.kotlin.tools.projectWizard.core.checker import org.jetbrains.kotlin.tools.projectWizard.core.checker
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.Task import org.jetbrains.kotlin.tools.projectWizard.core.entity.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.AndroidModuleConfigurator import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.AndroidModuleConfigurator
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.allIRModules import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.allIRModules
@@ -22,36 +21,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.withAllSubModules import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.withAllSubModules
class AndroidPlugin(context: Context) : Plugin(context) { class AndroidPlugin(context: Context) : Plugin(context) {
override val path = "android" override val path = PATH
val androidSdkPath by pathSetting(
KotlinNewProjectWizardBundle.message("plugin.android.setting.sdk"),
neededAtPhase = GenerationPhase.PROJECT_GENERATION
) {
isSavable = true
isAvailable = isAndroidContainingProject
shouldExists()
}
private val isAndroidContainingProject = checker {
KotlinPlugin::modules.settingValue
.withAllSubModules(includeSourcesets = true)
.any { it.configurator is AndroidModuleConfigurator }
}
val addAndroidSdkToLocalProperties by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runBefore(GradlePlugin::createLocalPropertiesFile)
runAfter(KotlinPlugin::createModules)
isAvailable = isAndroidContainingProject
withAction {
if (allIRModules.none { it.originalModule.configurator is AndroidModuleConfigurator }) return@withAction UNIT_SUCCESS
val path = AndroidPlugin::androidSdkPath.settingValue
val fileSystemService = service<FileSystemWizardService>()
GradlePlugin::localProperties.addValues(
"sdk.dir" to fileSystemService.renderPath(path)
)
}
}
override val settings: List<PluginSetting<*, *>> = listOf( override val settings: List<PluginSetting<*, *>> = listOf(
androidSdkPath androidSdkPath
@@ -59,4 +29,40 @@ class AndroidPlugin(context: Context) : Plugin(context) {
override val pipelineTasks: List<PipelineTask> = listOf( override val pipelineTasks: List<PipelineTask> = listOf(
addAndroidSdkToLocalProperties addAndroidSdkToLocalProperties
) )
override val properties: List<Property<*>> = listOf()
companion object {
private const val PATH = "android"
val androidSdkPath by pathSetting(
KotlinNewProjectWizardBundle.message("plugin.android.setting.sdk"),
neededAtPhase = GenerationPhase.PROJECT_GENERATION,
PATH
) {
isSavable = true
isAvailable = isAndroidContainingProject
shouldExists()
}
private val isAndroidContainingProject = checker {
KotlinPlugin.modules.settingValue
.withAllSubModules(includeSourcesets = true)
.any { it.configurator is AndroidModuleConfigurator }
}
val addAndroidSdkToLocalProperties by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(GradlePlugin.createLocalPropertiesFile)
runAfter(KotlinPlugin.createModules)
isAvailable = isAndroidContainingProject
withAction {
if (allIRModules.none { it.originalModule.configurator is AndroidModuleConfigurator }) return@withAction UNIT_SUCCESS
val path = androidSdkPath.settingValue
val fileSystemService = service<FileSystemWizardService>()
GradlePlugin.localProperties.addValues(
"sdk.dir" to fileSystemService.renderPath(path)
)
}
}
}
} }
@@ -10,27 +10,33 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.Plugin import org.jetbrains.kotlin.tools.projectWizard.core.Plugin
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.service.RunConfigurationsService import org.jetbrains.kotlin.tools.projectWizard.core.service.RunConfigurationsService
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
class RunConfigurationsPlugin(context: Context) : Plugin(context) { class RunConfigurationsPlugin(context: Context) : Plugin(context) {
override val path = "runConfigurations" override val path = PATH
val configurations by listProperty<WizardRunConfiguration>()
val createRunConfigurationsTask by pipelineTask(GenerationPhase.PROJECT_IMPORT) {
runBefore(BuildSystemPlugin::importProject)
withAction {
service<RunConfigurationsService>().apply {
addRunConfigurations(RunConfigurationsPlugin::configurations.propertyValue)
}
UNIT_SUCCESS
}
}
override val settings: List<PluginSetting<*, *>> = emptyList() override val settings: List<PluginSetting<*, *>> = emptyList()
override val pipelineTasks: List<PipelineTask> = listOf(createRunConfigurationsTask) override val pipelineTasks: List<PipelineTask> = listOf(createRunConfigurationsTask)
override val properties: List<Property<*>> = listOf(configurations)
companion object {
private const val PATH = "runConfigurations"
val configurations by listProperty<WizardRunConfiguration>(PATH)
val createRunConfigurationsTask by pipelineTask(PATH, GenerationPhase.PROJECT_IMPORT) {
runBefore(BuildSystemPlugin.importProject)
withAction {
service<RunConfigurationsService>().apply {
addRunConfigurations(configurations.propertyValue)
}
UNIT_SUCCESS
}
}
}
} }
@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.core.* 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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators
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.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
@@ -17,58 +18,70 @@ import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
class StructurePlugin(context: Context) : Plugin(context) { class StructurePlugin(context: Context) : Plugin(context) {
override val path = "structure" override val path = PATH
val projectPath by pathSetting( companion object {
KotlinNewProjectWizardBundle.message("plugin.structure.setting.location"), private const val PATH = "structure"
GenerationPhase.FIRST_STEP
) {
defaultValue = value(Paths.get("."))
validateOnProjectCreation = false private val ALLOWED_SPECIAL_CHARS_IN_GROUP_ID = Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES + '.'
private val ALLOWED_SPECIAL_CHARS_IN_ARTIFACT_ID = Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES
private val ALLOWED_SPECIAL_CHARS_IN_VERSION = setOf('_', '-', '.')
validate { path -> val projectPath by pathSetting(
if (!Files.exists(path)) return@validate ValidationResult.OK KotlinNewProjectWizardBundle.message("plugin.structure.setting.location"),
ValidationResult.create(Files.list(path).noneMatch { true }) { GenerationPhase.FIRST_STEP,
KotlinNewProjectWizardBundle.message("plugin.structure.setting.location.error.is.not.empty") PATH
) {
defaultValue = value(Paths.get("."))
validateOnProjectCreation = false
validate { path ->
if (!Files.exists(path)) return@validate ValidationResult.OK
ValidationResult.create(Files.list(path).noneMatch { true }) {
KotlinNewProjectWizardBundle.message("plugin.structure.setting.location.error.is.not.empty")
}
} }
} }
} val name by stringSetting(
val name by stringSetting( KotlinNewProjectWizardBundle.message("plugin.structure.setting.name"),
KotlinNewProjectWizardBundle.message("plugin.structure.setting.name"), GenerationPhase.FIRST_STEP,
GenerationPhase.FIRST_STEP PATH
) { ) {
shouldNotBeBlank() shouldNotBeBlank()
validate(StringValidators.shouldBeValidIdentifier(title, Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES)) validate(StringValidators.shouldBeValidIdentifier(title, Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES))
} }
val groupId by stringSetting( val groupId by stringSetting(
KotlinNewProjectWizardBundle.message("plugin.structure.setting.group.id"), KotlinNewProjectWizardBundle.message("plugin.structure.setting.group.id"),
GenerationPhase.FIRST_STEP GenerationPhase.FIRST_STEP,
) { PATH
isSavable = true ) {
shouldNotBeBlank() isSavable = true
validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_GROUP_ID)) shouldNotBeBlank()
} validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_GROUP_ID))
val artifactId by stringSetting( }
KotlinNewProjectWizardBundle.message("plugin.structure.setting.artifact.id"), val artifactId by stringSetting(
GenerationPhase.FIRST_STEP KotlinNewProjectWizardBundle.message("plugin.structure.setting.artifact.id"),
) { GenerationPhase.FIRST_STEP,
shouldNotBeBlank() PATH
validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_ARTIFACT_ID)) ) {
} shouldNotBeBlank()
val version by stringSetting( validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_ARTIFACT_ID))
KotlinNewProjectWizardBundle.message("plugin.structure.setting.version"), }
GenerationPhase.FIRST_STEP val version by stringSetting(
) { KotlinNewProjectWizardBundle.message("plugin.structure.setting.version"),
shouldNotBeBlank() GenerationPhase.FIRST_STEP,
validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_VERSION)) PATH
defaultValue = value("1.0-SNAPSHOT") ) {
} shouldNotBeBlank()
validate(StringValidators.shouldBeValidIdentifier(title, ALLOWED_SPECIAL_CHARS_IN_VERSION))
val createProjectDir by pipelineTask(GenerationPhase.PROJECT_GENERATION) { defaultValue = value("1.0-SNAPSHOT")
withAction { }
service<FileSystemWizardService>().createDirectory(StructurePlugin::projectPath.reference.settingValue) val createProjectDir by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
withAction {
service<FileSystemWizardService>().createDirectory(StructurePlugin.projectPath.settingValue)
}
} }
} }
@@ -82,23 +95,18 @@ class StructurePlugin(context: Context) : Plugin(context) {
) )
override val pipelineTasks: List<PipelineTask> = override val pipelineTasks: List<PipelineTask> =
listOf(createProjectDir) listOf(createProjectDir)
override val properties: List<Property<*>> = listOf()
companion object {
private val ALLOWED_SPECIAL_CHARS_IN_GROUP_ID = Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES + '.'
private val ALLOWED_SPECIAL_CHARS_IN_ARTIFACT_ID = Module.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES
private val ALLOWED_SPECIAL_CHARS_IN_VERSION = setOf('_', '-', '.')
}
} }
val Reader.projectPath val Reader.projectPath
get() = StructurePlugin::projectPath.reference.settingValue get() = StructurePlugin.projectPath.settingValue
val Reader.projectName val Reader.projectName
get() = StructurePlugin::name.reference.settingValue get() = StructurePlugin.name.settingValue
fun Writer.pomIR() = PomIR( fun Writer.pomIR() = PomIR(
artifactId = StructurePlugin::artifactId.reference.settingValue, artifactId = StructurePlugin.artifactId.settingValue,
groupId = StructurePlugin::groupId.reference.settingValue, groupId = StructurePlugin.groupId.settingValue,
version = Version.fromString(StructurePlugin::version.reference.settingValue) version = Version.fromString(StructurePlugin.version.settingValue)
) )
@@ -6,9 +6,9 @@ import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.core.* 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.Property
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.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemAvailabilityWizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemAvailabilityWizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService
import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
@@ -27,91 +27,96 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Repository
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles
abstract class BuildSystemPlugin(context: Context) : Plugin(context) { abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
override val path = "buildSystem" override val path = PATH
val type by enumSetting<BuildSystemType>( companion object {
KotlinNewProjectWizardBundle.message("plugin.buildsystem.setting.type"), private const val PATH = "buildSystem"
GenerationPhase.FIRST_STEP
) {
isSavable = true
filter = { _, type ->
val service = service<BuildSystemAvailabilityWizardService>()
service.isAvailable(type)
}
validate { buildSystemType -> val type by enumSetting<BuildSystemType>(
if (!buildSystemType.isGradle KotlinNewProjectWizardBundle.message("plugin.buildsystem.setting.type"),
&& KotlinPlugin::projectKind.reference.notRequiredSettingValue != ProjectKind.Singleplatform GenerationPhase.FIRST_STEP,
) { PATH
val projectKind = KotlinPlugin::projectKind.reference.notRequiredSettingValue?.text?.capitalize() ) {
?: KotlinNewProjectWizardBundle.message("project") isSavable = true
ValidationResult.ValidationError( filter = { _, type ->
KotlinNewProjectWizardBundle.message( val service = service<BuildSystemAvailabilityWizardService>()
"plugin.buildsystem.setting.type.error.wrong.project.kind", service.isAvailable(type)
projectKind, }
buildSystemType.fullText
validate { buildSystemType ->
if (!buildSystemType.isGradle
&& KotlinPlugin.projectKind.notRequiredSettingValue != ProjectKind.Singleplatform
) {
val projectKind = KotlinPlugin.projectKind.notRequiredSettingValue?.text?.capitalize()
?: KotlinNewProjectWizardBundle.message("project")
ValidationResult.ValidationError(
KotlinNewProjectWizardBundle.message(
"plugin.buildsystem.setting.type.error.wrong.project.kind",
projectKind,
buildSystemType.fullText
)
) )
) } else ValidationResult.OK
} else ValidationResult.OK }
} }
}
val buildSystemData by property<List<BuildSystemData>>(emptyList()) val buildSystemData by property<List<BuildSystemData>>(PATH, emptyList())
val buildFiles by listProperty<BuildFileIR>() val buildFiles by listProperty<BuildFileIR>(PATH)
val pluginRepositoreis by listProperty<Repository>() val pluginRepositoreis by listProperty<Repository>(PATH)
val takeRepositoriesFromDependencies by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val takeRepositoriesFromDependencies by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin::createModules) runBefore(createModules)
runAfter(TemplatesPlugin::postApplyTemplatesToModules) runAfter(TemplatesPlugin.postApplyTemplatesToModules)
withAction { withAction {
updateBuildFiles { buildFile -> updateBuildFiles { buildFile ->
val dependenciesOfModule = buildList<LibraryDependencyIR> { val dependenciesOfModule = buildList<LibraryDependencyIR> {
buildFile.modules.modules.forEach { module -> buildFile.modules.modules.forEach { module ->
if (module is SingleplatformModuleIR) module.sourcesets.forEach { sourceset -> if (module is SingleplatformModuleIR) module.sourcesets.forEach { sourceset ->
+sourceset.irs.filterIsInstance<LibraryDependencyIR>() +sourceset.irs.filterIsInstance<LibraryDependencyIR>()
}
+module.irs.filterIsInstance<LibraryDependencyIR>()
} }
+module.irs.filterIsInstance<LibraryDependencyIR>()
} }
val repositoriesToAdd = dependenciesOfModule.mapNotNull { dependency ->
dependency.artifact.safeAs<MavenArtifact>()?.repository?.let(::RepositoryIR)
}
buildFile.withIrs(repositoriesToAdd).asSuccess()
} }
val repositoriesToAdd = dependenciesOfModule.mapNotNull { dependency ->
dependency.artifact.safeAs<MavenArtifact>()?.repository?.let(::RepositoryIR)
}
buildFile.withIrs(repositoriesToAdd).asSuccess()
} }
} }
}
val createModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val createModules by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runAfter(StructurePlugin::createProjectDir) runAfter(StructurePlugin.createProjectDir)
withAction { withAction {
val fileSystem = service<FileSystemWizardService>() val fileSystem = service<FileSystemWizardService>()
val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType } val data = 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 -> buildFiles.propertyValue.mapSequenceIgnore { buildFile ->
fileSystem.createFile( fileSystem.createFile(
buildFile.directoryPath / buildFileData.buildFileName, buildFile.directoryPath / buildFileData.buildFileName,
buildFileData.createPrinter().printBuildFile { buildFile.render(this) } buildFileData.createPrinter().printBuildFile { buildFile.render(this) }
) )
}
} }
} }
}
val importProject by pipelineTask(GenerationPhase.PROJECT_IMPORT) { val importProject by pipelineTask(PATH, GenerationPhase.PROJECT_IMPORT) {
runAfter(BuildSystemPlugin::createModules) runAfter(createModules)
withAction { withAction {
val data = BuildSystemPlugin::buildSystemData.propertyValue.first { it.type == buildSystemType } val data = buildSystemData.propertyValue.first { it.type == buildSystemType }
service<ProjectImportingWizardService> { service -> service.isSuitableFor(data.type) } service<ProjectImportingWizardService> { service -> service.isSuitableFor(data.type) }
.importProject(this, StructurePlugin::projectPath.reference.settingValue, allIRModules, buildSystemType) .importProject(this, StructurePlugin.projectPath.settingValue, allIRModules, buildSystemType)
}
} }
}
protected fun addBuildSystemData(data: BuildSystemData) = pipelineTask(GenerationPhase.PREPARE) { fun addBuildSystemData(prefix: String, data: BuildSystemData) = pipelineTask(prefix, GenerationPhase.PREPARE) {
runBefore(BuildSystemPlugin::createModules) runBefore(createModules)
withAction { withAction {
BuildSystemPlugin::buildSystemData.addValues(data) buildSystemData.addValues(data)
}
} }
} }
@@ -123,6 +128,11 @@ abstract class BuildSystemPlugin(context: Context) : Plugin(context) {
createModules, createModules,
importProject, importProject,
) )
override val properties: List<Property<*>> = listOf(
buildSystemData,
buildFiles,
pluginRepositoreis
)
} }
data class BuildSystemData( data class BuildSystemData(
@@ -169,12 +179,12 @@ val BuildSystemType.isGradle
|| this == BuildSystemType.GradleKotlinDsl || this == BuildSystemType.GradleKotlinDsl
val Reader.allIRModules val Reader.allIRModules
get() = BuildSystemPlugin::buildFiles.propertyValue.flatMap { buildFile -> get() = BuildSystemPlugin.buildFiles.propertyValue.flatMap { buildFile ->
buildFile.modules.modules buildFile.modules.modules
} }
val Writer.allModulesPaths val Writer.allModulesPaths
get() = BuildSystemPlugin::buildFiles.propertyValue.flatMap { buildFile -> get() = BuildSystemPlugin.buildFiles.propertyValue.flatMap { buildFile ->
val paths = when (val structure = buildFile.modules) { val paths = when (val structure = buildFile.modules) {
is MultiplatformModulesStructureIR -> listOf(buildFile.directoryPath) is MultiplatformModulesStructureIR -> listOf(buildFile.directoryPath)
else -> structure.modules.map { it.path } else -> structure.modules.map { it.path }
@@ -189,5 +199,5 @@ val Writer.allModulesPaths
val Reader.buildSystemType: BuildSystemType val Reader.buildSystemType: BuildSystemType
get() = BuildSystemPlugin::type.reference.settingValue get() = BuildSystemPlugin.type.settingValue
@@ -1,14 +1,21 @@
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.entity.PipelineTask
class JpsPlugin(context: Context) : BuildSystemPlugin(context) { class JpsPlugin(context: Context) : BuildSystemPlugin(context) {
override val path = "buildSystem.jps" override val path = PATH
val addBuildSystemData by addBuildSystemData( companion object {
BuildSystemData( private const val PATH = "buildSystem.jps"
type = BuildSystemType.Jps, val addBuildSystemData by addBuildSystemData(
buildFileData = null PATH,
BuildSystemData(
type = BuildSystemType.Jps,
buildFileData = null
)
) )
) }
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + listOf(addBuildSystemData)
} }
@@ -14,56 +14,61 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.MavenPrinter
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.updateBuildFiles
class MavenPlugin(context: Context) : BuildSystemPlugin(context) { class MavenPlugin(context: Context) : BuildSystemPlugin(context) {
override val path = "buildSystem.maven" override val path = PATH
private val isMaven = checker { companion object {
BuildSystemPlugin::type.settingValue == BuildSystemType.Maven private const val PATH = "buildSystem.maven"
}
val createSettingsFileTask by pipelineTask(GenerationPhase.PROJECT_GENERATION) { private val isMaven = checker {
runAfter(KotlinPlugin::createModules) type.settingValue == BuildSystemType.Maven
runBefore(BuildSystemPlugin::createModules) }
isAvailable = isMaven
withAction { val createSettingsFileTask by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
BuildSystemPlugin::buildFiles.update { buildFiles -> runAfter(KotlinPlugin.createModules)
if (buildFiles.size == 1) return@update buildFiles.asSuccess() runBefore(createModules)
buildFiles.map { buildFile -> isAvailable = isMaven
when (val structure = buildFile.modules) { withAction {
is RootFileModuleStructureIR -> { buildFiles.update { buildFiles ->
val dependencies = allModulesPaths.map { path -> if (buildFiles.size == 1) return@update buildFiles.asSuccess()
path.joinToString(separator = "/") buildFiles.map { buildFile ->
when (val structure = buildFile.modules) {
is RootFileModuleStructureIR -> {
val dependencies = allModulesPaths.map { path ->
path.joinToString(separator = "/")
}
buildFile.copy(modules = structure.withIrs(ModulesDependencyMavenIR(dependencies)))
} }
buildFile.copy(modules = structure.withIrs(ModulesDependencyMavenIR(dependencies))) else -> buildFile
} }
else -> buildFile }.asSuccess()
} }
}.asSuccess()
} }
} }
}
val addBuildSystemPluginRepositories by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val addBuildSystemPluginRepositories by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createPluginRepositories) runAfter(KotlinPlugin.createPluginRepositories)
runBefore(BuildSystemPlugin::createModules) runBefore(createModules)
isAvailable = isMaven isAvailable = isMaven
withAction { withAction {
val repositories = BuildSystemPlugin::pluginRepositoreis.propertyValue val repositories = pluginRepositoreis.propertyValue
updateBuildFiles { buildFile -> updateBuildFiles { buildFile ->
buildFile.withIrs(repositories.map(::PluginRepositoryMavenIR)).asSuccess() buildFile.withIrs(repositories.map(::PluginRepositoryMavenIR)).asSuccess()
}
} }
} }
}
val addBuildSystemData by addBuildSystemData( val addBuildSystemData by addBuildSystemData(
BuildSystemData( PATH,
type = BuildSystemType.Maven, BuildSystemData(
buildFileData = BuildFileData( type = BuildSystemType.Maven,
createPrinter = { MavenPrinter() }, buildFileData = BuildFileData(
buildFileName = "pom.xml" createPrinter = { MavenPrinter() },
buildFileName = "pom.xml"
)
) )
) )
) }
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
@@ -4,8 +4,8 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.gradle
import org.jetbrains.kotlin.tools.projectWizard.Versions import org.jetbrains.kotlin.tools.projectWizard.Versions
import org.jetbrains.kotlin.tools.projectWizard.core.* 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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService 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.PluginManagementRepositoryIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.PluginManagementRepositoryIR
@@ -27,111 +27,116 @@ import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor
abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) { abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) {
override val path = "buildSystem.gradle" override val path = PATH
val gradleProperties by listProperty( companion object {
"kotlin.code.style" to "official" private const val PATH = "buildSystem.gradle"
)
val settingsGradleFileIRs by listProperty<BuildSystemIR>() val gradleProperties by listProperty(
PATH,
"kotlin.code.style" to "official"
)
val createGradlePropertiesFile by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val settingsGradleFileIRs by listProperty<BuildSystemIR>(PATH)
runAfter(KotlinPlugin::createModules)
runBefore(TemplatesPlugin::renderFileTemplates) val createGradlePropertiesFile by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
isAvailable = isGradle runAfter(KotlinPlugin.createModules)
withAction { runBefore(TemplatesPlugin.renderFileTemplates)
TemplatesPlugin::addFileTemplate.execute( isAvailable = isGradle
FileTemplate( withAction {
FileTemplateDescriptor( TemplatesPlugin.addFileTemplate.execute(
"gradle/gradle.properties.vm", FileTemplate(
"gradle.properties".asPath() FileTemplateDescriptor(
), "gradle/gradle.properties.vm",
StructurePlugin::projectPath.settingValue, "gradle.properties".asPath()
mapOf( ),
"properties" to GradlePlugin::gradleProperties StructurePlugin.projectPath.settingValue,
.propertyValue mapOf(
.distinctBy { it.first } "properties" to gradleProperties
.propertyValue
.distinctBy { it.first }
)
) )
) )
) }
} }
}
val localProperties by listProperty<Pair<String, String>>() val localProperties by listProperty<Pair<String, String>>(PATH)
val createLocalPropertiesFile by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val createLocalPropertiesFile by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createModules) runAfter(KotlinPlugin.createModules)
runBefore(TemplatesPlugin::renderFileTemplates) runBefore(TemplatesPlugin.renderFileTemplates)
isAvailable = isGradle isAvailable = isGradle
withAction { withAction {
TemplatesPlugin::addFileTemplate.execute( TemplatesPlugin.addFileTemplate.execute(
FileTemplate( FileTemplate(
FileTemplateDescriptor( FileTemplateDescriptor(
"gradle/local.properties.vm", "gradle/local.properties.vm",
"local.properties".asPath() "local.properties".asPath()
), ),
StructurePlugin::projectPath.settingValue, StructurePlugin.projectPath.settingValue,
mapOf( mapOf(
"properties" to GradlePlugin::localProperties.propertyValue "properties" to localProperties.propertyValue
)
) )
) )
) }
} }
}
private val isGradle = checker { buildSystemType.isGradle } private val isGradle = checker { buildSystemType.isGradle }
val initGradleWrapperTask by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
val initGradleWrapperTask by pipelineTask(GenerationPhase.PROJECT_GENERATION) { runBefore(TemplatesPlugin.renderFileTemplates)
runBefore(TemplatesPlugin::renderFileTemplates) isAvailable = isGradle
isAvailable = isGradle withAction {
withAction { TemplatesPlugin.addFileTemplate.execute(
TemplatesPlugin::addFileTemplate.execute( FileTemplate(
FileTemplate( FileTemplateDescriptor(
FileTemplateDescriptor( "gradle/gradle-wrapper.properties.vm",
"gradle/gradle-wrapper.properties.vm", "gradle" / "wrapper" / "gradle-wrapper.properties"
"gradle" / "wrapper" / "gradle-wrapper.properties" ),
), StructurePlugin.projectPath.settingValue,
StructurePlugin::projectPath.reference.settingValue, mapOf(
mapOf( "version" to Versions.GRADLE
"version" to Versions.GRADLE )
) )
) )
) }
}
val createSettingsFileTask by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin.createModules)
runAfter(KotlinPlugin.createPluginRepositories)
isAvailable = isGradle
withAction {
val (createBuildFile, buildFileName) = settingsGradleBuildFileData ?: return@withAction UNIT_SUCCESS
val repositories = buildList<RepositoryIR> {
+pluginRepositoreis.propertyValue.map(::RepositoryIR)
if (isNotEmpty()) {
+RepositoryIR(DefaultRepository.MAVEN_CENTRAL)
+RepositoryIR(DefaultRepository.GRADLE_PLUGIN_PORTAL)
}
}.map(::PluginManagementRepositoryIR)
val settingsGradleIR = SettingsGradleFileIR(
StructurePlugin.name.settingValue,
allModulesPaths.map { path -> path.joinToString(separator = "") { ":$it" } },
buildPersistenceList {
+repositories
+settingsGradleFileIRs.propertyValue
}
)
val buildFileText = createBuildFile().printBuildFile { settingsGradleIR.render(this) }
service<FileSystemWizardService>().createFile(
projectPath / buildFileName,
buildFileText
)
}
} }
} }
val createSettingsFileTask by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createModules)
runAfter(KotlinPlugin::createPluginRepositories)
isAvailable = isGradle
withAction {
val (createBuildFile, buildFileName) = settingsGradleBuildFileData ?: return@withAction UNIT_SUCCESS
val repositories = buildList<RepositoryIR> {
+BuildSystemPlugin::pluginRepositoreis.propertyValue.map(::RepositoryIR)
if (isNotEmpty()) {
+RepositoryIR(DefaultRepository.MAVEN_CENTRAL)
+RepositoryIR(DefaultRepository.GRADLE_PLUGIN_PORTAL)
}
}.map(::PluginManagementRepositoryIR)
val settingsGradleIR = SettingsGradleFileIR(
StructurePlugin::name.settingValue,
allModulesPaths.map { path -> path.joinToString(separator = "") { ":$it" } },
buildPersistenceList {
+repositories
+GradlePlugin::settingsGradleFileIRs.propertyValue
}
)
val buildFileText = createBuildFile().printBuildFile { settingsGradleIR.render(this) }
service<FileSystemWizardService>().createFile(
projectPath / buildFileName,
buildFileText
)
}
}
override val settings: List<PluginSetting<*, *>> = super.settings override val settings: List<PluginSetting<*, *>> = super.settings
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
@@ -140,7 +145,12 @@ abstract class GradlePlugin(context: Context) : BuildSystemPlugin(context) {
initGradleWrapperTask, initGradleWrapperTask,
createSettingsFileTask, createSettingsFileTask,
) )
override val properties: List<Property<*>> = super.properties +
listOf(
gradleProperties,
settingsGradleFileIRs,
localProperties
)
} }
val Reader.settingsGradleBuildFileData val Reader.settingsGradleBuildFileData
@@ -8,17 +8,22 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemT
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
class GroovyDslPlugin(context: Context) : GradlePlugin(context) { class GroovyDslPlugin(context: Context) : GradlePlugin(context) {
override val path = "buildSystem.gradle.groovyDsl" override val path = PATH
val addBuildSystemData by addBuildSystemData( companion object {
BuildSystemData( private const val PATH = "buildSystem.gradle.groovyDsl"
type = BuildSystemType.GradleGroovyDsl,
buildFileData = BuildFileData( val addBuildSystemData by addBuildSystemData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.GROOVY) }, PATH,
buildFileName = "build.gradle" BuildSystemData(
type = BuildSystemType.GradleGroovyDsl,
buildFileData = BuildFileData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.GROOVY) },
buildFileName = "build.gradle"
)
) )
) )
) }
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
@@ -8,17 +8,23 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemT
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
class KotlinDslPlugin(context: Context) : GradlePlugin(context) { class KotlinDslPlugin(context: Context) : GradlePlugin(context) {
override val path = "buildSystem.gradle.kotlinDsl" override val path = PATH
val addBuildSystemData by addBuildSystemData( companion object {
BuildSystemData( private const val PATH = "buildSystem.gradle.kotlinDsl"
type = BuildSystemType.GradleKotlinDsl,
buildFileData = BuildFileData( val addBuildSystemData by addBuildSystemData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.KOTLIN) }, PATH,
buildFileName = "build.gradle.kts" BuildSystemData(
type = BuildSystemType.GradleKotlinDsl,
buildFileData = BuildFileData(
createPrinter = { GradlePrinter(GradlePrinter.GradleDsl.KOTLIN) },
buildFileName = "build.gradle.kts"
)
) )
) )
) }
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
addBuildSystemData, addBuildSystemData,
@@ -3,10 +3,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.Versions import org.jetbrains.kotlin.tools.projectWizard.Versions
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.entity.fold
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.service.* import org.jetbrains.kotlin.tools.projectWizard.core.service.*
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildFileIR import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.BuildFileIR
@@ -21,128 +18,14 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.pomIR
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 org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.*
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import java.nio.file.Path import java.nio.file.Path
class KotlinPlugin(context: Context) : Plugin(context) { class KotlinPlugin(context: Context) : Plugin(context) {
override val path = "kotlin" override val path = PATH
val version by property(
// todo do not hardcode kind & repository
WizardKotlinVersion(Versions.KOTLIN, KotlinVersionKind.M, Repositories.KOTLIN_EAP_BINTRAY)
)
val initKotlinVersions by pipelineTask(GenerationPhase.PREPARE_GENERATION) {
title = KotlinNewProjectWizardBundle.message("plugin.kotlin.downloading.kotlin.versions")
withAction {
val version = service<KotlinVersionProviderService>().getKotlinVersion()
KotlinPlugin::version.update { version.asSuccess() }
}
}
val projectKind by enumSetting<ProjectKind>(
KotlinNewProjectWizardBundle.message("plugin.kotlin.setting.project.kind"),
GenerationPhase.FIRST_STEP
)
private fun List<Module>.findDuplicatesByName() =
groupingBy { it.name }.eachCount().filter { it.value > 1 }
val modules by listSetting(
KotlinNewProjectWizardBundle.message("plugin.kotlin.setting.modules"),
GenerationPhase.SECOND_STEP,
Module.parser
) {
validate { value ->
val allModules = value.withAllSubModules()
val duplicatedModules = allModules.findDuplicatesByName()
if (duplicatedModules.isEmpty()) ValidationResult.OK
else ValidationResult.ValidationError(
KotlinNewProjectWizardBundle.message(
"plugin.kotlin.setting.modules.error.duplicated.modules",
duplicatedModules.values.first(),
duplicatedModules.keys.first()
)
)
}
validate { value ->
value.withAllSubModules().filter { it.kind == ModuleKind.multiplatform }.map { module ->
val duplicatedModules = module.subModules.findDuplicatesByName()
if (duplicatedModules.isEmpty()) ValidationResult.OK
else ValidationResult.ValidationError(
KotlinNewProjectWizardBundle.message(
"plugin.kotlin.setting.modules.error.duplicated.targets",
duplicatedModules.values.first(),
duplicatedModules.keys.first()
)
)
}.fold()
}
validate(moduleDependenciesValidator)
}
val createModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin::createModules)
runAfter(StructurePlugin::createProjectDir)
withAction {
BuildSystemPlugin::buildFiles.update {
val modules = KotlinPlugin::modules.settingValue
val (buildFiles) = createBuildFiles(modules)
buildFiles.map { it.withIrs(RepositoryIR(DefaultRepository.MAVEN_CENTRAL)) }.asSuccess()
}
}
}
val createPluginRepositories by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin::createModules)
withAction {
val version = KotlinPlugin::version.propertyValue
if (version.kind.isStable) return@withAction UNIT_SUCCESS
val pluginRepository = version.repository
BuildSystemPlugin::pluginRepositoreis.addValues(pluginRepository) andThen
updateBuildFiles { buildFile ->
buildFile.withIrs(RepositoryIR(pluginRepository)).asSuccess()
}
}
}
val createSourcesetDirectories by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createModules)
withAction {
fun Path.createKotlinAndResourceDirectories(moduleConfigurator: ModuleConfigurator) = with(service<FileSystemWizardService>()) {
createDirectory(this@createKotlinAndResourceDirectories / moduleConfigurator.kotlinDirectoryName) andThen
createDirectory(this@createKotlinAndResourceDirectories / moduleConfigurator.resourcesDirectoryName)
}
forEachModule { moduleIR ->
moduleIR.sourcesets.mapSequenceIgnore { sourcesetIR ->
sourcesetIR.path.createKotlinAndResourceDirectories(moduleIR.originalModule.configurator)
}
}
}
}
private fun Writer.createBuildFiles(modules: List<Module>): TaskResult<List<BuildFileIR>> =
with(
ModulesToIRsConverter(
ModulesToIrConversionData(
modules,
projectPath,
StructurePlugin::name.settingValue,
KotlinPlugin::version.propertyValue,
buildSystemType,
pomIR()
)
)
) { createBuildFiles() }
companion object { companion object {
private const val PATH = "kotlin"
private val moduleDependenciesValidator = settingValidator<List<Module>> { modules -> private val moduleDependenciesValidator = settingValidator<List<Module>> { modules ->
val allModules = modules.withAllSubModules(includeSourcesets = true).toSet() val allModules = modules.withAllSubModules(includeSourcesets = true).toSet()
val allModulePaths = allModules.map(Module::path).toSet() val allModulePaths = allModules.map(Module::path).toSet()
@@ -162,6 +45,122 @@ class KotlinPlugin(context: Context) : Plugin(context) {
} }
}.fold() }.fold()
} }
val version by property(
PATH,
// todo do not hardcode kind & repository
WizardKotlinVersion(Versions.KOTLIN, KotlinVersionKind.M, Repositories.KOTLIN_EAP_BINTRAY)
)
val initKotlinVersions by pipelineTask(PATH, GenerationPhase.PREPARE_GENERATION) {
title = KotlinNewProjectWizardBundle.message("plugin.kotlin.downloading.kotlin.versions")
withAction {
val version = service<KotlinVersionProviderService>().getKotlinVersion()
KotlinPlugin.version.update { version.asSuccess() }
}
}
val projectKind by enumSetting<ProjectKind>(
KotlinNewProjectWizardBundle.message("plugin.kotlin.setting.project.kind"),
GenerationPhase.FIRST_STEP,
PATH
)
private fun List<Module>.findDuplicatesByName() =
groupingBy { it.name }.eachCount().filter { it.value > 1 }
val modules by listSetting(
KotlinNewProjectWizardBundle.message("plugin.kotlin.setting.modules"),
GenerationPhase.SECOND_STEP,
Module.parser,
PATH
) {
validate { value ->
val allModules = value.withAllSubModules()
val duplicatedModules = allModules.findDuplicatesByName()
if (duplicatedModules.isEmpty()) ValidationResult.OK
else ValidationResult.ValidationError(
KotlinNewProjectWizardBundle.message(
"plugin.kotlin.setting.modules.error.duplicated.modules",
duplicatedModules.values.first(),
duplicatedModules.keys.first()
)
)
}
validate { value ->
value.withAllSubModules().filter { it.kind == ModuleKind.multiplatform }.map { module ->
val duplicatedModules = module.subModules.findDuplicatesByName()
if (duplicatedModules.isEmpty()) ValidationResult.OK
else ValidationResult.ValidationError(
KotlinNewProjectWizardBundle.message(
"plugin.kotlin.setting.modules.error.duplicated.targets",
duplicatedModules.values.first(),
duplicatedModules.keys.first()
)
)
}.fold()
}
validate(moduleDependenciesValidator)
}
val createModules by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin.createModules)
runAfter(StructurePlugin.createProjectDir)
withAction {
BuildSystemPlugin.buildFiles.update {
val modules = modules.settingValue
val (buildFiles) = createBuildFiles(modules)
buildFiles.map { it.withIrs(RepositoryIR(DefaultRepository.MAVEN_CENTRAL)) }.asSuccess()
}
}
}
val createPluginRepositories by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin.createModules)
withAction {
val version = version.propertyValue
if (version.kind.isStable) return@withAction UNIT_SUCCESS
val pluginRepository = version.repository
BuildSystemPlugin.pluginRepositoreis.addValues(pluginRepository) andThen
updateBuildFiles { buildFile ->
buildFile.withIrs(RepositoryIR(pluginRepository)).asSuccess()
}
}
}
val createSourcesetDirectories by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin.createModules)
withAction {
fun Path.createKotlinAndResourceDirectories(moduleConfigurator: ModuleConfigurator) =
with(service<FileSystemWizardService>()) {
createDirectory(this@createKotlinAndResourceDirectories / moduleConfigurator.kotlinDirectoryName) andThen
createDirectory(this@createKotlinAndResourceDirectories / moduleConfigurator.resourcesDirectoryName)
}
forEachModule { moduleIR ->
moduleIR.sourcesets.mapSequenceIgnore { sourcesetIR ->
sourcesetIR.path.createKotlinAndResourceDirectories(moduleIR.originalModule.configurator)
}
}
}
}
private fun Writer.createBuildFiles(modules: List<Module>): TaskResult<List<BuildFileIR>> =
with(
ModulesToIRsConverter(
ModulesToIrConversionData(
modules,
projectPath,
StructurePlugin.name.settingValue,
version.propertyValue,
buildSystemType,
pomIR()
)
)
) { createBuildFiles() }
} }
override val settings: List<PluginSetting<*, *>> = override val settings: List<PluginSetting<*, *>> =
@@ -177,6 +176,8 @@ class KotlinPlugin(context: Context) : Plugin(context) {
createPluginRepositories, createPluginRepositories,
createSourcesetDirectories createSourcesetDirectories
) )
override val properties: List<Property<*>> =
listOf(version)
} }
@@ -253,9 +253,9 @@ class ModulesToIRsConverter(
compute { compute {
rootBuildFileIrs += createRootBuildFileIrs(data) rootBuildFileIrs += createRootBuildFileIrs(data)
runArbitraryTask(data, module, modulePath).ensure() runArbitraryTask(data, module, modulePath).ensure()
TemplatesPlugin::addFileTemplates.execute(createTemplates(data, module, modulePath)).ensure() TemplatesPlugin.addFileTemplates.execute(createTemplates(data, module, modulePath)).ensure()
if (this@with is GradleModuleConfigurator) { if (this@with is GradleModuleConfigurator) {
GradlePlugin::settingsGradleFileIRs.addValues(createSettingsGradleIRs(module)).ensure() GradlePlugin.settingsGradleFileIRs.addValues(createSettingsGradleIRs(module)).ensure()
} }
} }
} }
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates
import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle import org.jetbrains.kotlin.tools.projectWizard.KotlinNewProjectWizardBundle
import org.jetbrains.kotlin.tools.projectWizard.core.* 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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
@@ -11,28 +12,34 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.withAllSubModules
import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate
class ProjectTemplatesPlugin(context: Context) : Plugin(context) { class ProjectTemplatesPlugin(context: Context) : Plugin(context) {
override val path = "projectTemplates" override val path = PATH
val template by dropDownSetting<ProjectTemplate>( companion object {
KotlinNewProjectWizardBundle.message("plugin.templates.setting.template"), const val PATH = "projectTemplates"
GenerationPhase.INIT_TEMPLATE,
parser = valueParserM { _, _ -> val template by dropDownSetting<ProjectTemplate>(
Failure(ParseError("Project templates is not supported in yaml for now")) KotlinNewProjectWizardBundle.message("plugin.templates.setting.template"),
GenerationPhase.INIT_TEMPLATE,
parser = valueParserM { _, _ ->
Failure(ParseError("Project templates is not supported in yaml for now"))
},
PATH
) {
values = ProjectTemplate.ALL
isRequired = false
} }
) {
values = ProjectTemplate.ALL
isRequired = false
} }
override val settings: List<PluginSetting<*, *>> = listOf(template) override val settings: List<PluginSetting<*, *>> = listOf(template)
override val pipelineTasks: List<PipelineTask> = listOf() override val pipelineTasks: List<PipelineTask> = listOf()
override val properties: List<Property<*>> = listOf()
} }
fun SettingsWriter.applyProjectTemplate(projectTemplate: ProjectTemplate) { fun SettingsWriter.applyProjectTemplate(projectTemplate: ProjectTemplate) {
projectTemplate.setsValues.forEach { (setting, value) -> projectTemplate.setsValues.forEach { (setting, value) ->
setting.setValue(value) setting.setValue(value)
} }
KotlinPlugin::modules.settingValue.withAllSubModules(includeSourcesets = true).forEach { module -> KotlinPlugin.modules.settingValue.withAllSubModules(includeSourcesets = true).forEach { module ->
module.apply { initDefaultValuesForSettings() } module.apply { initDefaultValuesForSettings() }
} }
} }
@@ -1,12 +1,17 @@
package org.jetbrains.kotlin.tools.projectWizard.plugins.templates package org.jetbrains.kotlin.tools.projectWizard.plugins.templates
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask
import org.jetbrains.kotlin.tools.projectWizard.templates.ConsoleJvmApplicationTemplate import org.jetbrains.kotlin.tools.projectWizard.templates.ConsoleJvmApplicationTemplate
class ConsoleJvmApplicationTemplatePlugin(context: Context) : TemplatePlugin(context) { class ConsoleJvmApplicationTemplatePlugin(context: Context) : TemplatePlugin(context) {
override val path = "template.consoleJvmApplicationTemplate" override val path = PATH
val addTemplate by addTemplateTask( override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + listOf(addTemplate)
ConsoleJvmApplicationTemplate()
) companion object {
private const val PATH = "template.consoleJvmApplicationTemplate"
val addTemplate by addTemplateTask(PATH, ConsoleJvmApplicationTemplate())
}
} }
@@ -5,12 +5,16 @@ import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask
import org.jetbrains.kotlin.tools.projectWizard.templates.SimpleJsClientTemplate import org.jetbrains.kotlin.tools.projectWizard.templates.SimpleJsClientTemplate
class JsTemplatesPlugin(context: Context) : TemplatePlugin(context) { class JsTemplatesPlugin(context: Context) : TemplatePlugin(context) {
override val path = "template.jsTemplate" override val path = PATH
val addTemplate by addTemplateTask(SimpleJsClientTemplate())
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
addTemplate, addTemplate,
) )
companion object {
private const val PATH = "template.jsTemplates"
val addTemplate by addTemplateTask(PATH, SimpleJsClientTemplate())
}
} }
@@ -5,10 +5,16 @@ import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask
import org.jetbrains.kotlin.tools.projectWizard.templates.KtorServerTemplate import org.jetbrains.kotlin.tools.projectWizard.templates.KtorServerTemplate
class KtorTemplatesPlugin(context: Context) : TemplatePlugin(context) { class KtorTemplatesPlugin(context: Context) : TemplatePlugin(context) {
val addTemplate by addTemplateTask(KtorServerTemplate()) override val path = PATH
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
addTemplate, addTemplate,
) )
companion object {
private const val PATH = "template.ktorTemplates"
val addTemplate by addTemplateTask(PATH, KtorServerTemplate())
}
} }
@@ -10,10 +10,16 @@ import org.jetbrains.kotlin.tools.projectWizard.core.entity.PipelineTask
import org.jetbrains.kotlin.tools.projectWizard.templates.NativeConsoleApplicationTemplate import org.jetbrains.kotlin.tools.projectWizard.templates.NativeConsoleApplicationTemplate
class NativeConsoleApplicationTemplatePlugin(context: Context) : TemplatePlugin(context) { class NativeConsoleApplicationTemplatePlugin(context: Context) : TemplatePlugin(context) {
val addTemplate by addTemplateTask(NativeConsoleApplicationTemplate()) override val path = PATH
override val pipelineTasks: List<PipelineTask> = super.pipelineTasks + override val pipelineTasks: List<PipelineTask> = super.pipelineTasks +
listOf( listOf(
addTemplate, addTemplate,
) )
companion object {
private const val PATH = "template.nativeConsoleApplicationTemplate"
val addTemplate by addTemplateTask(PATH, NativeConsoleApplicationTemplate())
}
} }
@@ -3,19 +3,25 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.templates
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.Plugin import org.jetbrains.kotlin.tools.projectWizard.core.Plugin
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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.templates.Template import org.jetbrains.kotlin.tools.projectWizard.templates.Template
abstract class TemplatePlugin(context: Context) : Plugin(context) { abstract class TemplatePlugin(context: Context) : Plugin(context) {
override val path = "template" override val path = PATH
fun addTemplateTask(template: Template) = pipelineTask(GenerationPhase.PREPARE) {
withAction {
TemplatesPlugin::addTemplate.execute(template)
}
}
override val settings: List<PluginSetting<*, *>> = emptyList() override val settings: List<PluginSetting<*, *>> = emptyList()
override val pipelineTasks: List<PipelineTask> = emptyList() override val pipelineTasks: List<PipelineTask> = emptyList()
override val properties: List<Property<*>> = emptyList()
companion object {
const val PATH = "template"
fun addTemplateTask(prefix: String, template: Template) = pipelineTask(prefix, GenerationPhase.PREPARE) {
withAction {
TemplatesPlugin.addTemplate.execute(template)
}
}
}
} }
@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.tools.projectWizard.plugins.templates
import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.Defaults.SRC_DIR import org.jetbrains.kotlin.tools.projectWizard.core.Defaults.SRC_DIR
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.Property
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.PluginSetting
import org.jetbrains.kotlin.tools.projectWizard.core.service.TemplateEngineService import org.jetbrains.kotlin.tools.projectWizard.core.service.TemplateEngineService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.*
@@ -23,144 +24,149 @@ import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.settingValue
import java.nio.file.Path import java.nio.file.Path
class TemplatesPlugin(context: Context) : Plugin(context) { class TemplatesPlugin(context: Context) : Plugin(context) {
override val path = "templates" override val path = PATH
val templates by property<Map<String, Template>>( companion object {
emptyMap() private const val PATH = "templates"
)
val addTemplate by task1<Template, Unit> { val templates by property<Map<String, Template>>(
withAction { template -> PATH,
TemplatesPlugin::templates.update { success(it + (template.id to template)) } emptyMap()
} )
}
val fileTemplatesToRender by property<List<FileTemplate>>(emptyList()) val addTemplate by task1<Template, Unit>(PATH) {
withAction { template ->
val addFileTemplate by task1<FileTemplate, Unit> { templates.update { success(it + (template.id to template)) }
withAction { template ->
TemplatesPlugin::fileTemplatesToRender.update { success(it + template) }
}
}
val addFileTemplates by task1<List<FileTemplate>, Unit> {
withAction { templates ->
TemplatesPlugin::fileTemplatesToRender.addValues(templates)
}
}
val renderFileTemplates by pipelineTask(GenerationPhase.PROJECT_GENERATION) {
runAfter(KotlinPlugin::createModules)
withAction {
val templateEngine = service<TemplateEngineService>()
TemplatesPlugin::fileTemplatesToRender.propertyValue.mapSequenceIgnore { template ->
with(templateEngine) { writeTemplate(template) }
} }
} }
}
val addTemplatesToModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val fileTemplatesToRender by property<List<FileTemplate>>(PATH, emptyList())
runBefore(BuildSystemPlugin::createModules)
runAfter(KotlinPlugin::createModules)
withAction { val addFileTemplate by task1<FileTemplate, Unit>(PATH) {
updateBuildFiles { buildFile -> withAction { template ->
buildFile.modules.modules.mapSequence { module -> fileTemplatesToRender.update { success(it + template) }
applyTemplateToModule( }
module.template, }
module
).map { result -> module.withIrs(result.librariesToAdd) to result } val addFileTemplates by task1<List<FileTemplate>, Unit>(PATH) {
}.map { withAction { templates ->
val (moduleIrs, results) = it.unzip() fileTemplatesToRender.addValues(templates)
val foldedResults = results.fold() }
buildFile.copy( }
modules = buildFile.modules.withModules(moduleIrs)
).withIrs(foldedResults.irsToAddToBuildFile).let { buildFile -> val renderFileTemplates by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
when (val structure = buildFile.modules) { runAfter(KotlinPlugin.createModules)
is MultiplatformModulesStructureIR -> withAction {
buildFile.copy(modules = structure.updateTargets(foldedResults.updateTarget)) val templateEngine = service<TemplateEngineService>()
else -> buildFile fileTemplatesToRender.propertyValue.mapSequenceIgnore { template ->
with(templateEngine) { writeTemplate(template) }
}
}
}
val addTemplatesToModules by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin.createModules)
runAfter(KotlinPlugin.createModules)
withAction {
updateBuildFiles { buildFile ->
buildFile.modules.modules.mapSequence { module ->
applyTemplateToModule(
module.template,
module
).map { result -> module.withIrs(result.librariesToAdd) to result }
}.map {
val (moduleIrs, results) = it.unzip()
val foldedResults = results.fold()
buildFile.copy(
modules = buildFile.modules.withModules(moduleIrs)
).withIrs(foldedResults.irsToAddToBuildFile).let { buildFile ->
when (val structure = buildFile.modules) {
is MultiplatformModulesStructureIR ->
buildFile.copy(modules = structure.updateTargets(foldedResults.updateTarget))
else -> buildFile
}
} }
} }
} }
} }
} }
}
val postApplyTemplatesToModules by pipelineTask(GenerationPhase.PROJECT_GENERATION) { val postApplyTemplatesToModules by pipelineTask(PATH, GenerationPhase.PROJECT_GENERATION) {
runBefore(BuildSystemPlugin::createModules) runBefore(BuildSystemPlugin.createModules)
runAfter(KotlinPlugin::createModules) runAfter(KotlinPlugin.createModules)
runAfter(TemplatesPlugin::addTemplatesToModules) runAfter(TemplatesPlugin.addTemplatesToModules)
withAction { withAction {
updateBuildFiles { buildFile -> updateBuildFiles { buildFile ->
val modules = buildFile.modules.modules val modules = buildFile.modules.modules
val applicationState = modules.mapNotNull { module -> val applicationState = modules.mapNotNull { module ->
module.template?.createInterceptors(module) module.template?.createInterceptors(module)
}.flatten() }.flatten()
.applyAll(TemplateInterceptionApplicationState(buildFile, emptyMap())) .applyAll(TemplateInterceptionApplicationState(buildFile, emptyMap()))
val templateEngine = service<TemplateEngineService>() val templateEngine = service<TemplateEngineService>()
val templatesApplicationResult = modules.map { module -> val templatesApplicationResult = modules.map { module ->
val settings = applicationState.moduleToSettings[module.originalModule.identificator].orEmpty() val settings = applicationState.moduleToSettings[module.originalModule.identificator].orEmpty()
applyFileTemplatesFromSourceset(module, templateEngine, settings) applyFileTemplatesFromSourceset(module, templateEngine, settings)
}.sequenceIgnore() }.sequenceIgnore()
templatesApplicationResult andThen applicationState.buildFileIR.asSuccess() templatesApplicationResult andThen applicationState.buildFileIR.asSuccess()
}
}
}
private fun Writer.applyFileTemplatesFromSourceset(
module: ModuleIR,
templateEngine: TemplateEngineService,
interceptionPointSettings: Map<InterceptionPoint<Any>, Any>
): TaskResult<Unit> {
val template = module.template ?: return UNIT_SUCCESS
val settings = with(template) { settingsAsMap(module.originalModule) }
val allSettings: Map<String, Any> = mutableMapOf<String, Any>().apply {
putAll(settings)
putAll(interceptionPointSettings.mapKeys { it.key.name })
putAll(defaultSettings(module))
}
return with(template) { getFileTemplates(module) }.mapNotNull { (fileTemplateDescriptor, filePath) ->
val path = generatePathForFileTemplate(module, filePath) ?: return@mapNotNull null
val fileTemplate = FileTemplate(
fileTemplateDescriptor,
module.path / path,
allSettings
)
with(templateEngine) { writeTemplate(fileTemplate) }
}.sequenceIgnore()
}
private fun Reader.defaultSettings(moduleIR: ModuleIR) = mapOf(
"projectName" to projectName,
"moduleName" to moduleIR.name
)
private fun Reader.generatePathForFileTemplate(module: ModuleIR, filePath: FilePath): Path? {
if (filePath is SrcFilePath
&& filePath.sourcesetType == SourcesetType.test
&& settingValue(module.originalModule, ModuleConfiguratorWithTests.testFramework)?.isPresent != true
) return null
val moduleConfigurator = module.originalModule.configurator
return when (module) {
is SingleplatformModuleIR -> {
when (filePath) {
is SrcFilePath -> SRC_DIR / filePath.sourcesetType.toString() / moduleConfigurator.kotlinDirectoryName
is ResourcesFilePath -> SRC_DIR / filePath.sourcesetType.toString() / moduleConfigurator.resourcesDirectoryName
} }
} }
}
is MultiplatformModuleIR -> { private fun Writer.applyFileTemplatesFromSourceset(
val directory = when (filePath) { module: ModuleIR,
is SrcFilePath -> moduleConfigurator.kotlinDirectoryName templateEngine: TemplateEngineService,
is ResourcesFilePath -> moduleConfigurator.resourcesDirectoryName interceptionPointSettings: Map<InterceptionPoint<Any>, Any>
): TaskResult<Unit> {
val template = module.template ?: return UNIT_SUCCESS
val settings = with(template) { settingsAsMap(module.originalModule) }
val allSettings: Map<String, Any> = mutableMapOf<String, Any>().apply {
putAll(settings)
putAll(interceptionPointSettings.mapKeys { it.key.name })
putAll(defaultSettings(module))
}
return with(template) { getFileTemplates(module) }.mapNotNull { (fileTemplateDescriptor, filePath) ->
val path = generatePathForFileTemplate(module, filePath) ?: return@mapNotNull null
val fileTemplate = FileTemplate(
fileTemplateDescriptor,
module.path / path,
allSettings
)
with(templateEngine) { writeTemplate(fileTemplate) }
}.sequenceIgnore()
}
private fun Reader.defaultSettings(moduleIR: ModuleIR) = mapOf(
"projectName" to projectName,
"moduleName" to moduleIR.name
)
private fun Reader.generatePathForFileTemplate(module: ModuleIR, filePath: FilePath): Path? {
if (filePath is SrcFilePath
&& filePath.sourcesetType == SourcesetType.test
&& settingValue(module.originalModule, ModuleConfiguratorWithTests.testFramework)?.isPresent != true
) return null
val moduleConfigurator = module.originalModule.configurator
return when (module) {
is SingleplatformModuleIR -> {
when (filePath) {
is SrcFilePath -> SRC_DIR / filePath.sourcesetType.toString() / moduleConfigurator.kotlinDirectoryName
is ResourcesFilePath -> SRC_DIR / filePath.sourcesetType.toString() / moduleConfigurator.resourcesDirectoryName
}
}
is MultiplatformModuleIR -> {
val directory = when (filePath) {
is SrcFilePath -> moduleConfigurator.kotlinDirectoryName
is ResourcesFilePath -> moduleConfigurator.resourcesDirectoryName
}
SRC_DIR / "${module.name}${filePath.sourcesetType.name.capitalize()}" / directory
} }
SRC_DIR / "${module.name}${filePath.sourcesetType.name.capitalize()}" / directory
} }
} }
} }
@@ -172,4 +178,9 @@ class TemplatesPlugin(context: Context) : Plugin(context) {
addTemplatesToModules, addTemplatesToModules,
postApplyTemplatesToModules postApplyTemplatesToModules
) )
override val properties: List<Property<*>> =
listOf(
templates,
fileTemplatesToRender
)
} }
@@ -27,7 +27,7 @@ sealed class ProjectTemplate : DisplayableSettingItem {
abstract val id: String abstract val id: String
private val setsDefaultValues: List<SettingWithValue<*, *>> private val setsDefaultValues: List<SettingWithValue<*, *>>
get() = listOf(KotlinPlugin::projectKind.reference withValue projectKind) get() = listOf(KotlinPlugin.projectKind.reference withValue projectKind)
protected open val setsPluginSettings: List<SettingWithValue<*, *>> = emptyList() protected open val setsPluginSettings: List<SettingWithValue<*, *>> = emptyList()
protected open val setsModules: List<Module> = emptyList() protected open val setsModules: List<Module> = emptyList()
@@ -36,7 +36,7 @@ sealed class ProjectTemplate : DisplayableSettingItem {
val setsValues: List<SettingWithValue<*, *>> val setsValues: List<SettingWithValue<*, *>>
get() = buildList { get() = buildList {
setsModules.takeIf { it.isNotEmpty() }?.let { modules -> setsModules.takeIf { it.isNotEmpty() }?.let { modules ->
+(KotlinPlugin::modules withValue modules) +(KotlinPlugin.modules.reference withValue modules)
} }
+setsDefaultValues +setsDefaultValues
+setsPluginSettings +setsPluginSettings
@@ -123,10 +123,6 @@ data class SettingWithValue<V : Any, T : SettingType<V>>(val setting: SettingRef
infix fun <V : Any, T : SettingType<V>> PluginSettingReference<V, T>.withValue(value: V): SettingWithValue<V, T> = infix fun <V : Any, T : SettingType<V>> PluginSettingReference<V, T>.withValue(value: V): SettingWithValue<V, T> =
SettingWithValue(this, value) SettingWithValue(this, value)
inline infix fun <V : Any, reified T : SettingType<V>> PluginSettingPropertyReference<V, T>.withValue(
value: V
): SettingWithValue<V, T> = reference.withValue(value)
private fun createDefaultSourcesets() = private fun createDefaultSourcesets() =
SourcesetType.values().map { sourcesetType -> SourcesetType.values().map { sourcesetType ->
Sourceset( Sourceset(
@@ -150,7 +146,7 @@ object BackendApplicationProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
SingleplatformModule("mainModule", createDefaultSourcesets()) SingleplatformModule("mainModule", createDefaultSourcesets())
) )
) )
@@ -167,7 +163,7 @@ object MultiplatformApplicationProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
MultiplatformModule("mainModule", listOf(ModuleType.common.createDefaultTarget())) MultiplatformModule("mainModule", listOf(ModuleType.common.createDefaultTarget()))
) )
) )
@@ -184,7 +180,7 @@ object ConsoleApplicationProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
SingleplatformModule( SingleplatformModule(
"consoleApp", "consoleApp",
createDefaultSourcesets() createDefaultSourcesets()
@@ -206,7 +202,7 @@ object MultiplatformLibraryProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
MultiplatformModule( MultiplatformModule(
"library", "library",
listOf( listOf(
@@ -231,7 +227,7 @@ object FullStackWebApplicationProjectTemplate : ProjectTemplate() {
override val suggestedProjectName: String = "myFullStackApplication" override val suggestedProjectName: String = "myFullStackApplication"
override val projectKind: ProjectKind = ProjectKind.Multiplatform override val projectKind: ProjectKind = ProjectKind.Multiplatform
override val setsPluginSettings: List<SettingWithValue<*, *>> = listOf( override val setsPluginSettings: List<SettingWithValue<*, *>> = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
MultiplatformModule( MultiplatformModule(
"application", "application",
listOf( listOf(
@@ -261,7 +257,7 @@ object NativeApplicationProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
Module( Module(
"app", "app",
MppModuleConfigurator, MppModuleConfigurator,
@@ -288,7 +284,7 @@ object FrontendApplicationProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
Module( Module(
"frontend", "frontend",
BrowserJsSinglePlatformModuleConfigurator, BrowserJsSinglePlatformModuleConfigurator,
@@ -365,7 +361,7 @@ object MultiplatformMobileLibraryProjectTemplate : ProjectTemplate() {
override val setsPluginSettings: List<SettingWithValue<*, *>> override val setsPluginSettings: List<SettingWithValue<*, *>>
get() = listOf( get() = listOf(
KotlinPlugin::modules withValue listOf( KotlinPlugin.modules.reference withValue listOf(
MultiplatformModule( MultiplatformModule(
"library", "library",
listOf( listOf(
@@ -87,7 +87,7 @@ sealed class ModuleDependencyType(
IOSSinglePlatformModuleConfigurator.dependentModule.reference IOSSinglePlatformModuleConfigurator.dependentModule.reference
.setValue(IOSSinglePlatformModuleConfigurator.DependentModuleReference(to)) .setValue(IOSSinglePlatformModuleConfigurator.DependentModuleReference(to))
val dummyFilePath = Defaults.SRC_DIR / "${to.iosTargetSafe()!!.name}Main" / to.configurator.kotlinDirectoryName / "dummyFile.kt" val dummyFilePath = Defaults.SRC_DIR / "${to.iosTargetSafe()!!.name}Main" / to.configurator.kotlinDirectoryName / "dummyFile.kt"
TemplatesPlugin::addFileTemplate.execute( TemplatesPlugin.addFileTemplate.execute(
FileTemplate( FileTemplate(
FileTemplateDescriptor("ios/dummyFile.kt", dummyFilePath), FileTemplateDescriptor("ios/dummyFile.kt", dummyFilePath),
projectPath / toModulePath projectPath / toModulePath
@@ -85,7 +85,7 @@ enum class SourcesetType : DisplayableSettingItem {
fun Writer.updateBuildFiles(action: (BuildFileIR) -> TaskResult<BuildFileIR>): TaskResult<Unit> = fun Writer.updateBuildFiles(action: (BuildFileIR) -> TaskResult<BuildFileIR>): TaskResult<Unit> =
BuildSystemPlugin::buildFiles.update { buildFiles -> BuildSystemPlugin.buildFiles.update { buildFiles ->
buildFiles.mapSequence(action) buildFiles.mapSequence(action)
} }
@@ -41,13 +41,13 @@ class KtorServerTemplate : Template() {
override fun Writer.getRequiredLibraries(module: ModuleIR): List<DependencyIR> = override fun Writer.getRequiredLibraries(module: ModuleIR): List<DependencyIR> =
withSettingsOf(module.originalModule) { withSettingsOf(module.originalModule) {
val kotlinVersion = KotlinPlugin::version.propertyValue.version val kotlinVersion = KotlinPlugin.version.propertyValue.version
buildList { buildList {
+ktorArtifactDependency(serverEngine.reference.settingValue.dependencyName, kotlinVersion) +ktorArtifactDependency(serverEngine.reference.settingValue.dependencyName, kotlinVersion)
+ktorArtifactDependency("ktor-html-builder", kotlinVersion) +ktorArtifactDependency("ktor-html-builder", kotlinVersion)
+ArtifactBasedLibraryDependencyIR( +ArtifactBasedLibraryDependencyIR(
MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-jvm"), MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-jvm"),
Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin::version.propertyValue.version), Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin.version.propertyValue.version),
DependencyType.MAIN DependencyType.MAIN
) )
} }
@@ -81,11 +81,11 @@ class SimpleJsClientTemplate : Template() {
buildList { buildList {
+ArtifactBasedLibraryDependencyIR( +ArtifactBasedLibraryDependencyIR(
MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-js"), MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-js"),
Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin::version.propertyValue.version), Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin.version.propertyValue.version),
DependencyType.MAIN DependencyType.MAIN
) )
val kotlinVersion = KotlinPlugin::version.propertyValue val kotlinVersion = KotlinPlugin.version.propertyValue
if (renderEngine.reference.settingValue != RenderEngine.KOTLINX_HTML) { if (renderEngine.reference.settingValue != RenderEngine.KOTLINX_HTML) {
+Dependencies.KOTLIN_REACT(kotlinVersion.version) +Dependencies.KOTLIN_REACT(kotlinVersion.version)
+Dependencies.KOTLIN_REACT_DOM(kotlinVersion.version) +Dependencies.KOTLIN_REACT_DOM(kotlinVersion.version)
@@ -66,6 +66,7 @@ fun <V : Any, T : SettingType<V>> Reader.settingValue(module: Module, setting: T
abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSettingItem { abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSettingItem {
final override fun <V : Any, T : SettingType<V>> settingDelegate( final override fun <V : Any, T : SettingType<V>> settingDelegate(
prefix: String,
create: (path: String) -> SettingBuilder<V, T> create: (path: String) -> SettingBuilder<V, T>
): ReadOnlyProperty<Any, TemplateSetting<V, T>> = cached { name -> ): ReadOnlyProperty<Any, TemplateSetting<V, T>> = cached { name ->
TemplateSetting(create(name).buildInternal()) TemplateSetting(create(name).buildInternal())
@@ -126,7 +127,7 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
else -> idFunction() else -> idFunction()
} }
RunConfigurationsPlugin::configurations.addValues(createRunConfigurations(module)) RunConfigurationsPlugin.configurations.addValues(createRunConfigurations(module))
val result = TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile, targetsUpdater) val result = TemplateApplicationResult(librariesToAdd, irsToAddToBuildFile, targetsUpdater)
return result.asSuccess() return result.asSuccess()
@@ -144,7 +145,7 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
private fun Reader.createDefaultSettings() = mapOf( private fun Reader.createDefaultSettings() = mapOf(
"projectName" to StructurePlugin::name.settingValue.capitalize() "projectName" to StructurePlugin.name.settingValue.capitalize()
) )
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
@@ -157,12 +158,14 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: DropDownSettingType.Builder<V>.() -> Unit init: DropDownSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<V, DropDownSettingType<V>>> = ): ReadOnlyProperty<Any, TemplateSetting<V, DropDownSettingType<V>>> =
super.dropDownSetting( super.dropDownSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<V, DropDownSettingType<V>>> ) as ReadOnlyProperty<Any, TemplateSetting<V, DropDownSettingType<V>>>
@@ -170,11 +173,13 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
final override fun stringSetting( final override fun stringSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: StringSettingType.Builder.() -> Unit init: StringSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<String, StringSettingType>> = ): ReadOnlyProperty<Any, TemplateSetting<String, StringSettingType>> =
super.stringSetting( super.stringSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<String, StringSettingType>> ) as ReadOnlyProperty<Any, TemplateSetting<String, StringSettingType>>
@@ -182,11 +187,13 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
final override fun booleanSetting( final override fun booleanSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: BooleanSettingType.Builder.() -> Unit init: BooleanSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<Boolean, BooleanSettingType>> = ): ReadOnlyProperty<Any, TemplateSetting<Boolean, BooleanSettingType>> =
super.booleanSetting( super.booleanSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<Boolean, BooleanSettingType>> ) as ReadOnlyProperty<Any, TemplateSetting<Boolean, BooleanSettingType>>
@@ -195,12 +202,14 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: ValueSettingType.Builder<V>.() -> Unit init: ValueSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<V, ValueSettingType<V>>> = ): ReadOnlyProperty<Any, TemplateSetting<V, ValueSettingType<V>>> =
super.valueSetting( super.valueSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<V, ValueSettingType<V>>> ) as ReadOnlyProperty<Any, TemplateSetting<V, ValueSettingType<V>>>
@@ -208,11 +217,13 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
final override fun versionSetting( final override fun versionSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: VersionSettingType.Builder.() -> Unit init: VersionSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<Version, VersionSettingType>> = ): ReadOnlyProperty<Any, TemplateSetting<Version, VersionSettingType>> =
super.versionSetting( super.versionSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<Version, VersionSettingType>> ) as ReadOnlyProperty<Any, TemplateSetting<Version, VersionSettingType>>
@@ -221,12 +232,14 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
parser: Parser<V>, parser: Parser<V>,
prefix: String,
init: ListSettingType.Builder<V>.() -> Unit init: ListSettingType.Builder<V>.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<List<V>, ListSettingType<V>>> = ): ReadOnlyProperty<Any, TemplateSetting<List<V>, ListSettingType<V>>> =
super.listSetting( super.listSetting(
title, title,
neededAtPhase, neededAtPhase,
parser, parser,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<List<V>, ListSettingType<V>>> ) as ReadOnlyProperty<Any, TemplateSetting<List<V>, ListSettingType<V>>>
@@ -235,11 +248,13 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
final override fun pathSetting( final override fun pathSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String,
init: PathSettingType.Builder.() -> Unit init: PathSettingType.Builder.() -> Unit
): ReadOnlyProperty<Any, TemplateSetting<Path, PathSettingType>> = ): ReadOnlyProperty<Any, TemplateSetting<Path, PathSettingType>> =
super.pathSetting( super.pathSetting(
title, title,
neededAtPhase, neededAtPhase,
prefix,
init init
) as ReadOnlyProperty<Any, TemplateSetting<Path, PathSettingType>> ) as ReadOnlyProperty<Any, TemplateSetting<Path, PathSettingType>>
@@ -247,9 +262,10 @@ abstract class Template : SettingsOwner, EntitiesOwnerDescriptor, DisplayableSet
inline fun <reified E> enumSetting( inline fun <reified E> enumSetting(
title: String, title: String,
neededAtPhase: GenerationPhase, neededAtPhase: GenerationPhase,
prefix: String = "",
crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {} crossinline init: DropDownSettingType.Builder<E>.() -> Unit = {}
): ReadOnlyProperty<Any, TemplateSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem = ): ReadOnlyProperty<Any, TemplateSetting<E, DropDownSettingType<E>>> where E : Enum<E>, E : DisplayableSettingItem =
enumSettingImpl(title, neededAtPhase, init) as ReadOnlyProperty<Any, TemplateSetting<E, DropDownSettingType<E>>> enumSettingImpl(title, neededAtPhase, prefix, init) as ReadOnlyProperty<Any, TemplateSetting<E, DropDownSettingType<E>>>
companion object { companion object {
fun parser(templateId: Identificator): Parser<Template> = mapParser { map, path -> fun parser(templateId: Identificator): Parser<Template> = mapParser { map, path ->
@@ -23,7 +23,7 @@ abstract class Wizard(createPlugins: PluginsCreator, servicesManager: ServicesMa
private fun initNonPluginDefaultValues() { private fun initNonPluginDefaultValues() {
context.writeSettings { context.writeSettings {
KotlinPlugin::modules.reference.notRequiredSettingValue KotlinPlugin.modules.notRequiredSettingValue
?.withAllSubModules(includeSourcesets = true) ?.withAllSubModules(includeSourcesets = true)
?.forEach { module -> ?.forEach { module ->
with(module) { initDefaultValuesForSettings() } with(module) { initDefaultValuesForSettings() }
@@ -41,7 +41,7 @@ abstract class Wizard(createPlugins: PluginsCreator, servicesManager: ServicesMa
fun validate(phases: Set<GenerationPhase>): ValidationResult = context.read { fun validate(phases: Set<GenerationPhase>): ValidationResult = context.read {
pluginSettings.map { setting -> pluginSettings.map { setting ->
val value = setting.reference.notRequiredSettingValue ?: return@map ValidationResult.OK val value = setting.notRequiredSettingValue ?: return@map ValidationResult.OK
if (setting.validateOnProjectCreation && setting.neededAtPhase in phases && setting.isActive(this)) if (setting.validateOnProjectCreation && setting.neededAtPhase in phases && setting.isActive(this))
(setting.validator as SettingValidator<Any>).validate(this, value) (setting.validator as SettingValidator<Any>).validate(this, value)
else ValidationResult.OK else ValidationResult.OK
@@ -56,7 +56,7 @@ abstract class Wizard(createPlugins: PluginsCreator, servicesManager: ServicesMa
val serializer = setting.type.serializer as? SettingSerializer.Serializer<Any> ?: continue val serializer = setting.type.serializer as? SettingSerializer.Serializer<Any> ?: continue
service<SettingSavingWizardService>().saveSettingValue( service<SettingSavingWizardService>().saveSettingValue(
setting.path, setting.path,
serializer.toString(setting.reference.settingValue) serializer.toString(setting.settingValue)
) )
} }
} }