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.openapi.application.runWriteAction
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.util.concurrency.FutureResult
import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent 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.idea.configuration.MigrationInfo
import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait
import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
import java.lang.IllegalStateException
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
class GradleMigrateTest : GradleImportingTestCase() { class GradleMigrateTest : GradleImportingTestCase() {
@Test @Test
@TargetVersions("4.4+")
fun testMigrateStdlib() { fun testMigrateStdlib() {
createProjectSubFile("settings.gradle", "include ':app'") val migrateComponentState = doMigrationTest(
val gradleFile = createProjectSubFile( beforeText = """
"app/build.gradle",
"""
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
@@ -39,19 +44,9 @@ class GradleMigrateTest : GradleImportingTestCase() {
dependencies { dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0" compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
} }
""".trimIndent() """,
)
importProject() afterText =
val document = runReadAction {
val gradlePsiFile = PsiManager.getInstance(myProject).findFile(gradleFile) ?: error("Can't find psi file for gradle file")
PsiDocumentManager.getInstance(myProject).getDocument(gradlePsiFile) ?: error("Can't find document for gradle file")
}
runInEdtAndWait {
runWriteAction {
document.setText(
""" """
buildscript { buildscript {
repositories { repositories {
@@ -68,17 +63,47 @@ class GradleMigrateTest : GradleImportingTestCase() {
dependencies { dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.0" compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.0"
} }
""".trimIndent() """
)
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 {
val gradlePsiFile = PsiManager.getInstance(myProject).findFile(gradleFile) ?: error("Can't find psi file for gradle file")
PsiDocumentManager.getInstance(myProject).getDocument(gradlePsiFile) ?: error("Can't find document for gradle file")
}
runInEdtAndWait {
runWriteAction {
document.setText(afterText.trimIndent())
}
}
val importResult = FutureResult<MigrationTestState?>()
val migrationProjectComponent = KotlinMigrationProjectComponent.getInstance(myProject)
migrationProjectComponent.setImportFinishListener { migrationState ->
importResult.set(migrationState)
} }
importProject() importProject()
val actualMigrationInfo = KotlinMigrationProjectComponent.getInstance(myProject).requestLastMigrationInfo() return try {
importResult.get(5, TimeUnit.SECONDS)
Assert.assertEquals( } catch (te: TimeoutException) {
MigrationInfo.create("1.1.0", ApiVersion.KOTLIN_1_2, LanguageVersion.KOTLIN_1_2, newStdlibVersion = "1.2.0"), throw IllegalStateException("No reply with result from migration component")
actualMigrationInfo) } 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.migration.CodeMigrationToggleAction
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import org.jetbrains.kotlin.idea.versions.LibInfo import org.jetbrains.kotlin.idea.versions.LibInfo
class KotlinMigrationProjectComponent(val project: Project) { class KotlinMigrationProjectComponent(val project: Project) {
@Volatile
private var old: MigrationState? = null private var old: MigrationState? = null
private var new: MigrationState? = null
private var lastMigrationInfo: MigrationInfo? = null @Volatile
private var importFinishListener: ((MigrationTestState?) -> Unit)? = null
init { init {
val connection = project.messageBus.connect() val connection = project.messageBus.connect()
@@ -46,44 +48,54 @@ class KotlinMigrationProjectComponent(val project: Project) {
}) })
} }
@Synchronized class MigrationTestState(val migrationInfo: MigrationInfo?)
@TestOnly @TestOnly
fun requestLastMigrationInfo(): MigrationInfo? { fun setImportFinishListener(newListener: ((MigrationTestState?) -> Unit)?) {
val temp = lastMigrationInfo synchronized(this) {
lastMigrationInfo = null if (newListener != null && importFinishListener != null) {
return temp importFinishListener!!.invoke(null)
}
importFinishListener = newListener
}
}
private fun notifyFinish(migrationInfo: MigrationInfo?) {
importFinishListener?.invoke(MigrationTestState(migrationInfo))
} }
@Synchronized
fun onImportAboutToStart() { fun onImportAboutToStart() {
if (!CodeMigrationToggleAction.isEnabled(project) || !hasChangesInProjectFiles(project)) { if (!CodeMigrationToggleAction.isEnabled(project) || !hasChangesInProjectFiles(project)) {
old = null old = null
return return
} }
lastMigrationInfo = null
old = MigrationState.build(project) old = MigrationState.build(project)
} }
@Synchronized
fun onImportFinished() { fun onImportFinished() {
if (!CodeMigrationToggleAction.isEnabled(project)) { if (!CodeMigrationToggleAction.isEnabled(project) || old == null) {
notifyFinish(null)
return return
} }
if (old == null) return; ApplicationManager.getApplication().executeOnPooledThread {
var migrationInfo: MigrationInfo? = null
new = MigrationState.build(project) try {
val new = project.runReadActionInSmartMode {
val migrationInfo = prepareMigrationInfo(old, new) ?: return MigrationState.build(project)
}
val localOld = old.also {
old = null old = null
new = null } ?: return@executeOnPooledThread
migrationInfo = prepareMigrationInfo(localOld, new) ?: return@executeOnPooledThread
if (ApplicationManager.getApplication().isUnitTestMode) { if (ApplicationManager.getApplication().isUnitTestMode) {
lastMigrationInfo = migrationInfo return@executeOnPooledThread
return
} }
ApplicationManager.getApplication().invokeLater { ApplicationManager.getApplication().invokeLater {
@@ -101,6 +113,10 @@ class KotlinMigrationProjectComponent(val project: Project) {
} }
} }
} }
} finally {
notifyFinish(migrationInfo)
}
}
} }
companion object { companion object {