如何从自定义 ToolWindow 调用 IntelliJ 重命名重构?
How to invoke IntelliJ rename refactor from custom ToolWindow?
我正在开发一个有自己工具的 IntelliJ 插件 window。当用户按下某个键时,该插件应调用 IntelliJ 的内置重命名重构函数来重命名变量。当我 运行 我的示例时,当我按下一个键来调用重命名重构函数时抛出以下异常:
2020-05-16 23:03:17,741 [ 41062] ERROR - llij.ide.plugins.PluginManager - EventQueue.isDispatchThread()=false Toolkit.getEventQueue()=com.intellij.ide.IdeEventQueue@574ed46a
Current thread: Thread[JavaFX Application Thread,6,Idea Thread Group] 648578026
Write thread (volatile): Thread[AWT-EventQueue-0,6,Idea Thread Group] 807407917com.intellij.openapi.diagnostic.Attachment@339b1167
com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: EventQueue.isDispatchThread()=false Toolkit.getEventQueue()=com.intellij.ide.IdeEventQueue@574ed46a
Current thread: Thread[JavaFX Application Thread,6,Idea Thread Group] 648578026
Write thread (volatile): Thread[AWT-EventQueue-0,6,Idea Thread Group] 807407917com.intellij.openapi.diagnostic.Attachment@339b1167
at com.intellij.openapi.application.impl.ApplicationImpl.assertIsWriteThread(ApplicationImpl.java:1068)
at com.intellij.openapi.application.impl.ApplicationImpl.startWrite(ApplicationImpl.java:1154)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:974)
at MyToolWindowFactory.handle(MyToolWindowFactory.java:55)
at MyToolWindowFactory.handle(MyToolWindowFactory.java:17)
我认为在 ApplicationManager.getApplication().runWriteAction
中调用 setName
函数作为 lambda 会起作用,但显然不行。我怎样才能让它工作?
这是我使用的完整代码。
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.psi.*;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class MyToolWindowFactory implements ToolWindowFactory, EventHandler<KeyEvent> {
PsiField[] variables;
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
final JFXPanel fxPanel = new JFXPanel();
JComponent component = toolWindow.getComponent();
ApplicationManager.getApplication().invokeLater(() -> {
PsiClass currentClass = getCurrentClass(project);
variables = currentClass.getFields();
Scene scene = new Scene(new VBox(), 400, 250);
scene.setOnKeyPressed(this);
fxPanel.setScene(scene);
fxPanel.requestFocus();
});
component.getParent().add(fxPanel);
}
private PsiClass getCurrentClass(Project project) {
// Get the currently selected file.
FileEditorManager manager = FileEditorManager.getInstance(project);
VirtualFile[] files = manager.getSelectedFiles();
VirtualFile currentFile = files[0];
// Get the PsiClass for the currently selected file.
PsiFile psiFile = PsiManager.getInstance(project).findFile(currentFile);
PsiJavaFile psiJavaFile = (PsiJavaFile)psiFile;
final PsiClass[] classes = psiJavaFile.getClasses();
return classes[0];
}
@Override
public void handle(KeyEvent event) {
ApplicationManager.getApplication().runWriteAction(() -> {
variables[0].setName("newVariableName");
});
}
}
让它工作的一种方法是从 WriteCommandAction.runWriteCommandAction
方法调用重命名函数。此外,仅调用 setName
只会重命名变量声明。为了重命名对变量的所有引用,我首先使用 ReferencesSearch.search
方法搜索所有变量的引用,然后在每个引用上调用 handleElementRename
。
public void handle(KeyEvent event) {
Runnable r = ()->
{
for (PsiReference reference : ReferencesSearch.search(variables[0])) {
reference.handleElementRename(variableName);
}
variables[0].setName(variableName);
}
WriteCommandAction.runWriteCommandAction(project, r);
}
从这里得到使用 WriteCommandAction
的提示:
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206754235
我正在开发一个有自己工具的 IntelliJ 插件 window。当用户按下某个键时,该插件应调用 IntelliJ 的内置重命名重构函数来重命名变量。当我 运行 我的示例时,当我按下一个键来调用重命名重构函数时抛出以下异常:
2020-05-16 23:03:17,741 [ 41062] ERROR - llij.ide.plugins.PluginManager - EventQueue.isDispatchThread()=false Toolkit.getEventQueue()=com.intellij.ide.IdeEventQueue@574ed46a
Current thread: Thread[JavaFX Application Thread,6,Idea Thread Group] 648578026
Write thread (volatile): Thread[AWT-EventQueue-0,6,Idea Thread Group] 807407917com.intellij.openapi.diagnostic.Attachment@339b1167
com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: EventQueue.isDispatchThread()=false Toolkit.getEventQueue()=com.intellij.ide.IdeEventQueue@574ed46a
Current thread: Thread[JavaFX Application Thread,6,Idea Thread Group] 648578026
Write thread (volatile): Thread[AWT-EventQueue-0,6,Idea Thread Group] 807407917com.intellij.openapi.diagnostic.Attachment@339b1167
at com.intellij.openapi.application.impl.ApplicationImpl.assertIsWriteThread(ApplicationImpl.java:1068)
at com.intellij.openapi.application.impl.ApplicationImpl.startWrite(ApplicationImpl.java:1154)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:974)
at MyToolWindowFactory.handle(MyToolWindowFactory.java:55)
at MyToolWindowFactory.handle(MyToolWindowFactory.java:17)
我认为在 ApplicationManager.getApplication().runWriteAction
中调用 setName
函数作为 lambda 会起作用,但显然不行。我怎样才能让它工作?
这是我使用的完整代码。
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.psi.*;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class MyToolWindowFactory implements ToolWindowFactory, EventHandler<KeyEvent> {
PsiField[] variables;
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
final JFXPanel fxPanel = new JFXPanel();
JComponent component = toolWindow.getComponent();
ApplicationManager.getApplication().invokeLater(() -> {
PsiClass currentClass = getCurrentClass(project);
variables = currentClass.getFields();
Scene scene = new Scene(new VBox(), 400, 250);
scene.setOnKeyPressed(this);
fxPanel.setScene(scene);
fxPanel.requestFocus();
});
component.getParent().add(fxPanel);
}
private PsiClass getCurrentClass(Project project) {
// Get the currently selected file.
FileEditorManager manager = FileEditorManager.getInstance(project);
VirtualFile[] files = manager.getSelectedFiles();
VirtualFile currentFile = files[0];
// Get the PsiClass for the currently selected file.
PsiFile psiFile = PsiManager.getInstance(project).findFile(currentFile);
PsiJavaFile psiJavaFile = (PsiJavaFile)psiFile;
final PsiClass[] classes = psiJavaFile.getClasses();
return classes[0];
}
@Override
public void handle(KeyEvent event) {
ApplicationManager.getApplication().runWriteAction(() -> {
variables[0].setName("newVariableName");
});
}
}
让它工作的一种方法是从 WriteCommandAction.runWriteCommandAction
方法调用重命名函数。此外,仅调用 setName
只会重命名变量声明。为了重命名对变量的所有引用,我首先使用 ReferencesSearch.search
方法搜索所有变量的引用,然后在每个引用上调用 handleElementRename
。
public void handle(KeyEvent event) {
Runnable r = ()->
{
for (PsiReference reference : ReferencesSearch.search(variables[0])) {
reference.handleElementRename(variableName);
}
variables[0].setName(variableName);
}
WriteCommandAction.runWriteCommandAction(project, r);
}
从这里得到使用 WriteCommandAction
的提示:
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206754235