idea插件开发的第七天-开发一款数据格式化插件
idea插件开发的第七天-开发一款数据格式化插件。
·
写在前面
该插件基于Idea插件JTools开发JTools插件安装参考如下博客: call-this-method
创建项目
项目模板
修改gradle相关配置
gradle-wrapper.properties
#Sun Oct 06 09:40:43 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
build.gradle
plugins {
id 'org.jetbrains.intellij' version '1.10.1'
id 'java'
}
group = 'com.lhstack'
version = 'v1.0.0'
repositories {
mavenLocal()
maven {
url 'https://maven.aliyun.com/repository/public/'
}
mavenCentral()
}
intellij {
version.set("2022.1")
type.set("IC") // Target IDE Platform
plugins.set(["com.intellij.java", "org.jetbrains.plugins.yaml"])
}
tasks.withType(JavaCompile).configureEach {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
options.encoding = "UTF-8"
}
tasks.withType(JavaExec).configureEach {
jvmArgs("-Dfile.encoding=UTF-8")
}
dependencies {
testImplementation platform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
test {
useJUnitPlatform()
}
settings.gradle
pluginManagement {
repositories {
mavenLocal()
maven{
url 'https://maven.aliyun.com/repository/public/'
}
gradlePluginPortal()
}
}
rootProject.name = 'jtools-format'
安装插件sdk

高亮和build.gradle中出现以下依赖,即代表安装成功

创建插件实现


下载图标

pluginIcon在light主题下显示的图标
pluginIcon在dark主题下显示的图标
pluginTabIcon在dark主题下显示的图标
pluginTabIcon在light主题下显示的图标
代码中文件命名风格如下
在代码中使用图标

package com.lhstack.demo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.lhstack.tools.plugins.IPlugin;
import javax.swing.*;
public class PluginImpl implements IPlugin {
@Override
public Icon pluginIcon() {
return IconLoader.findIcon("format.svg",PluginImpl.class);
}
@Override
public Icon pluginTabIcon() {
return IconLoader.findIcon("format_tab.svg", PluginImpl.class);
}
@Override
public JComponent createPanel(Project project) {
return new JLabel("测试",JLabel.CENTER);
}
@Override
public String pluginName() {
return "格式化";
}
@Override
public String pluginDesc() {
return "这是一个任意数据结构格式化的插件";
}
@Override
public String pluginVersion() {
return "0.0.1";
}
}
打包安装,查看图标效果

拖拽到这个面板进行安装
安装成功和打开的效果如下图

在jtools开发模块运行查看效果

编写代码,实现格式化功能
DynamicLanguageTextField.java
package com.lhstack.demo;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.EditorSettings;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.ui.LanguageTextField;
import org.jetbrains.annotations.NotNull;
public class DynamicLanguageTextField extends LanguageTextField implements Disposable {
private final SimpleDocumentCreator documentCreator;
private LanguageFileType languageFileType;
public DynamicLanguageTextField(LanguageFileType languageFileType, Project project, String title) {
this(languageFileType, project, new SimpleDocumentCreator() {
@Override
public void customizePsiFile(PsiFile file) {
file.setName(title);
}
});
}
public DynamicLanguageTextField(LanguageFileType languageFileType, Project project) {
this(languageFileType, project, new SimpleDocumentCreator());
}
public DynamicLanguageTextField(LanguageFileType languageFileType, Project project, SimpleDocumentCreator documentCreator) {
super(languageFileType.getLanguage(), project, "", documentCreator, false);
this.documentCreator = documentCreator;
this.languageFileType = languageFileType;
}
public void changeLanguageFileType(LanguageFileType languageFileType) {
if (this.languageFileType != languageFileType) {
this.setNewDocumentAndFileType(languageFileType, this.documentCreator.createDocument(this.getDocument().getText(), languageFileType.getLanguage(), this.getProject()));
this.languageFileType = languageFileType;
Editor editor = this.getEditor();
if (editor instanceof EditorEx) {
EditorEx editorEx = (EditorEx) editor;
editorEx.setHighlighter(HighlighterFactory.createHighlighter(this.getProject(), this.languageFileType));
}
}
}
public LanguageFileType getLanguageFileType() {
return languageFileType;
}
@Override
protected @NotNull EditorEx createEditor() {
EditorEx editor = (EditorEx) EditorFactory.getInstance().createEditor(getDocument(), getProject(), languageFileType, false);
editor.setHorizontalScrollbarVisible(true);
editor.setVerticalScrollbarVisible(true);
editor.setHighlighter(HighlighterFactory.createHighlighter(this.getProject(), this.languageFileType));
PsiFile psiFile = PsiDocumentManager.getInstance(getProject()).getPsiFile(getDocument());
if (psiFile != null) {
DaemonCodeAnalyzer.getInstance(getProject()).setHighlightingEnabled(psiFile, true);
}
EditorSettings settings = editor.getSettings();
settings.setLineNumbersShown(true);
settings.setRightMarginShown(true);
settings.setAutoCodeFoldingEnabled(false);
settings.setLineMarkerAreaShown(false);
settings.setAdditionalColumnsCount(1);
settings.setRightMargin(-1);
settings.setLineCursorWidth(1);
settings.setAdditionalLinesCount(0);
settings.setFoldingOutlineShown(true);
Disposer.register(getProject(), () -> EditorFactory.getInstance().releaseEditor(editor));
return editor;
}
@Override
public void dispose() {
Editor editor = getEditor();
if (editor != null) {
EditorFactory.getInstance().releaseEditor(editor);
}
}
}
PluginImpl.java
package com.lhstack.demo;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.designer.actions.AbstractComboBoxAction;
import com.intellij.json.json5.Json5FileType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.lhstack.tools.plugins.IPlugin;
import org.apache.commons.collections.CollectionUtils;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.*;
public class PluginImpl implements IPlugin {
private static final Map<String, JComponent> cache = new HashMap<>();
private static final Map<String, Disposable> disposable = new HashMap<>();
private static final String ACTION_PLACE = "JTools-Format";
@Override
public JComponent createPanel(Project project) {
return cache.computeIfAbsent(project.getLocationHash(), key -> {
SimpleToolWindowPanel panel = new SimpleToolWindowPanel(true);
List<LanguageFileType> languageFileTypes = Arrays.stream(FileTypeManager.getInstance().getRegisteredFileTypes())
.filter(fileType -> fileType instanceof LanguageFileType)
.map(LanguageFileType.class::cast)
.toList();
if (CollectionUtils.isEmpty(languageFileTypes)) {
return new JLabel("没有可以支持的格式化类型", JLabel.CENTER);
}
DynamicLanguageTextField languageTextField = new DynamicLanguageTextField(Json5FileType.INSTANCE, project, "JTools-Format");
disposable.put(project.getLocationHash(), languageTextField);
//创建actionGroup
DefaultActionGroup actionGroup = new DefaultActionGroup();
//支持的格式化类型
AbstractComboBoxAction<LanguageFileType> comboBoxAction = new AbstractComboBoxAction<>() {
@Override
protected void update(LanguageFileType languageFileType, Presentation presentation, boolean b) {
presentation.setText(languageFileType.getDisplayName());
presentation.setIcon(languageFileType.getIcon());
}
@Override
protected boolean selectionChanged(LanguageFileType languageFileType) {
if (this.getSelection() != languageFileType) {
if (languageTextField.getLanguageFileType() != languageFileType) {
languageTextField.changeLanguageFileType(languageFileType);
Document document = languageTextField.getDocument();
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
psiDocumentManager.commitDocument(document);
PsiFile psiFile = psiDocumentManager.getPsiFile(document);
if (psiFile != null) {
new ReformatCodeProcessor(psiFile, false)
.run();
}
}
//需要重新格式化
return true;
}
return false;
}
};
comboBoxAction.setItems(languageFileTypes, Json5FileType.INSTANCE);
actionGroup.add(comboBoxAction);
//创建toolbar
ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ACTION_PLACE, actionGroup, true);
actionToolbar.setTargetComponent(panel);
//右对齐
JPanel toolbar = new JPanel(new BorderLayout());
toolbar.add(actionToolbar.getComponent(), BorderLayout.EAST);
panel.setToolbar(toolbar);
panel.setContent(languageTextField);
return panel;
});
}
@Override
public void closeProject(String locationHash) {
cache.remove(locationHash);
Optional.ofNullable(disposable.remove(locationHash)).ifPresent(Disposer::dispose);
}
@Override
public Icon pluginIcon() {
return IconLoader.findIcon("format.svg", PluginImpl.class);
}
@Override
public Icon pluginTabIcon() {
return IconLoader.findIcon("format_tab.svg", PluginImpl.class);
}
@Override
public String pluginName() {
return "格式化";
}
@Override
public String pluginDesc() {
return "这是一个任意数据结构格式化的插件";
}
@Override
public String pluginVersion() {
return "0.0.1";
}
}
在jtools开发模块运行查看效果

输入SQL,使用sql格式化

使用idea格式化快捷键格式化ctrl + alt + l

打包安装查看效果
卸载之前安装的插件
打包
按钮选择安装

双击打开

更多推荐




所有评论(0)