IDEA-337454 introduce internal API actions(canReturnStub: Boolean): Sequence<AnAction>

GitOrigin-RevId: a5e5a814bb81fbc2c17def3f271c9e3990f6a172
This commit is contained in:
Vladimir Krivosheev
2023-11-23 07:18:37 +01:00
committed by intellij-monorepo-bot
parent e0d4501336
commit 87cdcf6070
8 changed files with 105 additions and 85 deletions

View File

@@ -285,17 +285,13 @@ public final class TraverseUIStarter implements ApplicationStarter {
}
private static @NotNull Map<String, Set<OptionDescription>> processKeymap(boolean splitByResourcePath) {
Map<String, Set<OptionDescription>> map = new HashMap<>();
Map<String, Set<OptionDescription>> map = new LinkedHashMap<>();
ActionManagerImpl actionManager = (ActionManagerImpl)ActionManager.getInstance();
Map<String, PluginId> actionToPluginId = splitByResourcePath ? getActionToPluginId() : Collections.emptyMap();
String componentName = "ActionManager";
SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance();
for (String id : actionManager.getActionIds()) {
AnAction action = actionManager.getAction(id);
if (action == null) {
throw new IllegalStateException("Cannot find action by id " + id);
}
for (Iterator<AnAction> iterator = actionManager.actions(false).iterator(); iterator.hasNext(); ) {
AnAction action = iterator.next();
String module = splitByResourcePath ? getModuleByAction(action, actionToPluginId) : "";
Set<OptionDescription> options = map.computeIfAbsent(module, __ -> new TreeSet<>());
String text = action.getTemplatePresentation().getText();

View File

@@ -37,7 +37,7 @@ private val LOG = logger<ActionAsyncProvider>()
@OptIn(ExperimentalCoroutinesApi::class)
class ActionAsyncProvider(private val myModel: GotoActionModel) {
private val myActionManager: ActionManager = ActionManager.getInstance()
private val actionManager: ActionManager = ActionManager.getInstance()
private val myIntentions = ConcurrentHashMap<String, ApplyIntentionAction>()
fun processActions(scope: CoroutineScope, presentationProvider: suspend (AnAction) -> Presentation, pattern: String,
@@ -68,7 +68,7 @@ class ActionAsyncProvider(private val myModel: GotoActionModel) {
LOG.debug("Start actions searching ($pattern)")
val actionIds = (myActionManager as ActionManagerImpl).actionIds
val actionIds = (actionManager as ActionManagerImpl).actionIds
val comparator: Comparator<MatchedValue> = Comparator { o1, o2 -> o1.compareWeights(o2) }
@@ -180,7 +180,7 @@ class ActionAsyncProvider(private val myModel: GotoActionModel) {
return allIds.asFlow()
.mapNotNull {
val action = myActionManager.getActionOrStub(it) ?: return@mapNotNull null
val action = actionManager.getActionOrStub(it) ?: return@mapNotNull null
if (action is ActionGroup && !action.isSearchable) return@mapNotNull null
action
}

View File

@@ -2,7 +2,6 @@
package com.intellij.platform.ml.embeddings.search.services
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl
import com.intellij.openapi.application.ApplicationManager
@@ -112,13 +111,12 @@ class ActionEmbeddingsStorage(private val cs: CoroutineScope) : AbstractEmbeddin
private suspend fun checkSearchEnabled() = serviceAsync<SemanticSearchSettings>().enabledInActionsTab
private fun shouldIndexAction(action: AnAction?): Boolean {
return action != null && !(action is ActionGroup && !action.isSearchable) && action.templatePresentation.hasText()
private fun shouldIndexAction(action: AnAction): Boolean {
return !(action is ActionGroup && !action.isSearchable) && action.templatePresentation.hasText()
}
internal suspend fun getIndexableActionIds(): Set<String> {
val actionManager = (serviceAsync<ActionManager>() as ActionManagerImpl)
return actionManager.actionIds.filterTo(LinkedHashSet()) { shouldIndexAction(actionManager.getActionOrStub(it)) }
internal fun getIndexableActions(actionManager: ActionManagerImpl): Set<AnAction> {
return actionManager.actions(canReturnStub = true).filterTo(LinkedHashSet()) { shouldIndexAction(it) }
}
}
}

View File

@@ -1,41 +1,49 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.ml.embeddings.search.services
import com.intellij.platform.ml.embeddings.services.LocalEmbeddingServiceProvider
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl
import com.intellij.openapi.components.serviceAsync
import com.intellij.platform.ml.embeddings.search.indices.EmbeddingSearchIndex
import com.intellij.platform.ml.embeddings.services.LocalEmbeddingServiceProvider
import com.intellij.platform.ml.embeddings.utils.normalized
import com.intellij.platform.util.progress.durationStep
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicReference
class ActionEmbeddingsStorageSetup(
internal class ActionEmbeddingsStorageSetup(
private val index: EmbeddingSearchIndex,
private val indexSetupJob: AtomicReference<Job>
) {
private var shouldSaveToDisk = false
suspend fun run() = coroutineScope {
val indexableActionIds = ActionEmbeddingsStorage.getIndexableActionIds()
val actionManager = (serviceAsync<ActionManager>() as ActionManagerImpl)
val embeddingService = LocalEmbeddingServiceProvider.getInstance().getService() ?: return@coroutineScope
val indexableActions = ActionEmbeddingsStorage.getIndexableActions(actionManager)
val embeddingService = serviceAsync<LocalEmbeddingServiceProvider>().getService() ?: return@coroutineScope
// Cancel the previous embeddings calculation task if it's not finished
indexSetupJob.getAndSet(launch {
var indexedActionsCount = 0
val totalIndexableActionsCount = indexableActionIds.size
val totalIndexableActionsCount = indexableActions.size
val actionManager = ActionManager.getInstance() as ActionManagerImpl
index.onIndexingStart()
indexableActionIds
indexableActions
.asSequence()
.filter { it !in index }
.map { it to actionManager.getActionOrStub(it) }
.filter { (_, action) -> action != null && action.templateText != null }
.mapNotNull {
val id = actionManager.getId(it)
if (id == null || index.contains(id)) {
null
}
else {
id to it
}
}
.chunked(BATCH_SIZE)
.forEach { batch ->
val actionIds = batch.map { (id, _) -> id }
val texts = batch.map { (_, action) -> action!!.templateText!! }
val texts = batch.map { (_, action) -> action.templateText!! }
durationStep(texts.size.toDouble() / totalIndexableActionsCount) {
val embeddings = embeddingService.embed(texts).map { it.normalized() }

View File

@@ -194,25 +194,28 @@ public final class ActionUpdatesBenchmarkAction extends DumbAwareAction {
Set<String> nonUniqueClasses = new HashSet<>();
{
Set<String> visited = new HashSet<>();
for (String id : actionManager.getActionIds()) {
AnAction action = actionManager.getAction(id);
if (action == null) continue;
if (action.getClass() == DefaultActionGroup.class) continue;
for (Iterator<AnAction> it = actionManager.actions(false).iterator(); it.hasNext(); ) {
AnAction action = it.next();
if (action.getClass() == DefaultActionGroup.class) {
continue;
}
String className = action.getClass().getName();
if (!visited.add(className)) nonUniqueClasses.add(className);
if (!visited.add(className)) {
nonUniqueClasses.add(className);
}
}
}
int count = 0;
long startActions = System.nanoTime();
for (String id : actionManager.getActionIds()) {
AnAction action = actionManager.getAction(id);
if (action == null) {
LOG.warn("no action for id: " + id);
for (Iterator<AnAction> it = actionManager.actions(false).iterator(); it.hasNext(); ) {
AnAction action = it.next();
if (action.getClass() == DefaultActionGroup.class || isDumb && !DumbService.isDumbAware(action)) {
continue;
}
if (action.getClass() == DefaultActionGroup.class) continue;
if (isDumb && !DumbService.isDumbAware(action)) continue;
String id = actionManager.getId(action);
String className = action.getClass().getName();
String actionIdIfNeeded = nonUniqueClasses.contains(className) ? " (" + id + ")" : "";
String actionName = className + actionIdIfNeeded;
@@ -240,15 +243,18 @@ public final class ActionUpdatesBenchmarkAction extends DumbAwareAction {
ActionManagerImpl actionManager = (ActionManagerImpl)ActionManager.getInstance();
int[] actionUpdateThreadCounts = new int[ActionUpdateThread.values().length];
List<String> oldEdtActionNames = new ArrayList<>();
for (String id : actionManager.getActionIds()) {
AnAction action = actionManager.getAction(id);
if (action == null) continue;
if (action.getClass() == DefaultActionGroup.class) continue;
for (Iterator<AnAction> it = actionManager.actions(false).iterator(); it.hasNext(); ) {
AnAction action = it.next();
if (action.getClass() == DefaultActionGroup.class) {
continue;
}
ActionUpdateThread updateThread = action.getActionUpdateThread();
actionUpdateThreadCounts[updateThread.ordinal()]++;
if (updateThread == ActionUpdateThread.OLD_EDT) {
String className = action.getClass().getName();
String actionIdIfNeeded = nonUniqueClasses.contains(className) ? " (" + id + ")" : "";
String actionIdIfNeeded = nonUniqueClasses.contains(className) ? " (" + actionManager.getId(action) + ")" : "";
String actionName = className + actionIdIfNeeded;
oldEdtActionNames.add(actionName);
}

View File

@@ -60,8 +60,6 @@ import com.intellij.util.ReflectionUtil
import com.intellij.util.childScope
import com.intellij.util.concurrency.*
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.with
import com.intellij.util.containers.without
import com.intellij.util.ui.StartupUiUtil.addAwtListener
import com.intellij.util.xml.dom.XmlElement
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
@@ -127,7 +125,7 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C
ThreadingAssertions.assertBackgroundThread()
}
val idToAction = HashMap<String, AnAction>(5_000, 0.5f)
val idToAction = LinkedHashMap<String, AnAction>(5_000, 0.5f)
val actionPreInitRegistrar = ActionPreInitRegistrar(idToAction)
doRegisterActions(PluginManagerCore.getPluginSet().getEnabledModules(), actionRegistrar = actionPreInitRegistrar)
@@ -230,11 +228,15 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C
}
override fun createActionToolbar(place: String, group: ActionGroup, horizontal: Boolean): ActionToolbar {
return createActionToolbar(place, group, horizontal, false, true)
return createActionToolbar(place = place, group = group, horizontal = horizontal, decorateButtons = false, customizable = true)
}
override fun createActionToolbar(place: String, group: ActionGroup, horizontal: Boolean, decorateButtons: Boolean): ActionToolbar {
return createActionToolbarImpl(place, group, horizontal, decorateButtons, false)
return createActionToolbarImpl(place = place,
group = group,
horizontal = horizontal,
decorateButtons = decorateButtons,
customizable = false)
}
override fun createActionToolbar(place: String,
@@ -1264,6 +1266,20 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C
val actionIds: Set<String>
get() = actionPostInitRegistrar.ids
@Internal
fun actions(canReturnStub: Boolean): Sequence<AnAction> {
if (canReturnStub) {
// return snapshot
return actionPostInitRegistrar.actions.asSequence()
}
else {
return actionPostInitRegistrar.ids.asSequence()
.mapNotNull {
doGetAction(id = it, canReturnStub = false, actionRegistrar = actionPostInitRegistrar)
}
}
}
@TestOnly
fun preloadActions() {
for (id in actionPostInitRegistrar.ids) {
@@ -1901,22 +1917,37 @@ private sealed interface ActionRegistrar {
fun getAction(id: String): AnAction?
}
private class ActionPostInitRegistrar(@Volatile private var idToAction: Map<String, AnAction>) : ActionRegistrar {
private class ActionPostInitRegistrar(@Volatile private var idToAction: LinkedHashMap<String, AnAction>) : ActionRegistrar {
val ids: Set<String>
get() = idToAction.keys
override val isPostInit: Boolean
get() = true
/**
* Stub actions here! Don't use it blindly.
*/
val actions: Collection<AnAction>
get() = idToAction.values
override fun putAction(actionId: String, action: AnAction) {
idToAction = idToAction.with(actionId, action)
val oldMap = idToAction
val result = LinkedHashMap<String, AnAction>(oldMap.size + 1)
result.putAll(oldMap)
result.put(actionId, action)
idToAction = result
}
override fun removeAction(actionId: String) {
idToAction = idToAction.without(actionId)
val oldMap = idToAction
if (!oldMap.containsKey(actionId)) {
return
}
val result = LinkedHashMap<String, AnAction>(oldMap.size, 0.5f)
result.putAll(oldMap)
result.remove(actionId)
idToAction = result
}
override fun getAction(id: String) = idToAction.get(id)
@@ -1928,7 +1959,7 @@ private class ActionPostInitRegistrar(@Volatile private var idToAction: Map<Stri
fun actionsOrStubs(): Sequence<AnAction> = idToAction.values.asSequence()
}
private class ActionPreInitRegistrar(private val idToAction: MutableMap<String, AnAction>) : ActionRegistrar {
private class ActionPreInitRegistrar(private val idToAction: LinkedHashMap<String, AnAction>) : ActionRegistrar {
override val isPostInit: Boolean
get() = false

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.actions;
import com.intellij.openapi.actionSystem.*;
@@ -8,6 +8,7 @@ import com.intellij.openapi.actionSystem.impl.Utils;
import com.intellij.testFramework.LightPlatformTestCase;
import java.util.ArrayList;
import java.util.Iterator;
public class ActionsWithBrokenUpdateMethodTest extends LightPlatformTestCase {
public void testActionsUpdateMethods() {
@@ -21,13 +22,8 @@ public class ActionsWithBrokenUpdateMethodTest extends LightPlatformTestCase {
Utils.initUpdateSession(event2);
ArrayList<String> failed = new ArrayList<>();
for (String id : actionManager.getActionIds()) {
AnAction action = actionManager.getAction(id);
if (action == null) {
failed.add("Can't find action: " + id);
continue;
}
for (Iterator<AnAction> iterator = actionManager.actions(false).iterator(); iterator.hasNext(); ) {
AnAction action = iterator.next();
// check invalid getRequiredData usages
try {
action.update(event1);
@@ -41,7 +37,7 @@ public class ActionsWithBrokenUpdateMethodTest extends LightPlatformTestCase {
}
catch (Throwable e) {
e.printStackTrace();
failed.add(String.format("%s (%s): %s", id, action.getClass().getName(), e.getMessage()));
failed.add(String.format("%s (%s): %s", actionManager.getId(action), action.getClass().getName(), e.getMessage()));
}
}

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.actions;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -25,8 +11,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class ActionsWithInvalidTemplatePresentationTest extends LightPlatformTestCase {
private static final List<String> KNOWN_FALSE_POSITIVES = Arrays.asList(
@@ -35,16 +21,15 @@ public class ActionsWithInvalidTemplatePresentationTest extends LightPlatformTes
);
public void testActionsPresentations() {
ActionManagerImpl mgr = (ActionManagerImpl)ActionManager.getInstance();
ActionManagerImpl actionManager = (ActionManagerImpl)ActionManager.getInstance();
Set<String> ids = mgr.getActionIds();
List<String> failed = new ArrayList<>();
for (String id : ids) {
if (KNOWN_FALSE_POSITIVES.contains(id)) continue;
AnAction action = mgr.getActionOrStub(id);
if (action == null) fail("Can't find action: " + id);
for (Iterator<AnAction> it = actionManager.actions(true).iterator(); it.hasNext(); ) {
AnAction action = it.next();
String id = actionManager.getId(action);
if (KNOWN_FALSE_POSITIVES.contains(id)) {
continue;
}
Presentation presentation = action.getTemplatePresentation();
String text = presentation.getText();