From 6fbb370eae2830369bffe15889edfe1145b59de3 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 18 Aug 2017 15:36:22 +0200 Subject: [PATCH] Move coroutine state update logic to KotlinProjectConfigurator --- idea/idea-gradle/idea-gradle.iml | 1 + .../KotlinWithGradleConfigurator.kt | 23 ++++++ .../configuration/KotlinMavenConfigurator.kt | 44 ++++++++++ idea/idea.iml | 2 +- .../ConfigureKotlinInProjectUtils.kt | 8 +- .../KotlinProjectConfigurator.kt | 3 + .../KotlinWithLibraryConfigurator.kt | 22 +++++ .../idea/configuration/ModuleSourceRootMap.kt | 2 + .../quickfix/ChangeCoroutineSupportFix.kt | 81 +++---------------- 9 files changed, 114 insertions(+), 72 deletions(-) diff --git a/idea/idea-gradle/idea-gradle.iml b/idea/idea-gradle/idea-gradle.iml index f40570979cb..27be60e02b4 100644 --- a/idea/idea-gradle/idea-gradle.iml +++ b/idea/idea-gradle/idea-gradle.iml @@ -17,5 +17,6 @@ + \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt index 9b52a179793..4691e3ff9e5 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt @@ -20,6 +20,7 @@ import com.intellij.codeInsight.CodeInsightUtilCore import com.intellij.ide.actions.OpenFileAction import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.fileEditor.OpenFileDescriptor import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtil import com.intellij.openapi.project.Project @@ -33,8 +34,12 @@ import com.intellij.openapi.vfs.WritingAccessProvider import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.config.CoroutineSupport +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.idea.KotlinPluginUtil +import org.jetbrains.kotlin.idea.facet.getRuntimeLibraryVersion import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion +import org.jetbrains.kotlin.idea.quickfix.ChangeCoroutineSupportFix import org.jetbrains.kotlin.idea.util.application.executeCommand import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.versions.getStdlibArtifactId @@ -177,6 +182,24 @@ abstract class KotlinWithGradleConfigurator : KotlinProjectConfigurator { return isModified } + override fun changeCoroutineConfiguration(module: Module, state: LanguageFeature.State) { + val runtimeUpdateRequired = state != LanguageFeature.State.DISABLED && + (getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false) + + if (runtimeUpdateRequired) { + Messages.showErrorDialog(module.project, + "Coroutines support requires version 1.1 or later of the Kotlin runtime library. " + + "Please update the version in your build script.", + ChangeCoroutineSupportFix.getFixText(state)) + return + } + + val element = changeCoroutineConfiguration(module, CoroutineSupport.getCompilerArgument(state)) + if (element != null) { + OpenFileDescriptor(module.project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true) + } + } + companion object { fun getManipulator(file: PsiFile): GradleBuildScriptManipulator = when (file) { is KtFile -> KotlinBuildScriptManipulator(file) diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/configuration/KotlinMavenConfigurator.kt b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/configuration/KotlinMavenConfigurator.kt index 48e497d07d3..4d5339686ea 100644 --- a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/configuration/KotlinMavenConfigurator.kt +++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/configuration/KotlinMavenConfigurator.kt @@ -20,11 +20,13 @@ import com.intellij.codeInsight.CodeInsightUtilCore import com.intellij.ide.actions.OpenFileAction import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.fileEditor.OpenFileDescriptor import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Messages import com.intellij.openapi.vfs.WritingAccessProvider +import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import com.intellij.psi.search.FileTypeIndex @@ -35,12 +37,17 @@ import org.jetbrains.idea.maven.dom.model.MavenDomPlugin import org.jetbrains.idea.maven.model.MavenId import org.jetbrains.idea.maven.project.MavenProjectsManager import org.jetbrains.idea.maven.utils.MavenArtifactScope +import org.jetbrains.kotlin.config.CoroutineSupport +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.idea.KotlinPluginUtil import org.jetbrains.kotlin.idea.configuration.* +import org.jetbrains.kotlin.idea.facet.getRuntimeLibraryVersion import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion import org.jetbrains.kotlin.idea.maven.PomFile +import org.jetbrains.kotlin.idea.maven.changeCoroutineConfiguration import org.jetbrains.kotlin.idea.maven.excludeMavenChildrenModules import org.jetbrains.kotlin.idea.maven.kotlinPluginId +import org.jetbrains.kotlin.idea.quickfix.ChangeCoroutineSupportFix import org.jetbrains.kotlin.idea.util.application.runReadAction abstract class KotlinMavenConfigurator @@ -187,6 +194,43 @@ abstract class KotlinMavenConfigurator } } + override fun changeCoroutineConfiguration(module: Module, state: LanguageFeature.State) { + val runtimeUpdateRequired = state != LanguageFeature.State.DISABLED && + (getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false) + + val messageTitle = ChangeCoroutineSupportFix.getFixText(state) + if (runtimeUpdateRequired) { + Messages.showErrorDialog(module.project, + "Coroutines support requires version 1.1 or later of the Kotlin runtime library. " + + "Please update the version in your build script.", + messageTitle) + return + } + + val element = changeMavenCoroutineConfiguration(module, CoroutineSupport.getCompilerArgument(state), messageTitle) + + if (element != null) { + OpenFileDescriptor(module.project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true) + } + + } + + private fun changeMavenCoroutineConfiguration(module: Module, value: String, messageTitle: String): PsiElement? { + fun doChangeMavenCoroutineConfiguration(): PsiElement? { + val psi = KotlinMavenConfigurator.findModulePomFile(module) as? XmlFile ?: return null + val pom = PomFile.forFileOrNull(psi) ?: return null + return pom.changeCoroutineConfiguration(value) + } + + val element = doChangeMavenCoroutineConfiguration() + if (element == null) { + Messages.showErrorDialog(module.project, + "Failed to update.pom.xml. Please update the file manually.", + messageTitle) + } + return element + } + companion object { val NAME = "maven" diff --git a/idea/idea.iml b/idea/idea.iml index 9978df58217..2f91c792c75 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -67,7 +67,7 @@ - + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt index c6ea7df879e..aab667de1c3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt @@ -168,7 +168,7 @@ fun getConfigurableModules(project: Project): List { } fun getAbleToRunConfigurators(module: Module): Collection { - val moduleGroup = ModuleSourceRootMap(module.project).toModuleGroup(module) + val moduleGroup = module.toModuleGroup() return allConfigurators().filter { it.getStatus(moduleGroup) == ConfigureKotlinStatus.CAN_BE_CONFIGURED } @@ -203,6 +203,12 @@ fun getCanBeConfiguredModulesWithKotlinFiles(project: Project, excludeModules: C }.map { it.baseModule } } +fun findApplicableConfigurator(module: Module): KotlinProjectConfigurator { + val moduleGroup = module.toModuleGroup() + return allConfigurators().find { it.getStatus(moduleGroup) != ConfigureKotlinStatus.NON_APPLICABLE } + ?: KotlinJavaModuleConfigurator.instance +} + fun hasAnyKotlinRuntimeInScope(module: Module): Boolean { return runReadAction { val scope = module.getModuleWithDependenciesAndLibrariesScope(hasKotlinFilesOnlyInTests(module)) diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinProjectConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinProjectConfigurator.kt index 3ec933f3a9b..7b88694fbc3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinProjectConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinProjectConfigurator.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.configuration import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.resolve.TargetPlatform enum class ConfigureKotlinStatus { @@ -47,6 +48,8 @@ interface KotlinProjectConfigurator { val targetPlatform: TargetPlatform + fun changeCoroutineConfiguration(module: Module, state: LanguageFeature.State) + companion object { val EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.projectConfigurator") } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt index 08e767e31d6..25dbda1f11d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt @@ -28,9 +28,14 @@ import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtilCore import org.jetbrains.annotations.Contract +import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.idea.KotlinPluginUtil +import org.jetbrains.kotlin.idea.facet.getRuntimeLibraryVersion import org.jetbrains.kotlin.idea.framework.ui.CreateLibraryDialogWithModules import org.jetbrains.kotlin.idea.framework.ui.FileUIUtils +import org.jetbrains.kotlin.idea.quickfix.askUpdateRuntime import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor import org.jetbrains.kotlin.idea.versions.findKotlinRuntimeLibrary @@ -325,6 +330,23 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj !KotlinPluginUtil.isGradleModule(module) } + override fun changeCoroutineConfiguration(module: Module, state: LanguageFeature.State) { + val runtimeUpdateRequired = state != LanguageFeature.State.DISABLED && + (getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false) + + + if (runtimeUpdateRequired && !askUpdateRuntime(module, LanguageFeature.Coroutines.sinceApiVersion)) { + return + } + + val facetSettings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module) + ModuleRootModificationUtil.updateModel(module) { + facetSettings.coroutineSupport = state + facetSettings.apiLevel = LanguageVersion.KOTLIN_1_1 + facetSettings.languageLevel = LanguageVersion.KOTLIN_1_1 + } + } + companion object { val DEFAULT_LIBRARY_DIR = "lib" diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt index 7cce80adc46..8ed0f7fc432 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt @@ -58,6 +58,8 @@ class ModuleSourceRootMap(val modules: Collection) { fun toModuleGroup(module: Module): ModuleSourceRootGroup = groupByBaseModules(listOf(module)).single() } +fun Module.toModuleGroup() = ModuleSourceRootMap(project).toModuleGroup(this) + private fun isSourceRootPrefix(externalId: String, previousModuleExternalId: String) = externalId.length < previousModuleExternalId.length && previousModuleExternalId.startsWith(externalId) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt index 0c33e6ae976..a3a890ee5aa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt @@ -18,30 +18,18 @@ package org.jetbrains.kotlin.idea.quickfix import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor -import com.intellij.openapi.fileEditor.OpenFileDescriptor -import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.roots.ex.ProjectRootManagerEx -import com.intellij.openapi.ui.Messages import com.intellij.psi.PsiElement -import com.intellij.psi.xml.XmlFile import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.config.CoroutineSupport -import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.KotlinPluginUtil import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder -import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator +import org.jetbrains.kotlin.idea.configuration.findApplicableConfigurator import org.jetbrains.kotlin.idea.facet.KotlinFacet -import org.jetbrains.kotlin.idea.facet.getRuntimeLibraryVersion -import org.jetbrains.kotlin.idea.maven.PomFile -import org.jetbrains.kotlin.idea.maven.changeCoroutineConfiguration -import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator import org.jetbrains.kotlin.psi.KtFile sealed class ChangeCoroutineSupportFix( @@ -57,58 +45,7 @@ sealed class ChangeCoroutineSupportFix( override fun invoke(project: Project, editor: Editor?, file: KtFile) { val module = ModuleUtilCore.findModuleForPsiElement(file) ?: return - val runtimeUpdateRequired = coroutineSupportEnabled && - (getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false) - - if (KotlinPluginUtil.isGradleModule(module) || KotlinPluginUtil.isMavenModule(module)) { - if (runtimeUpdateRequired) { - Messages.showErrorDialog(project, - "Coroutines support requires version 1.1 or later of the Kotlin runtime library. " + - "Please update the version in your build script.", - super.getText()) - return - } - - val element = if (KotlinPluginUtil.isGradleModule(module)) - KotlinWithGradleConfigurator.changeCoroutineConfiguration( - module, CoroutineSupport.getCompilerArgument(coroutineSupport) - ) - else - changeMavenCoroutineConfiguration(module, CoroutineSupport.getCompilerArgument(coroutineSupport)) - - if (element != null) { - OpenFileDescriptor(project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true) - } - return - } - - if (runtimeUpdateRequired && !askUpdateRuntime(module, LanguageFeature.Coroutines.sinceApiVersion)) { - return - } - - val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(module) - ModuleRootModificationUtil.updateModel(module) { - facetSettings.coroutineSupport = coroutineSupport - facetSettings.apiLevel = LanguageVersion.KOTLIN_1_1 - facetSettings.languageLevel = LanguageVersion.KOTLIN_1_1 - } - } - - private fun changeMavenCoroutineConfiguration(module: Module, value: String): PsiElement? { - fun doChangeMavenCoroutineConfiguration(): PsiElement? { - val psi = KotlinMavenConfigurator.findModulePomFile(module) as? XmlFile ?: return null - val pom = PomFile.forFileOrNull(psi) ?: return null - return pom.changeCoroutineConfiguration(value) - } - - val element = doChangeMavenCoroutineConfiguration() - if (element == null) { - Messages.showErrorDialog(module.project, - "Failed to update.pom.xml. Please update the file manually.", - text) - } - return element - + findApplicableConfigurator(module).changeCoroutineConfiguration(module, coroutineSupport) } } @@ -135,14 +72,18 @@ sealed class ChangeCoroutineSupportFix( override fun getFamilyName() = "Enable/Disable coroutine support" override fun getText(): String { - return when (coroutineSupport) { - LanguageFeature.State.ENABLED -> "Enable coroutine support" - LanguageFeature.State.ENABLED_WITH_WARNING -> "Enable coroutine support (with warning)" - LanguageFeature.State.ENABLED_WITH_ERROR, LanguageFeature.State.DISABLED -> "Disable coroutine support" - } + return getFixText(coroutineSupport) } companion object : KotlinIntentionActionsFactory() { + fun getFixText(state: LanguageFeature.State): String { + return when (state) { + LanguageFeature.State.ENABLED -> "Enable coroutine support" + LanguageFeature.State.ENABLED_WITH_WARNING -> "Enable coroutine support (with warning)" + LanguageFeature.State.ENABLED_WITH_ERROR, LanguageFeature.State.DISABLED -> "Disable coroutine support" + } + } + override fun doCreateActions(diagnostic: Diagnostic): List { val newCoroutineSupports = when (diagnostic.factory) { Errors.EXPERIMENTAL_FEATURE_ERROR -> {