diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMigrateTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMigrateTest.kt index eeeca7c9cd2..1e912792582 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMigrateTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMigrateTest.kt @@ -9,21 +9,26 @@ import com.intellij.openapi.application.runReadAction import com.intellij.openapi.application.runWriteAction import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiManager +import com.intellij.util.concurrency.FutureResult import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent +import org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent.MigrationTestState import org.jetbrains.kotlin.idea.configuration.MigrationInfo import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait +import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions import org.junit.Assert import org.junit.Test +import java.lang.IllegalStateException +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException class GradleMigrateTest : GradleImportingTestCase() { @Test + @TargetVersions("4.4+") fun testMigrateStdlib() { - createProjectSubFile("settings.gradle", "include ':app'") - val gradleFile = createProjectSubFile( - "app/build.gradle", - """ + val migrateComponentState = doMigrationTest( + beforeText = """ buildscript { repositories { jcenter() @@ -39,9 +44,38 @@ class GradleMigrateTest : GradleImportingTestCase() { dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0" } - """.trimIndent() + """, + + afterText = + """ + buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0" + } + } + + apply plugin: 'kotlin' + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.0" + } + """ ) + Assert.assertEquals( + MigrationInfo.create("1.1.0", ApiVersion.KOTLIN_1_2, LanguageVersion.KOTLIN_1_2, newStdlibVersion = "1.2.0"), + migrateComponentState?.migrationInfo + ) + } + + private fun doMigrationTest(beforeText: String, afterText: String): MigrationTestState? { + createProjectSubFile("settings.gradle", "include ':app'") + val gradleFile = createProjectSubFile("app/build.gradle", beforeText.trimIndent()) + importProject() val document = runReadAction { @@ -51,34 +85,25 @@ class GradleMigrateTest : GradleImportingTestCase() { runInEdtAndWait { runWriteAction { - document.setText( - """ - buildscript { - repositories { - jcenter() - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0" - } - } - - apply plugin: 'kotlin' - - dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.0" - } - """.trimIndent() - ) + document.setText(afterText.trimIndent()) } } + val importResult = FutureResult() + val migrationProjectComponent = KotlinMigrationProjectComponent.getInstance(myProject) + + migrationProjectComponent.setImportFinishListener { migrationState -> + importResult.set(migrationState) + } + importProject() - val actualMigrationInfo = KotlinMigrationProjectComponent.getInstance(myProject).requestLastMigrationInfo() - - Assert.assertEquals( - MigrationInfo.create("1.1.0", ApiVersion.KOTLIN_1_2, LanguageVersion.KOTLIN_1_2, newStdlibVersion = "1.2.0"), - actualMigrationInfo) + return try { + importResult.get(5, TimeUnit.SECONDS) + } catch (te: TimeoutException) { + throw IllegalStateException("No reply with result from migration component") + } finally { + migrationProjectComponent.setImportFinishListener(null) + } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMigrationProjectComponent.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMigrationProjectComponent.kt index 8f27202e926..ee6778b3ce9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMigrationProjectComponent.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMigrationProjectComponent.kt @@ -31,13 +31,15 @@ import org.jetbrains.kotlin.idea.migration.CodeMigrationAction import org.jetbrains.kotlin.idea.migration.CodeMigrationToggleAction import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode import org.jetbrains.kotlin.idea.versions.LibInfo class KotlinMigrationProjectComponent(val project: Project) { + @Volatile private var old: MigrationState? = null - private var new: MigrationState? = null - private var lastMigrationInfo: MigrationInfo? = null + @Volatile + private var importFinishListener: ((MigrationTestState?) -> Unit)? = null init { val connection = project.messageBus.connect() @@ -46,59 +48,73 @@ class KotlinMigrationProjectComponent(val project: Project) { }) } - @Synchronized + class MigrationTestState(val migrationInfo: MigrationInfo?) + @TestOnly - fun requestLastMigrationInfo(): MigrationInfo? { - val temp = lastMigrationInfo - lastMigrationInfo = null - return temp + fun setImportFinishListener(newListener: ((MigrationTestState?) -> Unit)?) { + synchronized(this) { + if (newListener != null && importFinishListener != null) { + importFinishListener!!.invoke(null) + } + + importFinishListener = newListener + } + } + + private fun notifyFinish(migrationInfo: MigrationInfo?) { + importFinishListener?.invoke(MigrationTestState(migrationInfo)) } - @Synchronized fun onImportAboutToStart() { if (!CodeMigrationToggleAction.isEnabled(project) || !hasChangesInProjectFiles(project)) { old = null return } - lastMigrationInfo = null - old = MigrationState.build(project) } - @Synchronized fun onImportFinished() { - if (!CodeMigrationToggleAction.isEnabled(project)) { + if (!CodeMigrationToggleAction.isEnabled(project) || old == null) { + notifyFinish(null) return } - if (old == null) return; + ApplicationManager.getApplication().executeOnPooledThread { + var migrationInfo: MigrationInfo? = null - new = MigrationState.build(project) - - val migrationInfo = prepareMigrationInfo(old, new) ?: return - - old = null - new = null - - if (ApplicationManager.getApplication().isUnitTestMode) { - lastMigrationInfo = migrationInfo - return - } - - ApplicationManager.getApplication().invokeLater { - val migrationNotificationDialog = MigrationNotificationDialog(project, migrationInfo) - migrationNotificationDialog.show() - - if (migrationNotificationDialog.isOK) { - val action = ActionManager.getInstance().getAction(CodeMigrationAction.ACTION_ID) - - val dataContext = getDataContextFromDialog(migrationNotificationDialog) - if (dataContext != null) { - val actionEvent = AnActionEvent.createFromAnAction(action, null, ActionPlaces.ACTION_SEARCH, dataContext) - - action.actionPerformed(actionEvent) + try { + val new = project.runReadActionInSmartMode { + MigrationState.build(project) } + + val localOld = old.also { + old = null + } ?: return@executeOnPooledThread + + migrationInfo = prepareMigrationInfo(localOld, new) ?: return@executeOnPooledThread + + if (ApplicationManager.getApplication().isUnitTestMode) { + return@executeOnPooledThread + } + + ApplicationManager.getApplication().invokeLater { + val migrationNotificationDialog = MigrationNotificationDialog(project, migrationInfo) + migrationNotificationDialog.show() + + if (migrationNotificationDialog.isOK) { + val action = ActionManager.getInstance().getAction(CodeMigrationAction.ACTION_ID) + + val dataContext = getDataContextFromDialog(migrationNotificationDialog) + if (dataContext != null) { + val actionEvent = AnActionEvent.createFromAnAction(action, null, ActionPlaces.ACTION_SEARCH, dataContext) + + action.actionPerformed(actionEvent) + } + } + } + } finally { + notifyFinish(migrationInfo) } } }