Quickfix to enable coroutine support works in Maven projects

#KT-17521 Fixed
This commit is contained in:
Dmitry Jemerov
2017-04-20 18:38:04 +02:00
parent aabd560eef
commit 7346fee513
6 changed files with 160 additions and 7 deletions
@@ -303,7 +303,7 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
return configurationTag.add(newTag) as XmlTag return configurationTag.add(newTag) as XmlTag
} }
fun addPluginConfiguration(plugin: MavenDomPlugin, optionName: String, optionValue: String) { fun addPluginConfiguration(plugin: MavenDomPlugin, optionName: String, optionValue: String): XmlTag {
val configurationTag = plugin.configuration.ensureTagExists() val configurationTag = plugin.configuration.ensureTagExists()
val existingTag = configurationTag.findFirstSubTag(optionName) val existingTag = configurationTag.findFirstSubTag(optionName)
if (existingTag != null) { if (existingTag != null) {
@@ -312,6 +312,7 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
else { else {
configurationTag.add(configurationTag.createChildTag(optionName, optionValue)) configurationTag.add(configurationTag.createChildTag(optionName, optionValue))
} }
return configurationTag
} }
fun addPluginRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository { fun addPluginRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository {
@@ -601,5 +602,12 @@ private fun PomFile.changeConfigurationOrProperty(kotlinPlugin: MavenDomPlugin,
} }
} }
return null return addPluginConfiguration(kotlinPlugin, configurationTagName, value)
}
fun PomFile.changeCoroutineConfiguration(value: String): PsiElement? {
val kotlinPlugin = findPlugin(MavenId(KotlinMavenConfigurator.GROUP_ID,
KotlinMavenConfigurator.MAVEN_PLUGIN_ID,
null)) ?: return null
return changeConfigurationOrProperty(kotlinPlugin, "experimentalCoroutines", "kotlin.compiler.experimental.coroutines", value)
} }
@@ -62,6 +62,10 @@ class MavenLanguageFeatureQuickFixTest : MavenImportingTestCase() {
doTest("Set module language version to 1.1") doTest("Set module language version to 1.1")
} }
@Test fun testEnableCoroutines() {
doTest("Enable coroutine support in the current module")
}
private fun doTest(intentionName: String) { private fun doTest(intentionName: String) {
val pomVFile = createProjectSubFile("pom.xml", File(getTestDataPath(), "pom.xml").readText()) val pomVFile = createProjectSubFile("pom.xml", File(getTestDataPath(), "pom.xml").readText())
val sourceVFile = createProjectSubFile("src/main/kotlin/src.kt", File(getTestDataPath(), "src.kt").readText()) val sourceVFile = createProjectSubFile("src/main/kotlin/src.kt", File(getTestDataPath(), "src.kt").readText())
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>wrong-goal</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>wrong-goal</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<experimentalCoroutines>enable</experimentalCoroutines>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,2 @@
suspend fun foo() {
}
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.OpenFileDescriptor import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ex.ProjectRootManagerEx import com.intellij.openapi.roots.ex.ProjectRootManagerEx
import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.Messages
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.xml.XmlFile
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.config.CoroutineSupport import org.jetbrains.kotlin.config.CoroutineSupport
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
@@ -37,6 +39,9 @@ import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgu
import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator
import org.jetbrains.kotlin.idea.facet.KotlinFacet import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.getRuntimeLibraryVersion 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 import org.jetbrains.kotlin.psi.KtFile
sealed class ChangeCoroutineSupportFix( sealed class ChangeCoroutineSupportFix(
@@ -55,7 +60,7 @@ sealed class ChangeCoroutineSupportFix(
val runtimeUpdateRequired = coroutineSupportEnabled && val runtimeUpdateRequired = coroutineSupportEnabled &&
(getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false) (getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false)
if (KotlinPluginUtil.isGradleModule(module)) { if (KotlinPluginUtil.isGradleModule(module) || KotlinPluginUtil.isMavenModule(module)) {
if (runtimeUpdateRequired) { if (runtimeUpdateRequired) {
Messages.showErrorDialog(project, Messages.showErrorDialog(project,
"Coroutines support requires version 1.1 or later of the Kotlin runtime library. " + "Coroutines support requires version 1.1 or later of the Kotlin runtime library. " +
@@ -64,9 +69,13 @@ sealed class ChangeCoroutineSupportFix(
return return
} }
val element = KotlinWithGradleConfigurator.changeCoroutineConfiguration( val element = if (KotlinPluginUtil.isGradleModule(module))
KotlinWithGradleConfigurator.changeCoroutineConfiguration(
module, CoroutineSupport.getCompilerArgument(coroutineSupport) module, CoroutineSupport.getCompilerArgument(coroutineSupport)
) )
else
changeMavenCoroutineConfiguration(module, CoroutineSupport.getCompilerArgument(coroutineSupport))
if (element != null) { if (element != null) {
OpenFileDescriptor(project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true) OpenFileDescriptor(project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true)
} }
@@ -85,6 +94,22 @@ sealed class ChangeCoroutineSupportFix(
} }
} }
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
}
} }
class InProject(element: PsiElement, coroutineSupport: LanguageFeature.State) : ChangeCoroutineSupportFix(element, coroutineSupport) { class InProject(element: PsiElement, coroutineSupport: LanguageFeature.State) : ChangeCoroutineSupportFix(element, coroutineSupport) {
@@ -131,11 +156,10 @@ sealed class ChangeCoroutineSupportFix(
else -> return emptyList() else -> return emptyList()
} }
val module = ModuleUtilCore.findModuleForPsiElement(diagnostic.psiElement) ?: return emptyList() val module = ModuleUtilCore.findModuleForPsiElement(diagnostic.psiElement) ?: return emptyList()
if (KotlinPluginUtil.isMavenModule(module)) return emptyList()
val facetSettings = KotlinFacet.get(module)?.configuration?.settings val facetSettings = KotlinFacet.get(module)?.configuration?.settings
val configureInProject = (facetSettings == null || facetSettings.useProjectSettings) && val configureInProject = (facetSettings == null || facetSettings.useProjectSettings) &&
!KotlinPluginUtil.isGradleModule(module) !KotlinPluginUtil.isGradleModule(module) && !KotlinPluginUtil.isMavenModule(module)
val quickFixConstructor: (PsiElement, LanguageFeature.State) -> ChangeCoroutineSupportFix = val quickFixConstructor: (PsiElement, LanguageFeature.State) -> ChangeCoroutineSupportFix =
if (configureInProject) ::InProject else ::InModule if (configureInProject) ::InProject else ::InModule
return newCoroutineSupports.map { quickFixConstructor(diagnostic.psiElement, it) } return newCoroutineSupports.map { quickFixConstructor(diagnostic.psiElement, it) }