diff --git a/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java index e5ac35c90e92..5c3c7e2dd381 100644 --- a/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java @@ -14,6 +14,7 @@ import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -183,11 +184,16 @@ public class ExecutionTargetManagerImpl extends ExecutionTargetManager implement boolean isCompound = settings.getConfiguration() instanceof CompoundRunConfiguration; if (isCompound && target == MULTIPLE_TARGETS) return true; + boolean useCache = ApplicationManager.getApplication().isInternal() || Registry.is("update.run.configuration.actions.from.cache"); + ExecutionTarget defaultTarget = DefaultExecutionTarget.INSTANCE; boolean checkFallbackToDefault = isCompound && !target.equals(defaultTarget); return doWithEachNonCompoundWithSpecifiedTarget(settings, each -> { + if (useCache && RunManagerImpl.getInstanceImpl(myProject).isInvalidInCache(each.first)) { + return false; + } RunConfiguration configuration = each.first.getConfiguration(); if (!(configuration instanceof TargetAwareRunProfile)) return true; TargetAwareRunProfile targetAwareProfile = (TargetAwareRunProfile)configuration; diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt index a3235be26921..fd9b3bc27723 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt @@ -852,6 +852,10 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi return icon } + fun isInvalidInCache(settings: RunnerAndConfigurationSettings): Boolean { + return iconCache.isInvalid(settings.uniqueID) + } + fun getConfigurationById(id: String): RunnerAndConfigurationSettings? = lock.read { idToSettings.get(id) } override fun findConfigurationByName(name: String?): RunnerAndConfigurationSettings? { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/TimedIconCache.kt b/platform/lang-impl/src/com/intellij/execution/impl/TimedIconCache.kt index 69eb4ed973ad..f21342e7d12d 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/TimedIconCache.kt +++ b/platform/lang-impl/src/com/intellij/execution/impl/TimedIconCache.kt @@ -17,6 +17,7 @@ import kotlin.concurrent.write class TimedIconCache { private val idToIcon = THashMap() + private val idToInvalid = THashMap() private val iconCheckTimes = ObjectLongHashMap() private val iconCalcTime = ObjectLongHashMap() @@ -35,7 +36,6 @@ class TimedIconCache { idToIcon.get(id)?.let { return it } - val icon = IconDeferrer.getInstance().deferAutoUpdatable(settings.configuration.icon, project.hashCode() xor settings.hashCode()) { if (project.isDisposed) { return@deferAutoUpdatable null @@ -47,13 +47,13 @@ class TimedIconCache { val startTime = System.currentTimeMillis() - val icon = calcIcon(settings, project) + val icon2Valid = calcIcon(settings, project) lock.write { iconCalcTime.put(id, System.currentTimeMillis() - startTime) + idToInvalid.set(id, icon2Valid.second) } - - icon + icon2Valid.first } set(id, icon) @@ -61,16 +61,22 @@ class TimedIconCache { } } - private fun calcIcon(settings: RunnerAndConfigurationSettings, project: Project): Icon { + fun isInvalid(id: String) : Boolean { + idToInvalid.get(id)?.let {return it} + return false + } + + private fun calcIcon(settings: RunnerAndConfigurationSettings, project: Project): Pair { try { settings.checkSettings() - return ProgramRunnerUtil.getConfigurationIcon(settings, false) + return ProgramRunnerUtil.getConfigurationIcon(settings, false).to(false) } catch (e: IndexNotReadyException) { - return ProgramRunnerUtil.getConfigurationIcon(settings, false) + return ProgramRunnerUtil.getConfigurationIcon(settings, false).to(false) } catch (ignored: RuntimeConfigurationException) { - return ProgramRunnerUtil.getConfigurationIcon(settings, !DumbService.isDumb(project)) + val invalid = !DumbService.isDumb(project) + return ProgramRunnerUtil.getConfigurationIcon(settings, invalid).to(invalid) } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index dab53e6a7b4e..3d0534bd5bae 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1357,6 +1357,8 @@ ide.require.transaction.for.model.changes.description=Whether write action can o select.run.configuration.from.context=true select.run.configuration.from.context.description=Select run configuration when run from context (gutter icon, popup menu) +update.run.configuration.actions.from.cache=true +update.run.configuration.actions.from.cache.description=Disable run actions on main toolbar if we have 'invalid' icon for it calculated recently in background run.configuration.max.name.length=80 run.configuration.max.name.length.description=When name of run configuration exceeds the limit it would be trimmed in UI like 'LongNamedRunCo...' suggest.all.run.configurations.from.context=false