mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
IDEA-337454 introduce internal API actions(canReturnStub: Boolean): Sequence<AnAction>
GitOrigin-RevId: a5e5a814bb81fbc2c17def3f271c9e3990f6a172
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e0d4501336
commit
87cdcf6070
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user