Wizard: automatically determine Kotlin version based on Kotlin plugin version

For snapshot plugin just take the latest eap or stable version
This commit is contained in:
Ilya Kirillov
2020-01-19 11:32:13 +03:00
parent 40d6fe7a00
commit b9226ce54f
28 changed files with 351 additions and 79 deletions
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.wizard.service
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.asNullable
import org.jetbrains.kotlin.tools.projectWizard.core.compute
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.KotlinVersionProviderService
import org.jetbrains.kotlin.tools.projectWizard.core.service.KotlinVersionProviderServiceImpl
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.URL
import java.util.stream.Collectors
class IdeaKotlinVersionProviderService : KotlinVersionProviderService, IdeaWizardService {
override fun getKotlinVersion(): Version {
if (KotlinPluginUtil.isSnapshotVersion()) {
return VersionsDownloader.getLatestEapOrStableKotlinVersion() ?: KotlinVersionProviderServiceImpl.DEFAULT
}
return KotlinPluginUtil.getPluginVersion().let { Version.fromString(it) }
}
}
private object VersionsDownloader {
fun getLatestEapOrStableKotlinVersion(): Version? {
val latestEap = EapVersionDownloader.getLatestEapVersion()
val latestStable = getLatestStableVersion()
if (latestEap == null) return latestStable
if (latestStable == null) return latestEap
return if (latestEap > latestStable) latestEap else latestStable
}
private fun getLatestStableVersion() = safe {
ConfigureDialogWithModulesAndVersion.loadVersions("1.0.0")
}.asNullable?.firstOrNull()?.let { Version.fromString(it) }
}
private object EapVersionDownloader {
fun getLatestEapVersion() = downloadVersions(EAP_URL).firstOrNull()
private fun downloadPage(url: String): TaskResult<String> = safe {
BufferedReader(InputStreamReader(URL(url).openStream())).lines().collect(Collectors.joining("\n"))
}
@Suppress("SameParameterValue")
private fun downloadVersions(url: String): List<Version> = compute {
val (text) = downloadPage(url)
versionRegexp.findAll(text)
.map { it.groupValues[1].removeSuffix("/") }
.filter { it.isNotEmpty() && it[0].isDigit() }
.map { Version.fromString(it) }
.toList()
.asReversed()
}.asNullable.orEmpty()
private val EAP_URL = "https://dl.bintray.com/kotlin/kotlin-eap/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/"
private val versionRegexp = """href="([^"\\]+)"""".toRegex()
}
@@ -15,7 +15,8 @@ interface IdeaWizardService : WizardService
object IdeaServices {
val PROJECT_INDEPENDENT: List<IdeaWizardService> = listOf(
IdeaFileSystemWizardService(),
IdeaBuildSystemAvailabilityWizardService()
IdeaBuildSystemAvailabilityWizardService(),
IdeaKotlinVersionProviderService()
)
fun createScopeDependent(project: Project, model: ModifiableModuleModel) = listOf(
@@ -42,5 +42,9 @@ abstract class DynamicComponent(private val valuesReadingContext: ValuesReadingC
if (isInitialized) onValueUpdated(reference)
}
}
protected fun <T> read(reader: ValuesReadingContext.() -> T): T =
reader(valuesReadingContext)
open fun onValueUpdated(reference: SettingReference<*, *>?) {}
}
@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.awt.event.ItemEvent
import javax.swing.DefaultComboBoxModel
import javax.swing.Icon
import javax.swing.JComboBox
import javax.swing.JList
class DropDownComponent<T : DisplayableSettingItem>(
private val valuesReadingContext: ValuesReadingContext,
initialValues: List<T> = emptyList(),
labelText: String? = null,
filter: (T) -> Boolean = { true },
private val filter: (T) -> Boolean = { true },
private val validator: SettingValidator<T> = settingValidator { ValidationResult.OK },
private val iconProvider: (T) -> Icon? = { null },
onValueUpdate: (T) -> Unit = {}
@@ -65,11 +67,16 @@ class DropDownComponent<T : DisplayableSettingItem>(
}
}
fun setValues(newValues: List<T>) {
@Suppress("UNCHECKED_CAST")
uiComponent.model = DefaultComboBoxModel(newValues.filter(filter).toTypedArray<DisplayableSettingItem>() as Array<T>)
}
override fun updateUiValue(newValue: T) = safeUpdateUi {
uiComponent.selectedItem = newValue
}
@Suppress("UNCHECKED_CAST")
override fun getUiValue(): T = uiComponent.selectedItem as T
override fun getUiValue(): T? = uiComponent.selectedItem as? T
}
@@ -28,7 +28,7 @@ abstract class UIComponent<V : Any>(
protected abstract val uiComponent: JComponent
abstract fun updateUiValue(newValue: V)
abstract fun getUiValue(): V
abstract fun getUiValue(): V?
private var allowEventFiring = true
@@ -41,7 +41,7 @@ abstract class UIComponent<V : Any>(
override fun onInit() {
super.onInit()
validate(getUiValue())
getUiValue()?.let(::validate)
}
final override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) {
@@ -65,5 +65,5 @@ abstract class UIComponent<V : Any>(
}
}
fun <V: Any> UIComponent<V>.valueForSetting(setting: Setting<V, SettingType<V>>): V =
setting.defaultValue ?: getUiValue()
fun <V : Any> UIComponent<V>.valueForSetting(setting: Setting<V, SettingType<V>>): V? =
setting.defaultValue ?: getUiValue()
@@ -20,7 +20,7 @@ import java.awt.BorderLayout
class BuildSystemTypeSettingComponent(
private val valuesReadingContext: ValuesReadingContext
valuesReadingContext: ValuesReadingContext
) : UIComponentDelegatingSettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
BuildSystemPlugin::type.reference,
valuesReadingContext
@@ -1,6 +1,5 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
import org.jetbrains.kotlin.tools.projectWizard.core.TaskRunningContext
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
@@ -28,7 +27,6 @@ class BuildSystemSubStep(valuesReadingContext: ValuesReadingContext) :
private val buildSystemSetting = BuildSystemTypeSettingComponent(valuesReadingContext).asSubComponent()
override fun buildContent(): JComponent = panel {
bordered(needBottomEmptyBorder = false)
add(buildSystemSetting.component, BorderLayout.CENTER)
}
}
@@ -91,7 +91,7 @@ class VersionSettingComponent(
class DropdownSettingComponent(
reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
private val valuesReadingContext: ValuesReadingContext
valuesReadingContext: ValuesReadingContext
) : UIComponentDelegatingSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>(
reference,
valuesReadingContext
@@ -7,7 +7,7 @@ import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
abstract class SettingComponent<V : Any, T: SettingType<V>>(
val reference: SettingReference<V, T>,
private val valuesReadingContext: ValuesReadingContext
val valuesReadingContext: ValuesReadingContext
) : DynamicComponent(valuesReadingContext), Displayable {
var value: V?
get() = reference.value
@@ -24,9 +24,7 @@ abstract class UIComponentDelegatingSettingComponent<V : Any, T : SettingType<V>
override fun onInit() {
super.onInit()
if (value == null) {
if (value == null) {
value = uiComponent.valueForSetting(setting)
}
uiComponent.valueForSetting(setting)?.let { value = it }
}
value?.let(uiComponent::updateUiValue)
}