Skip to content

Commit

Permalink
Convert KotlinNativeABICompatibilityChecker into a startup activity
Browse files Browse the repository at this point in the history
Relates to #KT-38318
  • Loading branch information
vladimirdolzhenko committed Apr 18, 2020
1 parent 6fe800e commit 1827465
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.ReadAction.nonBlocking
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.ModuleRootEvent
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.util.PathUtilRt
import com.intellij.util.concurrency.AppExecutorUtil
Expand All @@ -29,8 +31,9 @@ import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanel
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME

// BUNCH: 192
/** 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> {

Expand All @@ -47,46 +50,46 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec

private val cachedIncompatibleLibraries = HashSet<String>()

@Volatile
private var backgroundJob: CancellablePromise<*>? = null

init {
override fun runActivity(project: Project) {
project.messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
override fun rootsChanged(event: ModuleRootEvent) {
// run when project roots are changes, e.g. on project import
validateKotlinNativeLibraries()
validateKotlinNativeLibraries(project)
}
})
}

override fun projectOpened() {
// run when project is opened
validateKotlinNativeLibraries()
validateKotlinNativeLibraries(project)
}

private fun validateKotlinNativeLibraries() {
private fun validateKotlinNativeLibraries(project: Project) {
if (ApplicationManager.getApplication().isUnitTestMode || project.isDisposed)
return

backgroundJob = nonBlocking<List<Notification>> {
val librariesToNotify = getLibrariesToNotifyAbout()
prepareNotifications(librariesToNotify)
}
.finishOnUiThread(ModalityState.defaultModalityState()) { notifications ->
notifications.forEach {
it.notify(project)
}
}
.expireWith(project) // cancel job when project is disposed
.coalesceBy(this@KotlinNativeABICompatibilityChecker) // cancel previous job when new one is submitted
.withDocumentsCommitted(project)
.submit(AppExecutorUtil.getAppExecutorService())
.onProcessed {
backgroundJob = null
val backgroundJob: Ref<CancellablePromise<*>> = Ref()
val disposable = Disposable { backgroundJob.get()?.let(CancellablePromise<*>::cancel) }
Disposer.register(project, disposable)

backgroundJob.set(
nonBlocking<List<Notification>> {
val librariesToNotify = getLibrariesToNotifyAbout(project)
prepareNotifications(project, librariesToNotify)
}
.finishOnUiThread(ModalityState.defaultModalityState()) { notifications ->
notifications.forEach {
it.notify(project)
}
}
.expireWith(project) // cancel job when project is disposed
.coalesceBy(this@KotlinNativeABICompatibilityChecker) // cancel previous job when new one is submitted
.withDocumentsCommitted(project)
.submit(AppExecutorUtil.getAppExecutorService())
.onProcessed {
backgroundJob.set(null)
Disposer.dispose(disposable)
})
}

private fun getLibrariesToNotifyAbout(): Map<String, NativeKlibLibraryInfo> {
private fun getLibrariesToNotifyAbout(project: Project): Map<String, NativeKlibLibraryInfo> {
val incompatibleLibraries = getModuleInfosFromIdeaModel(project)
.filterIsInstance<NativeKlibLibraryInfo>()
.filter { !it.compatibilityInfo.isCompatible }
Expand All @@ -103,7 +106,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
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())
return emptyList()

Expand Down Expand Up @@ -201,13 +204,6 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
return (ideLibraryName ?: PathUtilRt.getFileName(libraryInfo.libraryRoot)) to LibraryGroup.User
}

override fun dispose() {
backgroundJob?.let(CancellablePromise<*>::cancel)
backgroundJob = null

cachedIncompatibleLibraries.clear()
}

companion object {
private val LIBRARY_NAME_COMPARATOR = Comparator<String> { libraryName1, libraryName2 ->
when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata

// BUNCH: 192
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable {

Expand Down

0 comments on commit 1827465

Please sign in to comment.