mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[command-completion] IDEA-373902 new action: FileStructurePopup
GitOrigin-RevId: d33f62c80ea847f720a317d7a81d3cf0adb88947
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0029d5ce36
commit
a2b6337be8
@@ -1504,6 +1504,7 @@
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaGenerateConstructorCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaSurroundWithCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaSafeDeleteCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.command.commands.ViewStructureCompletionCommandProvider" order="last"/>
|
||||
|
||||
<weigher implementationClass="com.intellij.codeInsight.completion.LoggerWeigher" key="completion" id="logger"/>
|
||||
|
||||
|
||||
@@ -584,6 +584,7 @@ command.completion.psi.element.uncomment.block.text=Uncomment
|
||||
command.completion.copy.reference.description=Copy reference for ''{0}''
|
||||
command.completion.copy.reference.text=Copy reference
|
||||
command.completion.comment.line.with.line.comment.text=Comment line with line comment
|
||||
command.completion.view.structure.text=Go to members
|
||||
command.completion.GotoDeclaration.text=Go to declaration
|
||||
command.completion.surround.with.text=Surround with ''{0}''
|
||||
options.command.completion.display.name=Command Completion
|
||||
|
||||
@@ -388,6 +388,9 @@ c:com.intellij.codeInsight.actions.VcsFacade
|
||||
- *sf:Companion:com.intellij.codeInsight.completion.command.commands.IntentionCommandSkipper$Companion
|
||||
- skip(com.intellij.codeInsight.intention.CommonIntentionAction,com.intellij.psi.PsiFile,I):Z
|
||||
*f:com.intellij.codeInsight.completion.command.commands.IntentionCommandSkipper$Companion
|
||||
*f:com.intellij.codeInsight.completion.command.commands.ViewStructureCompletionCommandProvider
|
||||
- com.intellij.codeInsight.completion.command.commands.ActionCommandProvider
|
||||
- <init>():V
|
||||
*:com.intellij.codeInsight.daemon.impl.focusMode.FocusModeProvider
|
||||
- a:calcFocusZones(com.intellij.psi.PsiFile):java.util.List
|
||||
*:com.intellij.codeInsight.editorActions.TypingActionsExtension
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ internal class CommandInsertHandler(private val completionCommand: CompletionCom
|
||||
startOffset)
|
||||
|
||||
// Remove the command text after the dots
|
||||
var commandStart = startOffset - actualIndex
|
||||
var commandStart = 0.coerceAtLeast(startOffset - actualIndex)
|
||||
|
||||
// Delete from commandStart to tailOffset
|
||||
document.deleteString(commandStart, tailOffset)
|
||||
|
||||
+3
-1
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.util.SlowOperations
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.util.Locale.getDefault
|
||||
import javax.swing.Icon
|
||||
@@ -166,7 +167,8 @@ open class ActionCompletionCommand(
|
||||
if (it.isLowerCase()) it.titlecase(getDefault()) else it.toString()
|
||||
}
|
||||
|
||||
private val action: AnAction? = ActionManager.getInstance().getAction(actionId)
|
||||
@ApiStatus.Internal
|
||||
protected open val action: AnAction? = ActionManager.getInstance().getAction(actionId)
|
||||
|
||||
override val additionalInfo: String?
|
||||
get() {
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.command.commands
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.completion.command.CommandCompletionProviderContext
|
||||
import com.intellij.ide.actions.ViewStructureAction
|
||||
import com.intellij.ide.structureView.impl.common.PsiTreeElementBase
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
class ViewStructureCompletionCommandProvider : ActionCommandProvider(actionId = "FileStructurePopup", synonyms = listOf("File Structure", "Go to members", "Show structure"), presentableName = CodeInsightBundle.message("command.completion.view.structure.text"), priority = -150, previewText = ActionsBundle.message("action.FileStructurePopup.description")) {
|
||||
|
||||
override fun createCommand(context: CommandCompletionProviderContext): ActionCompletionCommand {
|
||||
return object : ActionCompletionCommand(actionId = super.actionId, presentableActionName = super.presentableName, icon = super.icon, priority = super.priority, previewText = super.previewText, synonyms = super.synonyms) {
|
||||
override val action: AnAction
|
||||
get() = ViewStructureAction { node: AbstractTreeNode<*> ->
|
||||
val psiTreeElementBase = node.getValue() as? PsiTreeElementBase<*> ?: return@ViewStructureAction
|
||||
val psiElement = psiTreeElementBase.element ?: return@ViewStructureAction
|
||||
if (!psiElement.isPhysical) return@ViewStructureAction
|
||||
if (!psiElement.isValid) return@ViewStructureAction
|
||||
if (psiElement !is PsiNameIdentifierOwner) return@ViewStructureAction
|
||||
val endOffset = psiElement.nameIdentifier?.textRange?.endOffset ?: return@ViewStructureAction
|
||||
val project = context.project
|
||||
val selectedTextEditor = FileEditorManager.getInstance(project).selectedTextEditor ?: return@ViewStructureAction
|
||||
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.document) ?: return@ViewStructureAction
|
||||
if (!PsiTreeUtil.isAncestor(psiFile, psiElement, false)) return@ViewStructureAction
|
||||
selectedTextEditor.caretModel.moveToOffset(endOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.ide.structureView.logical.PhysicalAndLogicalStructureViewBuilder;
|
||||
import com.intellij.ide.structureView.StructureView;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.structureView.StructureViewModel;
|
||||
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
|
||||
import com.intellij.ide.structureView.impl.StructureViewComposite;
|
||||
import com.intellij.ide.structureView.logical.PhysicalAndLogicalStructureViewBuilder;
|
||||
import com.intellij.ide.util.FileStructurePopup;
|
||||
import com.intellij.ide.util.FileStructurePopupListener;
|
||||
import com.intellij.ide.util.StructureViewCompositeModel;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.ide.util.treeView.smartTree.TreeStructureUtil;
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
@@ -29,16 +30,27 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.PlaceHolder;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ViewStructureAction extends DumbAwareAction {
|
||||
|
||||
@Nullable
|
||||
private final Consumer<AbstractTreeNode<?>> myCallbackAfterNavigation;
|
||||
|
||||
public ViewStructureAction() {
|
||||
setEnabledInModalContext(true);
|
||||
myCallbackAfterNavigation = null;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ViewStructureAction(@Nullable Consumer<AbstractTreeNode<?>> callbackAfterNavigation) {
|
||||
myCallbackAfterNavigation = callbackAfterNavigation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +67,7 @@ public final class ViewStructureAction extends DumbAwareAction {
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
|
||||
}
|
||||
|
||||
FileStructurePopup popup = createPopup(project, fileEditor);
|
||||
FileStructurePopup popup = createPopup(project, fileEditor, myCallbackAfterNavigation);
|
||||
if (popup == null) return;
|
||||
|
||||
String title = virtualFile == null ? fileEditor.getName() : virtualFile.getName();
|
||||
@@ -64,6 +76,13 @@ public final class ViewStructureAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
public static @Nullable FileStructurePopup createPopup(@NotNull Project project, @NotNull FileEditor fileEditor) {
|
||||
return createPopup(project, fileEditor, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static @Nullable FileStructurePopup createPopup(@NotNull Project project,
|
||||
@NotNull FileEditor fileEditor,
|
||||
@Nullable Consumer<AbstractTreeNode<?>> callbackAfterNavigation) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
StructureViewBuilder builder = fileEditor.getStructureViewBuilder();
|
||||
if (builder == null) return null;
|
||||
@@ -83,10 +102,9 @@ public final class ViewStructureAction extends DumbAwareAction {
|
||||
treeModel = createStructureViewModel(project, fileEditor, structureView);
|
||||
}
|
||||
if (treeModel instanceof PlaceHolder) {
|
||||
//noinspection unchecked
|
||||
((PlaceHolder)treeModel).setPlace(TreeStructureUtil.PLACE);
|
||||
}
|
||||
FileStructurePopup popup = new FileStructurePopup(project, fileEditor, treeModel);
|
||||
FileStructurePopup popup = new FileStructurePopup(project, fileEditor, treeModel, callbackAfterNavigation);
|
||||
if (structureView != null) Disposer.register(popup, structureView);
|
||||
return popup;
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@ import com.intellij.util.ui.*;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.annotations.*;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
@@ -88,10 +85,11 @@ import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.event.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -131,12 +129,24 @@ public final class FileStructurePopup implements Disposable, TreeActionsOwner {
|
||||
private boolean myCanClose = true;
|
||||
private boolean myDisposed;
|
||||
|
||||
@Nullable
|
||||
private final Consumer<AbstractTreeNode<?>> myCallbackAfterNavigation;
|
||||
|
||||
public FileStructurePopup(@NotNull Project project,
|
||||
@NotNull FileEditor fileEditor,
|
||||
@NotNull StructureViewModel treeModel) {
|
||||
this(project, fileEditor, treeModel, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public FileStructurePopup(@NotNull Project project,
|
||||
@NotNull FileEditor fileEditor,
|
||||
@NotNull StructureViewModel treeModel,
|
||||
@Nullable Consumer<AbstractTreeNode<?>> callbackAfterNavigation) {
|
||||
myProject = project;
|
||||
myFileEditor = fileEditor;
|
||||
myTreeModel = treeModel;
|
||||
myCallbackAfterNavigation = callbackAfterNavigation;
|
||||
|
||||
//Stop code analyzer to speed up the EDT
|
||||
DaemonCodeAnalyzer.getInstance(myProject).disableUpdateByTimer(this);
|
||||
@@ -697,6 +707,9 @@ public final class FileStructurePopup implements Disposable, TreeActionsOwner {
|
||||
if (selectedNode != null) {
|
||||
if (selectedNode.canNavigateToSource()) {
|
||||
selectedNode.navigate(true);
|
||||
if (myCallbackAfterNavigation != null) {
|
||||
myCallbackAfterNavigation.accept(selectedNode);
|
||||
}
|
||||
myPopup.cancel();
|
||||
succeeded.set(true);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinQuickDocumentationCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinSurroundWithCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinSafeDeleteCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="com.intellij.codeInsight.completion.command.commands.ViewStructureCompletionCommandProvider" order="last"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
Reference in New Issue
Block a user