写在前面

该插件基于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
在这里插入图片描述
在这里插入图片描述

打包安装查看效果

卸载之前安装的插件
在这里插入图片描述
打包
在这里插入图片描述
按钮选择安装
在这里插入图片描述
在这里插入图片描述
双击打开
在这里插入图片描述
在这里插入图片描述

Logo

一站式 AI 云服务平台

更多推荐