Add test for enabling coroutines/bumping language level, fix several breakages

This commit is contained in:
Dmitry Jemerov
2017-02-17 21:50:57 +01:00
parent 999ef51653
commit 4261880340
6 changed files with 226 additions and 47 deletions
@@ -21,6 +21,7 @@ import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ContentEntry import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration
import org.jetbrains.kotlin.idea.facet.KotlinFacetType import org.jetbrains.kotlin.idea.facet.KotlinFacetType
import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait
@@ -28,15 +29,8 @@ import org.jetbrains.kotlin.test.testFramework.runWriteAction
class KotlinProjectDescriptorWithFacet(val languageVersion: LanguageVersion) : KotlinLightProjectDescriptor() { class KotlinProjectDescriptorWithFacet(val languageVersion: LanguageVersion) : KotlinLightProjectDescriptor() {
override fun configureModule(module: Module, model: ModifiableRootModel, contentEntry: ContentEntry) { override fun configureModule(module: Module, model: ModifiableRootModel, contentEntry: ContentEntry) {
val facetManager = FacetManager.getInstance(module) configureKotlinFacet(module) { ->
val facetModel = facetManager.createModifiableModel() settings.versionInfo.languageLevel = languageVersion
val configuration = KotlinFacetConfiguration()
configuration.settings.useProjectSettings = false
configuration.settings.versionInfo.languageLevel = languageVersion
val facet = facetManager.createFacet(KotlinFacetType.INSTANCE, "Kotlin", configuration, null)
facetModel.addFacet(facet)
runInEdtAndWait {
runWriteAction { facetModel.commit() }
} }
} }
@@ -44,3 +38,18 @@ class KotlinProjectDescriptorWithFacet(val languageVersion: LanguageVersion) : K
val KOTLIN_10 = KotlinProjectDescriptorWithFacet(LanguageVersion.KOTLIN_1_0) val KOTLIN_10 = KotlinProjectDescriptorWithFacet(LanguageVersion.KOTLIN_1_0)
} }
} }
fun configureKotlinFacet(module: Module, configureCallback: KotlinFacetConfiguration.() -> Unit = {}): KotlinFacet {
val facetManager = FacetManager.getInstance(module)
val facetModel = facetManager.createModifiableModel()
val configuration = KotlinFacetConfiguration()
configuration.settings.useProjectSettings = false
configuration.configureCallback()
val facet = facetManager.createFacet(KotlinFacetType.INSTANCE, "Kotlin", configuration, null)
facetModel.addFacet(facet)
runInEdtAndWait {
runWriteAction { facetModel.commit() }
}
return facet
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.quickfix package org.jetbrains.kotlin.idea.quickfix
import com.intellij.openapi.application.ApplicationManager
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.Module
@@ -157,23 +158,27 @@ sealed class EnableUnsupportedFeatureFix(
fun checkUpdateRuntime(project: Project, requiredVersion: ApiVersion): Boolean { fun checkUpdateRuntime(project: Project, requiredVersion: ApiVersion): Boolean {
val modulesWithOutdatedRuntime = project.allModules().filter { module -> val modulesWithOutdatedRuntime = project.allModules().filter { module ->
val parsedModuleRuntimeVersion = getRuntimeLibraryVersion(module)?.let { ApiVersion.parse(it) } val parsedModuleRuntimeVersion = getRuntimeLibraryVersion(module)?.let { version ->
ApiVersion.parse(version.substringBefore("-"))
}
parsedModuleRuntimeVersion != null && parsedModuleRuntimeVersion < requiredVersion parsedModuleRuntimeVersion != null && parsedModuleRuntimeVersion < requiredVersion
} }
if (modulesWithOutdatedRuntime.isNotEmpty()) { if (modulesWithOutdatedRuntime.isNotEmpty()) {
if (askUpdateRuntime(project, requiredVersion, if (!askUpdateRuntime(project, requiredVersion,
modulesWithOutdatedRuntime.mapNotNull(::findKotlinRuntimeLibrary))) return false modulesWithOutdatedRuntime.mapNotNull(::findKotlinRuntimeLibrary))) return false
} }
return true return true
} }
fun askUpdateRuntime(project: Project, requiredVersion: ApiVersion, librariesToUpdate: List<Library>): Boolean { fun askUpdateRuntime(project: Project, requiredVersion: ApiVersion, librariesToUpdate: List<Library>): Boolean {
if (!ApplicationManager.getApplication().isUnitTestMode) {
val rc = Messages.showOkCancelDialog(project, val rc = Messages.showOkCancelDialog(project,
"This language feature requires version $requiredVersion or later of the Kotlin runtime library. " + "This language feature requires version $requiredVersion or later of the Kotlin runtime library. " +
"Would you like to update the runtime library in your project?", "Would you like to update the runtime library in your project?",
"Update Runtime Library", "Update Runtime Library",
Messages.getQuestionIcon()) Messages.getQuestionIcon())
if (rc != Messages.OK) return false if (rc != Messages.OK) return false
}
updateLibraries(project, librariesToUpdate) updateLibraries(project, librariesToUpdate)
return true return true
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.versions package org.jetbrains.kotlin.idea.versions
import com.google.common.collect.Sets
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.module.ModuleManager
@@ -84,7 +85,6 @@ fun updateLibraries(project: Project, libraries: Collection<Library>) {
return return
} }
ApplicationManager.getApplication().invokeLater {
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?: val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?:
error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME) error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME)
@@ -119,7 +119,6 @@ fun updateLibraries(project: Project, libraries: Collection<Library>) {
} }
collector.showNotification() collector.showNotification()
}
} }
private fun updateJar( private fun updateJar(
@@ -108,7 +108,9 @@ fun notifyOutdatedKotlinRuntime(project: Project, outdatedLibraries: Collection<
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) { if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
if ("update" == event.description) { if ("update" == event.description) {
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library } val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
ApplicationManager.getApplication().invokeLater {
updateLibraries(project, outdatedLibraries) updateLibraries(project, outdatedLibraries)
}
suggestDeleteKotlinJsIfNeeded(project, outdatedLibraries) suggestDeleteKotlinJsIfNeeded(project, outdatedLibraries)
} }
else if ("ignore" == event.description) { else if ("ignore" == event.description) {
@@ -122,7 +122,11 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
} }
val actionLabelText = MessageFormat.format("$updateAction {0,choice,0#|1#|1<all }Kotlin runtime librar{0,choice,0#|1#y|1<ies} ", badRuntimeLibraries.size) val actionLabelText = MessageFormat.format("$updateAction {0,choice,0#|1#|1<all }Kotlin runtime librar{0,choice,0#|1#y|1<ies} ", badRuntimeLibraries.size)
answer.createActionLabel(actionLabelText) { updateLibraries(project, badRuntimeLibraries) } answer.createActionLabel(actionLabelText) {
ApplicationManager.getApplication().invokeLater {
updateLibraries(project, badRuntimeLibraries)
}
}
} }
else if (badVersionedRoots.size == 1) { else if (badVersionedRoots.size == 1) {
val badVersionedRoot = badVersionedRoots.first() val badVersionedRoot = badVersionedRoots.first()
@@ -0,0 +1,160 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.facet.FacetManager
import com.intellij.facet.impl.FacetUtil
import com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.JarFileSystem
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
import org.jetbrains.kotlin.config.CoroutineSupport
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.facet.KotlinFacetType
import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.configureKotlinFacet
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import java.io.File
class LanguageFeatureQuickFixTest : LightPlatformCodeInsightFixtureTestCase() {
fun testEnableCoroutines() {
configureRuntime("mockRuntime11")
resetProjectSettings(LanguageVersion.KOTLIN_1_1)
myFixture.configureByText("foo.kt", "suspend fun foo()")
assertFalse(KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.coroutinesEnable)
myFixture.launchAction(myFixture.findSingleIntention("Enable coroutine support in the project"))
assertTrue(KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.coroutinesEnable)
}
fun testEnableCoroutinesFacet() {
configureRuntime("mockRuntime11")
val facet = configureKotlinFacet(myModule)
resetProjectSettings(LanguageVersion.KOTLIN_1_1)
myFixture.configureByText("foo.kt", "suspend fun foo()")
assertEquals(CoroutineSupport.ENABLED_WITH_WARNING, facet.configuration.settings.compilerInfo.coroutineSupport)
myFixture.launchAction(myFixture.findSingleIntention("Enable coroutine support in the current module"))
assertEquals(CoroutineSupport.ENABLED, facet.configuration.settings.compilerInfo.coroutineSupport)
}
fun testIncreaseLangLevel() {
configureRuntime("mockRuntime11")
resetProjectSettings(LanguageVersion.KOTLIN_1_0)
myFixture.configureByText("foo.kt", "val x get() = 1")
myFixture.launchAction(myFixture.findSingleIntention("Set project language version to 1.1"))
assertEquals("1.1", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.languageVersion)
assertEquals("1.0", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.apiVersion)
}
fun testIncreaseLangLevelFacet() {
configureRuntime("mockRuntime11")
resetProjectSettings(LanguageVersion.KOTLIN_1_0)
configureKotlinFacet(myModule) {
settings.versionInfo.languageLevel = LanguageVersion.KOTLIN_1_0
settings.versionInfo.apiLevel = LanguageVersion.KOTLIN_1_0
}
myFixture.configureByText("foo.kt", "val x get() = 1")
assertEquals(LanguageVersion.KOTLIN_1_0, myModule.languageVersionSettings.languageVersion)
myFixture.launchAction(myFixture.findSingleIntention("Set module language version to 1.1"))
assertEquals(LanguageVersion.KOTLIN_1_1, myModule.languageVersionSettings.languageVersion)
}
fun testIncreaseLangAndApiLevel() {
configureRuntime("mockRuntime11")
resetProjectSettings(LanguageVersion.KOTLIN_1_0)
myFixture.configureByText("foo.kt", "val x = <caret>\"s\"::length")
myFixture.launchAction(myFixture.findSingleIntention("Set project language version to 1.1"))
assertEquals("1.1", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.languageVersion)
assertEquals("1.1", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.apiVersion)
}
fun testIncreaseLangAndApiLevel_10() {
val runtime = configureRuntime("mockRuntime106")
resetProjectSettings(LanguageVersion.KOTLIN_1_0)
myFixture.configureByText("foo.kt", "val x = <caret>\"s\"::length")
myFixture.launchAction(myFixture.findSingleIntention("Set project language version to 1.1"))
assertEquals("1.1", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.languageVersion)
assertEquals("1.1", KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.apiVersion)
assertEquals(bundledRuntimeVersion(), JavaRuntimeDetectionUtil.getJavaRuntimeVersion(listOf(runtime)))
}
fun testIncreaseLangLevelFacet_10() {
val runtime = configureRuntime("mockRuntime106")
resetProjectSettings(LanguageVersion.KOTLIN_1_0)
configureKotlinFacet(myModule) {
settings.versionInfo.languageLevel = LanguageVersion.KOTLIN_1_0
settings.versionInfo.apiLevel = LanguageVersion.KOTLIN_1_0
}
myFixture.configureByText("foo.kt", "val x = <caret>\"s\"::length")
assertEquals(LanguageVersion.KOTLIN_1_0, myModule.languageVersionSettings.languageVersion)
myFixture.launchAction(myFixture.findSingleIntention("Set module language version to 1.1"))
assertEquals(LanguageVersion.KOTLIN_1_1, myModule.languageVersionSettings.languageVersion)
assertEquals(bundledRuntimeVersion(), JavaRuntimeDetectionUtil.getJavaRuntimeVersion(listOf(runtime)))
}
private fun configureRuntime(path: String): VirtualFile {
val tempFile = FileUtil.createTempFile("kotlin-runtime", ".jar")
FileUtil.copy(File("idea/testData/configuration/$path/kotlin-runtime.jar"), tempFile)
val tempVFile = LocalFileSystem.getInstance().findFileByIoFile(tempFile)!!
updateModel(myFixture.module) { model ->
val editor = NewLibraryEditor()
editor.name = "KotlinJavaRuntime"
editor.addRoot(JarFileSystem.getInstance().getJarRootForLocalFile(tempVFile), OrderRootType.CLASSES)
ConfigLibraryUtil.addLibrary(editor, model)
}
return tempVFile
}
private fun resetProjectSettings(version: LanguageVersion) {
with(KotlinCommonCompilerArgumentsHolder.getInstance(project).settings) {
languageVersion = version.versionString
apiVersion = version.versionString
coroutinesEnable = false
coroutinesWarn = true
coroutinesError = false
}
}
override fun tearDown() {
FacetManager.getInstance(myModule).getFacetByType(KotlinFacetType.TYPE_ID)?.let {
FacetUtil.deleteFacet(it)
}
ConfigLibraryUtil.removeLibrary(myModule, "KotlinJavaRuntime")
super.tearDown()
}
}