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.ModifiableRootModel
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.KotlinFacetType
import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait
@@ -28,15 +29,8 @@ import org.jetbrains.kotlin.test.testFramework.runWriteAction
class KotlinProjectDescriptorWithFacet(val languageVersion: LanguageVersion) : KotlinLightProjectDescriptor() {
override fun configureModule(module: Module, model: ModifiableRootModel, contentEntry: ContentEntry) {
val facetManager = FacetManager.getInstance(module)
val facetModel = facetManager.createModifiableModel()
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() }
configureKotlinFacet(module) { ->
settings.versionInfo.languageLevel = languageVersion
}
}
@@ -44,3 +38,18 @@ class KotlinProjectDescriptorWithFacet(val languageVersion: LanguageVersion) : K
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
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.module.Module
@@ -157,23 +158,27 @@ sealed class EnableUnsupportedFeatureFix(
fun checkUpdateRuntime(project: Project, requiredVersion: ApiVersion): Boolean {
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
}
if (modulesWithOutdatedRuntime.isNotEmpty()) {
if (askUpdateRuntime(project, requiredVersion,
modulesWithOutdatedRuntime.mapNotNull(::findKotlinRuntimeLibrary))) return false
if (!askUpdateRuntime(project, requiredVersion,
modulesWithOutdatedRuntime.mapNotNull(::findKotlinRuntimeLibrary))) return false
}
return true
}
fun askUpdateRuntime(project: Project, requiredVersion: ApiVersion, librariesToUpdate: List<Library>): Boolean {
val rc = Messages.showOkCancelDialog(project,
"This language feature requires version $requiredVersion or later of the Kotlin runtime library. " +
"Would you like to update the runtime library in your project?",
"Update Runtime Library",
Messages.getQuestionIcon())
if (rc != Messages.OK) return false
if (!ApplicationManager.getApplication().isUnitTestMode) {
val rc = Messages.showOkCancelDialog(project,
"This language feature requires version $requiredVersion or later of the Kotlin runtime library. " +
"Would you like to update the runtime library in your project?",
"Update Runtime Library",
Messages.getQuestionIcon())
if (rc != Messages.OK) return false
}
updateLibraries(project, librariesToUpdate)
return true
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.versions
import com.google.common.collect.Sets
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
@@ -84,42 +85,40 @@ fun updateLibraries(project: Project, libraries: Collection<Library>) {
return
}
ApplicationManager.getApplication().invokeLater {
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?:
error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME)
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?:
error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME)
val kJsConfigurator = getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator? ?:
error("Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME)
val kJsConfigurator = getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator? ?:
error("Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME)
val collector = createConfigureKotlinNotificationCollector(project)
val collector = createConfigureKotlinNotificationCollector(project)
for (library in libraries) {
if (isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
updateJar(project, getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR)
updateJar(project, getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR)
updateJar(project, getTestJar(library), LibraryJarDescriptor.TEST_JAR)
for (library in libraries) {
if (isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
updateJar(project, getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR)
updateJar(project, getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR)
updateJar(project, getTestJar(library), LibraryJarDescriptor.TEST_JAR)
if (kJvmConfigurator.changeOldSourcesPathIfNeeded(library, collector)) {
kJvmConfigurator.copySourcesToPathFromLibrary(library, collector)
}
else {
updateJar(project, getRuntimeSrcJar(library), LibraryJarDescriptor.RUNTIME_SRC_JAR)
}
if (kJvmConfigurator.changeOldSourcesPathIfNeeded(library, collector)) {
kJvmConfigurator.copySourcesToPathFromLibrary(library, collector)
}
else if (isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
updateJar(project, getJsStdLibJar(library), LibraryJarDescriptor.JS_STDLIB_JAR)
if (kJsConfigurator.changeOldSourcesPathIfNeeded(library, collector)) {
kJsConfigurator.copySourcesToPathFromLibrary(library, collector)
}
else {
updateJar(project, getJsStdLibSrcJar(library), LibraryJarDescriptor.JS_STDLIB_SRC_JAR)
}
else {
updateJar(project, getRuntimeSrcJar(library), LibraryJarDescriptor.RUNTIME_SRC_JAR)
}
}
else if (isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
updateJar(project, getJsStdLibJar(library), LibraryJarDescriptor.JS_STDLIB_JAR)
collector.showNotification()
if (kJsConfigurator.changeOldSourcesPathIfNeeded(library, collector)) {
kJsConfigurator.copySourcesToPathFromLibrary(library, collector)
}
else {
updateJar(project, getJsStdLibSrcJar(library), LibraryJarDescriptor.JS_STDLIB_SRC_JAR)
}
}
}
collector.showNotification()
}
private fun updateJar(
@@ -108,7 +108,9 @@ fun notifyOutdatedKotlinRuntime(project: Project, outdatedLibraries: Collection<
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
if ("update" == event.description) {
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
updateLibraries(project, outdatedLibraries)
ApplicationManager.getApplication().invokeLater {
updateLibraries(project, outdatedLibraries)
}
suggestDeleteKotlinJsIfNeeded(project, outdatedLibraries)
}
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)
answer.createActionLabel(actionLabelText) { updateLibraries(project, badRuntimeLibraries) }
answer.createActionLabel(actionLabelText) {
ApplicationManager.getApplication().invokeLater {
updateLibraries(project, badRuntimeLibraries)
}
}
}
else if (badVersionedRoots.size == 1) {
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()
}
}