Postpone migration till indexes are ready (KT-26428)

#KT-26428 Fixed
This commit is contained in:
Nikolay Krasko
2018-09-17 11:39:58 +03:00
parent 0660e4d616
commit 11b948f004
2 changed files with 107 additions and 66 deletions
@@ -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<MigrationTestState?>()
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)
}
}
}
@@ -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)
}
}
}