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,9 +44,38 @@ class GradleMigrateTest : GradleImportingTestCase() {
dependencies { dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0" 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() importProject()
val document = runReadAction { val document = runReadAction {
@@ -51,34 +85,25 @@ class GradleMigrateTest : GradleImportingTestCase() {
runInEdtAndWait { runInEdtAndWait {
runWriteAction { runWriteAction {
document.setText( document.setText(afterText.trimIndent())
"""
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()
)
} }
} }
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,59 +48,73 @@ 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)
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)
} }
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)
} }
} }
} }