Convert KotlinConfigurationCheckerComponent to service

Relates to #KT-36471
This commit is contained in:
Vladimir Dolzhenko
2020-03-24 15:23:20 +01:00
parent abd20e3a90
commit a6450dd67e
21 changed files with 463 additions and 745 deletions
@@ -7,13 +7,12 @@ package org.jetbrains.kotlin.idea.actions.internal
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.project.impl.ProjectImpl
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerService
class ReactivePostOpenProjectActionsAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project as? ProjectImpl ?: return
val configureComponent = project.getComponentInstancesOfType(KotlinConfigurationCheckerComponent::class.java).single()
configureComponent.performProjectPostOpenActions()
val project = e.project ?: return
val configurationChecker = KotlinConfigurationCheckerService.getInstanceIfNotDisposed(project) ?: return
configurationChecker.performProjectPostOpenActions()
}
}
@@ -20,19 +20,19 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerService
class KotlinExternalSystemSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
override fun onStart(id: ExternalSystemTaskId, workingDir: String) {
val project = id.findResolvedProject() ?: return
KotlinMigrationProjectComponent.getInstanceIfNotDisposed(project)?.onImportAboutToStart()
KotlinConfigurationCheckerComponent.getInstanceIfNotDisposed(project)?.syncStarted()
KotlinConfigurationCheckerService.getInstanceIfNotDisposed(project)?.syncStarted()
}
override fun onEnd(id: ExternalSystemTaskId) {
// At this point changes might be still not applied to project structure yet.
val project = id.findResolvedProject() ?: return
KotlinConfigurationCheckerComponent.getInstanceIfNotDisposed(project)?.syncDone()
KotlinConfigurationCheckerService.getInstanceIfNotDisposed(project)?.syncDone()
}
}
@@ -26,7 +26,7 @@ import com.intellij.ui.EditorNotifications
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerService
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.SuppressNotificationState
@@ -60,9 +60,9 @@ class KotlinSetupEnvironmentNotificationProvider(private val myProject: Project)
return createSetupSdkPanel(myProject, psiFile)
}
val configurationCheckerComponent = KotlinConfigurationCheckerComponent.getInstanceIfNotDisposed(module.project) ?: return null
val configurationChecker = KotlinConfigurationCheckerService.getInstanceIfNotDisposed(module.project) ?: return null
if (!configurationCheckerComponent.isSyncing &&
if (!configurationChecker.isSyncing &&
isNotConfiguredNotificationRequired(module.toModuleGroup()) &&
!hasAnyKotlinRuntimeInScope(module) &&
UnsupportedAbiVersionNotificationPanelProvider.collectBadRoots(module).isEmpty()
@@ -16,80 +16,5 @@
package org.jetbrains.kotlin.idea.configuration.ui
import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationsConfiguration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
import org.jetbrains.kotlin.idea.configuration.notifyOutdatedBundledCompilerIfNecessary
import org.jetbrains.kotlin.idea.configuration.ui.notifications.notifyKotlinStyleUpdateIfNeeded
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import java.util.concurrent.atomic.AtomicInteger
class KotlinConfigurationCheckerComponent(val project: Project) : ProjectComponent {
private val syncDepth = AtomicInteger()
init {
NotificationsConfiguration.getNotificationsConfiguration()
.register(CONFIGURE_NOTIFICATION_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
val connection = project.messageBus.connect()
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
notifyOutdatedBundledCompilerIfNecessary(project)
})
notifyKotlinStyleUpdateIfNeeded(project)
}
override fun projectOpened() {
super.projectOpened()
StartupManager.getInstance(project).registerPostStartupActivity {
performProjectPostOpenActions()
}
}
fun performProjectPostOpenActions() {
ApplicationManager.getApplication().executeOnPooledThread {
val modulesWithKotlinFiles = project.runReadActionInSmartMode {
getModulesWithKotlinFiles(project)
}
for (module in modulesWithKotlinFiles) {
runReadAction {
if (project.isDisposed) return@runReadAction
module.getAndCacheLanguageLevelByDependencies()
}
}
}
}
val isSyncing: Boolean get() = syncDepth.get() > 0
fun syncStarted() {
syncDepth.incrementAndGet()
}
fun syncDone() {
syncDepth.decrementAndGet()
}
companion object {
const val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project"
fun getInstanceIfNotDisposed(project: Project): KotlinConfigurationCheckerComponent? {
return runReadAction {
if (!project.isDisposed) {
project.getComponent(KotlinConfigurationCheckerComponent::class.java)
?: error("Can't find ${KotlinConfigurationCheckerComponent::class} component")
} else {
null
}
}
}
}
class KotlinConfigurationCheckerComponent {
}
@@ -0,0 +1,97 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration.ui
import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationsConfiguration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
import org.jetbrains.kotlin.idea.configuration.notifyOutdatedBundledCompilerIfNecessary
import org.jetbrains.kotlin.idea.configuration.ui.notifications.notifyKotlinStyleUpdateIfNeeded
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import java.util.concurrent.atomic.AtomicInteger
typealias KotlinConfigurationCheckerService = KotlinConfigurationCheckerComponent
class KotlinConfigurationCheckerComponent(val project: Project) : ProjectComponent {
private val syncDepth = AtomicInteger()
init {
NotificationsConfiguration.getNotificationsConfiguration()
.register(CONFIGURE_NOTIFICATION_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
val connection = project.messageBus.connect()
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
notifyOutdatedBundledCompilerIfNecessary(project)
})
notifyKotlinStyleUpdateIfNeeded(project)
}
override fun projectOpened() {
super.projectOpened()
StartupManager.getInstance(project).registerPostStartupActivity {
performProjectPostOpenActions()
}
}
fun performProjectPostOpenActions() {
ApplicationManager.getApplication().executeOnPooledThread {
val modulesWithKotlinFiles = project.runReadActionInSmartMode {
getModulesWithKotlinFiles(project)
}
for (module in modulesWithKotlinFiles) {
runReadAction {
if (project.isDisposed) return@runReadAction
module.getAndCacheLanguageLevelByDependencies()
}
}
}
}
val isSyncing: Boolean get() = syncDepth.get() > 0
fun syncStarted() {
syncDepth.incrementAndGet()
}
fun syncDone() {
syncDepth.decrementAndGet()
}
companion object {
const val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project"
fun getInstanceIfNotDisposed(project: Project): KotlinConfigurationCheckerComponent? {
return runReadAction {
if (!project.isDisposed) {
project.getComponent(KotlinConfigurationCheckerComponent::class.java)
?: error("Can't find ${KotlinConfigurationCheckerComponent::class} component")
} else {
null
}
}
}
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration.ui
import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationsConfiguration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
import org.jetbrains.kotlin.idea.configuration.notifyOutdatedBundledCompilerIfNecessary
import org.jetbrains.kotlin.idea.configuration.ui.notifications.notifyKotlinStyleUpdateIfNeeded
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import java.util.concurrent.atomic.AtomicInteger
class KotlinConfigurationCheckerStartupActivity : StartupActivity.DumbAware {
override fun runActivity(project: Project) {
NotificationsConfiguration.getNotificationsConfiguration()
.register(
KotlinConfigurationCheckerService.CONFIGURE_NOTIFICATION_GROUP_ID,
NotificationDisplayType.STICKY_BALLOON, true
)
val connection = project.messageBus.connect(project)
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
notifyOutdatedBundledCompilerIfNecessary(project)
})
notifyKotlinStyleUpdateIfNeeded(project)
KotlinConfigurationCheckerService.getInstanceIfNotDisposed(project)?.performProjectPostOpenActions()
}
}
class KotlinConfigurationCheckerService(val project: Project) {
private val syncDepth = AtomicInteger()
fun performProjectPostOpenActions() {
ApplicationManager.getApplication().executeOnPooledThread {
val modulesWithKotlinFiles = project.runReadActionInSmartMode {
getModulesWithKotlinFiles(project)
}
for (module in modulesWithKotlinFiles) {
runReadAction {
if (project.isDisposed) return@runReadAction
module.getAndCacheLanguageLevelByDependencies()
}
}
}
}
val isSyncing: Boolean get() = syncDepth.get() > 0
fun syncStarted() {
syncDepth.incrementAndGet()
}
fun syncDone() {
syncDepth.decrementAndGet()
}
companion object {
const val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project"
fun getInstanceIfNotDisposed(project: Project): KotlinConfigurationCheckerService? {
return runReadAction {
if (!project.isDisposed) {
project.getService(KotlinConfigurationCheckerService::class.java)
?: error("Can't find ${KotlinConfigurationCheckerService::class} service")
} else {
null
}
}
}
}
}
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator
import org.jetbrains.kotlin.idea.configuration.getConfigurationPossibilitiesForConfigureNotification
import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerService
import javax.swing.event.HyperlinkEvent
data class ConfigureKotlinNotificationState(
@@ -28,7 +28,7 @@ class ConfigureKotlinNotification(
excludeModules: List<Module>,
val notificationState: ConfigureKotlinNotificationState
) : Notification(
KotlinConfigurationCheckerComponent.CONFIGURE_NOTIFICATION_GROUP_ID, KotlinJvmBundle.message("configure.kotlin"),
KotlinConfigurationCheckerService.CONFIGURE_NOTIFICATION_GROUP_ID, KotlinJvmBundle.message("configure.kotlin"),
notificationState.notificationString,
NotificationType.WARNING,
NotificationListener { notification, event ->