Convert KotlinNativeABICompatibilityChecker into a startup activity

Relates to #KT-38318
This commit is contained in:
Vladimir Dolzhenko
2020-04-18 11:39:53 +02:00
parent 6fe800eea0
commit 1827465f48
2 changed files with 34 additions and 37 deletions
@@ -12,11 +12,13 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.ReadAction.nonBlocking import com.intellij.openapi.application.ReadAction.nonBlocking
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.ModuleRootEvent import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.startup.StartupActivity
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.text.StringUtilRt import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.util.PathUtilRt import com.intellij.util.PathUtilRt
import com.intellij.util.concurrency.AppExecutorUtil import com.intellij.util.concurrency.AppExecutorUtil
@@ -29,8 +31,9 @@ import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanel
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
// BUNCH: 192
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */ /** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable { class KotlinNativeABICompatibilityChecker : StartupActivity {
private sealed class LibraryGroup(private val ordinal: Int) : Comparable<LibraryGroup> { private sealed class LibraryGroup(private val ordinal: Int) : Comparable<LibraryGroup> {
@@ -47,46 +50,46 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
private val cachedIncompatibleLibraries = HashSet<String>() private val cachedIncompatibleLibraries = HashSet<String>()
@Volatile override fun runActivity(project: Project) {
private var backgroundJob: CancellablePromise<*>? = null
init {
project.messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener { project.messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
override fun rootsChanged(event: ModuleRootEvent) { override fun rootsChanged(event: ModuleRootEvent) {
// run when project roots are changes, e.g. on project import // run when project roots are changes, e.g. on project import
validateKotlinNativeLibraries() validateKotlinNativeLibraries(project)
} }
}) })
validateKotlinNativeLibraries(project)
} }
override fun projectOpened() { private fun validateKotlinNativeLibraries(project: Project) {
// run when project is opened
validateKotlinNativeLibraries()
}
private fun validateKotlinNativeLibraries() {
if (ApplicationManager.getApplication().isUnitTestMode || project.isDisposed) if (ApplicationManager.getApplication().isUnitTestMode || project.isDisposed)
return return
backgroundJob = nonBlocking<List<Notification>> { val backgroundJob: Ref<CancellablePromise<*>> = Ref()
val librariesToNotify = getLibrariesToNotifyAbout() val disposable = Disposable { backgroundJob.get()?.let(CancellablePromise<*>::cancel) }
prepareNotifications(librariesToNotify) Disposer.register(project, disposable)
}
.finishOnUiThread(ModalityState.defaultModalityState()) { notifications -> backgroundJob.set(
notifications.forEach { nonBlocking<List<Notification>> {
it.notify(project) val librariesToNotify = getLibrariesToNotifyAbout(project)
prepareNotifications(project, librariesToNotify)
}
.finishOnUiThread(ModalityState.defaultModalityState()) { notifications ->
notifications.forEach {
it.notify(project)
}
} }
} .expireWith(project) // cancel job when project is disposed
.expireWith(project) // cancel job when project is disposed .coalesceBy(this@KotlinNativeABICompatibilityChecker) // cancel previous job when new one is submitted
.coalesceBy(this@KotlinNativeABICompatibilityChecker) // cancel previous job when new one is submitted .withDocumentsCommitted(project)
.withDocumentsCommitted(project) .submit(AppExecutorUtil.getAppExecutorService())
.submit(AppExecutorUtil.getAppExecutorService()) .onProcessed {
.onProcessed { backgroundJob.set(null)
backgroundJob = null Disposer.dispose(disposable)
} })
} }
private fun getLibrariesToNotifyAbout(): Map<String, NativeKlibLibraryInfo> { private fun getLibrariesToNotifyAbout(project: Project): Map<String, NativeKlibLibraryInfo> {
val incompatibleLibraries = getModuleInfosFromIdeaModel(project) val incompatibleLibraries = getModuleInfosFromIdeaModel(project)
.filterIsInstance<NativeKlibLibraryInfo>() .filterIsInstance<NativeKlibLibraryInfo>()
.filter { !it.compatibilityInfo.isCompatible } .filter { !it.compatibilityInfo.isCompatible }
@@ -103,7 +106,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
return newEntries return newEntries
} }
private fun prepareNotifications(librariesToNotify: Map<String, NativeKlibLibraryInfo>): List<Notification> { private fun prepareNotifications(project: Project, librariesToNotify: Map<String, NativeKlibLibraryInfo>): List<Notification> {
if (librariesToNotify.isEmpty()) if (librariesToNotify.isEmpty())
return emptyList() return emptyList()
@@ -201,13 +204,6 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
return (ideLibraryName ?: PathUtilRt.getFileName(libraryInfo.libraryRoot)) to LibraryGroup.User return (ideLibraryName ?: PathUtilRt.getFileName(libraryInfo.libraryRoot)) to LibraryGroup.User
} }
override fun dispose() {
backgroundJob?.let(CancellablePromise<*>::cancel)
backgroundJob = null
cachedIncompatibleLibraries.clear()
}
companion object { companion object {
private val LIBRARY_NAME_COMPARATOR = Comparator<String> { libraryName1, libraryName2 -> private val LIBRARY_NAME_COMPARATOR = Comparator<String> { libraryName1, libraryName2 ->
when { when {
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata
// BUNCH: 192
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */ /** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable { class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable {