├── .gitignore
├── README.md
├── gradle.properties
├── idea-study-01
├── build.gradle
├── resources
│ ├── META-INF
│ │ ├── plugin.xml
│ │ ├── pluginIcon.svg
│ │ └── pluginIcon_dark.svg
│ ├── icons
│ │ ├── halo.png
│ │ └── right
│ │ │ ├── HaloBasic.png
│ │ │ ├── controller.png
│ │ │ └── mapper.png
│ └── templates
│ │ └── Controller.java.ftl
└── src
│ └── org
│ └── xujin
│ └── idea
│ └── right
│ ├── BasicActionOpenDialog.java
│ ├── BasicComBoxRenderer.java
│ ├── BasicCreateSelectInfoStep.form
│ ├── BasicCreateSelectInfoStep.java
│ ├── HaloConstant.java
│ ├── NewBasicExeAction.java
│ ├── model
│ ├── NewRightContext.java
│ ├── NewRightModel.java
│ └── SelectedTypeModel.java
│ └── utils
│ ├── FreemarkerConfiguration.java
│ ├── HaloIdeaUtils.java
│ └── PisFileByFreeMarkerUtil.java
├── idea-study-02
├── build.gradle
├── resources
│ ├── META-INF
│ │ ├── plugin.xml
│ │ ├── pluginIcon.svg
│ │ └── pluginIcon_dark.svg
│ ├── icons
│ │ ├── halo.png
│ │ └── right
│ │ │ ├── HaloBasic.png
│ │ │ ├── controller.png
│ │ │ └── mapper.png
│ └── templates
│ │ └── Controller.java.ftl
└── src
│ └── org
│ └── xujin
│ └── idea
│ └── right
│ ├── BasicActionOpenDialog.java
│ ├── BasicComBoxRenderer.java
│ ├── BasicCreateSelectInfoStep.form
│ ├── BasicCreateSelectInfoStep.java
│ ├── HaloConstant.java
│ ├── NewBasicExeAction.java
│ ├── linemarker
│ ├── AppMgmtNavigationHandler.java
│ ├── FunctionTooltip.java
│ └── HaloLineMarker.java
│ ├── model
│ ├── NewRightContext.java
│ ├── NewRightModel.java
│ └── SelectedTypeModel.java
│ └── utils
│ ├── FreemarkerConfiguration.java
│ ├── HaloIdeaUtils.java
│ └── PisFileByFreeMarkerUtil.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
3 | *.zip
4 | out
5 | .DS_Store
6 | .gradle/
7 | build/
8 | gradle/
9 | gradlew
10 | gradlew.bat
11 | /idea-sandbox
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # idea-study
2 | idea插件开发学习
3 |
4 | ## 相关资料
5 |
6 | ### SDK文档
7 |
8 | http://www.jetbrains.org/intellij/sdk/docs/welcome.html
9 |
10 | 1. Adding New Steps to Project Wizard
11 |
12 | * http://www.jetbrains.org/intellij/sdk/docs/tutorials/project_wizard.html
13 |
14 | * http://www.jetbrains.org/intellij/sdk/docs/tutorials/project_wizard/adding_new_steps.html
15 |
16 | 2.line_marker_provider
17 |
18 | * https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/line_marker_provider.html
19 |
20 |
21 | 3. Building plugins with Gradle
22 |
23 |
24 | * http://www.jetbrains.org/intellij/sdk/docs/tutorials/build_system.html
25 |
26 | * http://www.jetbrains.org/intellij/sdk/docs/tutorials/build_system/prerequisites.html
27 |
28 | ## 分享内容
29 |
30 | 1. 插件结构(Plugin Structure)
31 |
32 | 2. 自定义ComBox的图标-参考资料:https://www.logicbig.com/tutorials/java-swing/combo-box-icons.html
33 |
34 | 3. 两种开发IDEA插件开发方式:
35 |
36 | https://blog.csdn.net/ExcellentYuXiao/article/details/80273109
37 |
38 |
39 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | pluginVersion=1.0.0-SNAPSHOT
2 | ideaVersion=2019.1.3
--------------------------------------------------------------------------------
/idea-study-01/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' }
4 | }
5 |
6 | }
7 |
8 | plugins {
9 | id 'java'
10 | id 'org.jetbrains.intellij' version '0.4.9'
11 | }
12 |
13 | repositories {
14 | mavenLocal()
15 | mavenCentral()
16 | }
17 |
18 | dependencies {
19 | // compile group: 'commons-io', name: 'commons-io', version: '2.5'
20 | //compile group: 'com.alibaba', name: 'fastjson', version: '1.2.58'
21 | compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
22 | //compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.24'
23 |
24 | }
25 |
26 | apply plugin: 'java'
27 |
28 | sourceCompatibility = JavaVersion.VERSION_1_8
29 | targetCompatibility = JavaVersion.VERSION_1_8
30 |
31 | tasks.withType(JavaCompile) {
32 | options.encoding = "UTF-8"
33 | }
34 |
35 | sourceSets {
36 | main {
37 | java.srcDirs 'src'
38 | resources.srcDirs 'resources'
39 | }
40 | test {
41 | java.srcDirs 'test'
42 | resources.srcDirs 'test-resources'
43 | }
44 | }
45 |
46 | intellij {
47 | version ideaVersion //调试插件IDEA的版本
48 | pluginName 'HaloTools'
49 | updateSinceUntilBuild false
50 | sandboxDirectory = "${rootProject.projectDir}/idea-sandbox/idea-${ideaVersion}"
51 | plugins 'maven'
52 | }
53 |
54 | group 'org.xujin.idea'
55 | version pluginVersion
56 |
57 |
--------------------------------------------------------------------------------
/idea-study-01/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.xujin.idea.plugin
4 | HaloTools
5 | 1.0
6 | xujin.org
7 |
8 |
9 | <p>Enhances your productivity when developing applications based on Halo Framework.</p>
10 |
11 |
12 | com.intellij.modules.lang
13 | com.intellij.modules.platform
14 | com.intellij.modules.java
15 | org.jetbrains.idea.maven
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/idea-study-01/resources/META-INF/pluginIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/idea-study-01/resources/META-INF/pluginIcon_dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/idea-study-01/resources/icons/halo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-01/resources/icons/halo.png
--------------------------------------------------------------------------------
/idea-study-01/resources/icons/right/HaloBasic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-01/resources/icons/right/HaloBasic.png
--------------------------------------------------------------------------------
/idea-study-01/resources/icons/right/controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-01/resources/icons/right/controller.png
--------------------------------------------------------------------------------
/idea-study-01/resources/icons/right/mapper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-01/resources/icons/right/mapper.png
--------------------------------------------------------------------------------
/idea-study-01/resources/templates/Controller.java.ftl:
--------------------------------------------------------------------------------
1 | package ${selectedPackage};
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.*;
5 |
6 | @RestController
7 | @RequestMapping("/")
8 | public class ${className} {
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/BasicActionOpenDialog.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.ide.util.projectWizard.ModuleWizardStep;
4 | import com.intellij.ide.wizard.AbstractWizard;
5 | import com.intellij.openapi.module.Module;
6 | import com.intellij.openapi.options.ConfigurationException;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.ui.Messages;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | /**
12 | * Halo Basic组创建
13 | * @author xujin
14 | */
15 | public class BasicActionOpenDialog extends AbstractWizard {
16 |
17 | private Project myProject;
18 | private Module myModule;
19 |
20 | public BasicActionOpenDialog(Project project, Module module) {
21 | super("Create Halo Basic Class", project);
22 | myProject = project;
23 | myModule = module;
24 | ModuleWizardStep[] wizardSteps = createWizardSteps();
25 | for (ModuleWizardStep wizardStep : wizardSteps) {
26 | addStep(wizardStep);
27 | }
28 | init();
29 | }
30 |
31 | public ModuleWizardStep[] createWizardSteps() {
32 | return new ModuleWizardStep[]{
33 | new BasicCreateSelectInfoStep(myProject,myModule)
34 | };
35 | }
36 |
37 | /**
38 | * 点击Ok,之后去生成对应的扩展点
39 | */
40 | @Override
41 | protected void doOKAction() {
42 | ModuleWizardStep step = getCurrentStepObject();
43 | try {
44 | if (step.validate()) {
45 | super.doOKAction();
46 | }
47 | } catch (ConfigurationException e) {
48 | Messages.showErrorDialog(step.getComponent(), e.getMessage(), e.getTitle());
49 | }
50 | }
51 |
52 | @Nullable
53 | @Override
54 | protected String getHelpID() {
55 | return BasicActionOpenDialog.class.getName();
56 | }
57 |
58 |
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/BasicComBoxRenderer.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 |
4 | import org.xujin.idea.right.model.SelectedTypeModel;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * 下拉列表渲染
15 | */
16 | public class BasicComBoxRenderer extends DefaultListCellRenderer {
17 | private Map iconMap = new HashMap<>();
18 | private Color background = new Color(0, 100, 255, 15);
19 | private Color defaultBackground = (Color) UIManager.get("List.background");
20 |
21 | public BasicComBoxRenderer() {
22 | iconMap.put(HaloConstant.COMBOX_CONTROLLER,new ImageIcon(getClass().getResource("/icons/right/controller.png")));
23 | iconMap.put(HaloConstant.COMBOX_MAPPER,new ImageIcon(getClass().getResource("/icons/right/mapper.png")));
24 |
25 | }
26 |
27 | public static List getSelectedList(){
28 | List list=new ArrayList();
29 | SelectedTypeModel blank=new SelectedTypeModel();
30 | blank.setName("");
31 | blank.setValue(HaloConstant.COMBOX_BLANK);
32 | list.add(blank);
33 |
34 | SelectedTypeModel controller=new SelectedTypeModel();
35 | controller.setName("Controller");
36 | controller.setValue(HaloConstant.COMBOX_CONTROLLER);
37 | list.add(controller);
38 |
39 | SelectedTypeModel mapper=new SelectedTypeModel();
40 | mapper.setName("Mapper");
41 | mapper.setValue(HaloConstant.COMBOX_MAPPER);
42 | list.add(mapper);
43 |
44 |
45 |
46 | return list;
47 | }
48 |
49 | @Override
50 | public Component getListCellRendererComponent(JList> list, Object value, int index,
51 | boolean isSelected, boolean cellHasFocus) {
52 | super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
53 | SelectedTypeModel emp = (SelectedTypeModel) value;
54 | this.setText(emp.getName());
55 | this.setIcon(iconMap.get(emp.getValue()));
56 | if (!isSelected) {
57 | this.setBackground(index % 2 == 0 ? background : defaultBackground);
58 | }
59 | return this;
60 | }
61 | }
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/BasicCreateSelectInfoStep.form:
--------------------------------------------------------------------------------
1 |
2 |
101 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/BasicCreateSelectInfoStep.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.ide.util.projectWizard.ModuleWizardStep;
4 | import com.intellij.openapi.module.Module;
5 | import com.intellij.openapi.options.ConfigurationException;
6 | import com.intellij.openapi.project.Project;
7 | import org.xujin.idea.right.model.NewRightContext;
8 | import org.xujin.idea.right.model.SelectedTypeModel;
9 |
10 | import javax.swing.*;
11 | import java.awt.event.ItemEvent;
12 | import java.awt.event.ItemListener;
13 | import java.util.List;
14 |
15 | /**
16 | * @author xujin
17 | */
18 | public class BasicCreateSelectInfoStep extends ModuleWizardStep {
19 |
20 | private JPanel myMainPanel;
21 |
22 | private JPanel myPackagePanel;
23 |
24 | /**
25 | * 类名
26 | */
27 | private JTextField className;
28 |
29 | /**
30 | * 下拉列表框
31 | */
32 | private JComboBox kind;
33 |
34 |
35 |
36 |
37 | private Project myProject;
38 | private Module myModule;
39 |
40 |
41 |
42 |
43 | /**
44 | * 创建Mapper选择数据对象相关
45 | */
46 | private JLabel dataObjectTip;
47 | private JTextField dataObjectValue;
48 | private JButton dataObjectChooseButton;
49 |
50 | /**
51 | * @param project
52 | * @param module
53 | */
54 | public BasicCreateSelectInfoStep(Project project, Module module) {
55 | myProject = project;
56 | myModule = module;
57 | initComBox();
58 | dataObjectTip.setVisible(false);
59 | dataObjectValue.setVisible(false);
60 | dataObjectChooseButton.setVisible(false);
61 |
62 | kind.addItemListener(new ItemListener() {
63 | @Override
64 | public void itemStateChanged(ItemEvent e) {
65 | SelectedTypeModel selectedTypeModel = (SelectedTypeModel) e.getItem();
66 | switch (selectedTypeModel.getValue()) {
67 | case HaloConstant.COMBOX_CONTROLLER:
68 | NewRightContext.setClassType(HaloConstant.COMBOX_CONTROLLER);
69 | break;
70 | default:
71 | NewRightContext.setClassType(null);
72 | }
73 |
74 | }
75 | });
76 | }
77 |
78 |
79 |
80 | private void initComBox() {
81 |
82 | List list = BasicComBoxRenderer.getSelectedList();
83 | for (SelectedTypeModel seleType : list) {
84 | kind.addItem(seleType);
85 | }
86 | kind.setRenderer(new BasicComBoxRenderer());
87 | //Trinity trinity=new Trinity<>("Class", IconUtil.HALO , JavaTemplateUtil.INTERNAL_CLASS_TEMPLATE_NAME);
88 | //comboBox1.addItem(trinity);
89 |
90 |
91 | }
92 |
93 | @Override
94 | public JComponent getComponent() {
95 | return myMainPanel;
96 | }
97 |
98 | @Override
99 | public boolean validate() throws ConfigurationException {
100 | if (className.getText().isEmpty()) {
101 | throw new ConfigurationException("Class name cannot be empty", "Create Class Tips");
102 | }
103 | NewRightContext.setClassName(className.getText());
104 | return super.validate();
105 | }
106 |
107 |
108 | @Override
109 | public void updateDataModel() {
110 |
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/HaloConstant.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | /**
4 | * Halo Constant
5 | * @author xujin
6 | */
7 | public interface HaloConstant {
8 |
9 | String COMBOX_BLANK="0";
10 |
11 | /**
12 | * 创建Controller
13 | */
14 | String COMBOX_CONTROLLER="1";
15 |
16 |
17 | /**
18 | * 创建Mapper
19 | */
20 | String COMBOX_MAPPER="2";
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/NewBasicExeAction.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.DataKeys;
6 | import com.intellij.openapi.application.Result;
7 | import com.intellij.openapi.command.WriteCommandAction;
8 | import com.intellij.openapi.module.Module;
9 | import com.intellij.openapi.module.ModuleUtil;
10 | import com.intellij.openapi.project.DumbAwareRunnable;
11 | import com.intellij.openapi.project.DumbService;
12 | import com.intellij.openapi.project.Project;
13 | import com.intellij.openapi.roots.ModuleRootManager;
14 | import com.intellij.openapi.vfs.VirtualFile;
15 | import org.apache.commons.lang3.StringUtils;
16 | import org.jetbrains.annotations.NotNull;
17 | import org.jetbrains.idea.maven.project.MavenProjectsManager;
18 | import org.xujin.idea.right.model.NewRightContext;
19 | import org.xujin.idea.right.model.NewRightModel;
20 | import org.xujin.idea.right.utils.HaloIdeaUtils;
21 | import org.xujin.idea.right.utils.PisFileByFreeMarkerUtil;
22 |
23 |
24 | /**
25 | * 右键创建Basic Action
26 | * @author xujin
27 | */
28 | public class NewBasicExeAction extends AnAction {
29 |
30 | @Override
31 | public void actionPerformed(AnActionEvent e) {
32 |
33 | Project project = e.getProject();
34 | /**
35 | * 从Action中得到一个虚拟文件
36 | */
37 | VirtualFile virtualFile = e.getData(DataKeys.VIRTUAL_FILE);
38 | if (!virtualFile.isDirectory()) {
39 | virtualFile = virtualFile.getParent();
40 | }
41 | Module module = ModuleUtil.findModuleForFile(virtualFile, project);
42 |
43 | String moduleRootPath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
44 | String actionDir = virtualFile.getPath();
45 | String str = StringUtils.substringAfter(actionDir, moduleRootPath + "/src/main/java/");
46 | //获取右键后的路径
47 | String basePackage = StringUtils.replace(str, "/", ".");
48 | NewRightContext.clearAllSet();
49 | NewRightContext.setSelectedPackage(basePackage);
50 | BasicActionOpenDialog dialog = new BasicActionOpenDialog(project, module);
51 | if (!dialog.showAndGet()) {
52 | return;
53 | }
54 |
55 | DumbService.getInstance(project).runWhenSmart((DumbAwareRunnable) () -> new WriteCommandAction(project) {
56 | @Override
57 | protected void run(@NotNull Result result) {
58 | switch (NewRightContext.getClassType()) {
59 | case HaloConstant.COMBOX_CONTROLLER:
60 | createByFtl(project, moduleRootPath,"Controller.java.ftl");
61 | break;
62 | }
63 | MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
64 | //解决依赖
65 | manager.forceUpdateAllProjectsOrFindAllAvailablePomFiles();
66 | //优化生成的所有Java类
67 | HaloIdeaUtils.doOptimize(project);
68 |
69 | }
70 | }.execute());
71 |
72 | }
73 |
74 |
75 | /**
76 | * 通过ftl创建 Controller
77 | * @param project
78 | * @param moduleRootPath
79 | */
80 | private void createByFtl(Project project, String moduleRootPath, String ftlName) {
81 | NewRightModel newRightModel= NewRightContext.copyToNewRightModel();
82 | try {
83 | PisFileByFreeMarkerUtil.createFile(project, newRightModel, moduleRootPath,ftlName);
84 | NewRightContext.clearAllSet();
85 | } catch (Exception ex) {
86 | ex.printStackTrace();
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/model/NewRightContext.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | public class NewRightContext {
4 |
5 | /**
6 | * 类名
7 | */
8 | private static String className;
9 |
10 | /**
11 | * 所选择的类的类型
12 | */
13 | private static String classType;
14 |
15 | /**
16 | * 创建java类所在的包
17 | */
18 | private static String selectedPackage;
19 |
20 |
21 | public static String getClassType() {
22 | return classType;
23 | }
24 |
25 | public static void setClassType(String classType) {
26 | NewRightContext.classType = classType;
27 | }
28 |
29 | public static String getClassName() {
30 | return className;
31 | }
32 |
33 | public static void setClassName(String className) {
34 | NewRightContext.className = className;
35 | }
36 |
37 | public static String getSelectedPackage() {
38 | return selectedPackage;
39 | }
40 |
41 | public static void setSelectedPackage(String selectedPackage) {
42 | NewRightContext.selectedPackage = selectedPackage;
43 | }
44 |
45 | public static void clearAllSet() {
46 | classType = null;
47 | className = null;
48 | selectedPackage = null;
49 | }
50 |
51 | public static NewRightModel copyToNewRightModel() {
52 | NewRightModel newRightModel = new NewRightModel();
53 | newRightModel.setClassName(className);
54 | newRightModel.setSelectedPackage(selectedPackage);
55 | return newRightModel;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/model/NewRightModel.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | public class NewRightModel {
4 |
5 | /**
6 | * 类名
7 | */
8 | private String className;
9 |
10 | /**
11 | * 所选择的类的类型
12 | */
13 | private String classType;
14 |
15 | /**
16 | * 创建java类所在的包
17 | */
18 | private String selectedPackage;
19 |
20 | public String getClassName() {
21 | return className;
22 | }
23 |
24 | public void setClassName(String className) {
25 | this.className = className;
26 | }
27 |
28 | public String getClassType() {
29 | return classType;
30 | }
31 |
32 | public void setClassType(String classType) {
33 | this.classType = classType;
34 | }
35 |
36 | public String getSelectedPackage() {
37 | return selectedPackage;
38 | }
39 |
40 | public void setSelectedPackage(String selectedPackage) {
41 | this.selectedPackage = selectedPackage;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/model/SelectedTypeModel.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | /**
4 | * 下拉列表选中模型
5 | * @author xujin
6 | */
7 | public class SelectedTypeModel {
8 |
9 | /**
10 | * 下拉列表显示的名称
11 | */
12 | private String name;
13 |
14 | /**
15 | * 下拉列表的value
16 | */
17 | private String value;
18 |
19 | public String getName() {
20 | return name;
21 | }
22 |
23 | public void setName(String name) {
24 | this.name = name;
25 | }
26 |
27 | public String getValue() {
28 | return value;
29 | }
30 |
31 | public void setValue(String value) {
32 | this.value = value;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/utils/FreemarkerConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import freemarker.template.Configuration;
4 |
5 | public class FreemarkerConfiguration extends Configuration {
6 | private String basePackagePath;
7 |
8 | public FreemarkerConfiguration() {
9 | this("");
10 | }
11 |
12 | public FreemarkerConfiguration(String basePackagePath) {
13 | super(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
14 | setClassForTemplateLoading(getClass(), basePackagePath);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/utils/HaloIdeaUtils.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import com.intellij.openapi.application.ApplicationManager;
4 | import com.intellij.openapi.application.ModalityState;
5 | import com.intellij.openapi.application.Result;
6 | import com.intellij.openapi.command.WriteCommandAction;
7 | import com.intellij.openapi.project.DumbAwareRunnable;
8 | import com.intellij.openapi.project.DumbService;
9 | import com.intellij.openapi.project.Project;
10 | import com.intellij.openapi.startup.StartupManager;
11 | import com.intellij.openapi.vfs.VirtualFile;
12 | import com.intellij.psi.PsiJavaFile;
13 | import com.intellij.psi.PsiManager;
14 | import com.intellij.psi.codeStyle.CodeStyleManager;
15 | import com.intellij.psi.codeStyle.JavaCodeStyleManager;
16 | import com.intellij.util.DisposeAwareRunnable;
17 | import org.jetbrains.annotations.NotNull;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * @author xujin
24 | */
25 | public class HaloIdeaUtils {
26 | public static final String DEFAULT_CHARSET = "UTF-8";
27 |
28 | public static void invokeAndWait(Project p, Runnable r) {
29 | invokeAndWait(p, ModalityState.defaultModalityState(), r);
30 | }
31 |
32 | public static void invokeAndWait(Project p, ModalityState state, Runnable r) {
33 | if (isNoBackgroundMode()) {
34 | r.run();
35 | } else {
36 | ApplicationManager.getApplication().invokeAndWait(DisposeAwareRunnable.create(r, p), state);
37 | }
38 | }
39 |
40 | public static void invokeLater(Project p, Runnable r) {
41 | invokeLater(p, ModalityState.defaultModalityState(), r);
42 | }
43 |
44 | public static void invokeLater(Project p, ModalityState state, Runnable r) {
45 | if (isNoBackgroundMode()) {
46 | r.run();
47 | } else {
48 | ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state);
49 | }
50 |
51 | }
52 |
53 | public static void runWhenInitialized(final Project project, final Runnable r) {
54 | if (project.isDisposed()) {
55 | return;
56 | }
57 | if (isNoBackgroundMode()) {
58 | r.run();
59 | return;
60 | }
61 | if (!project.isInitialized()) {
62 | StartupManager.getInstance(project).registerPostStartupActivity(DisposeAwareRunnable.create(r, project));
63 | return;
64 | }
65 | runDumbAware(project, r);
66 | }
67 |
68 | public static boolean isNoBackgroundMode() {
69 | return (ApplicationManager.getApplication().isUnitTestMode()
70 | || ApplicationManager.getApplication().isHeadlessEnvironment());
71 | }
72 |
73 | public static void runDumbAware(final Project project, final Runnable r) {
74 | if (DumbService.isDumbAware(r)) {
75 | r.run();
76 | } else {
77 | DumbService.getInstance(project).runWhenSmart(DisposeAwareRunnable.create(r, project));
78 | }
79 | }
80 |
81 | private static List virtualFiles = new ArrayList<>();
82 |
83 | public static void addWaitOptimizeFile(VirtualFile virtualFile) {
84 | virtualFiles.add(virtualFile);
85 | }
86 |
87 | public static void doOptimize(Project project) {
88 | DumbService.getInstance(project).runWhenSmart((DumbAwareRunnable) () -> new WriteCommandAction(project) {
89 | @Override
90 | protected void run(@NotNull Result result) {
91 | for (VirtualFile virtualFile : virtualFiles) {
92 | try {
93 | PsiJavaFile javaFile = (PsiJavaFile) PsiManager.getInstance(project).findFile(virtualFile);
94 | if (javaFile != null) {
95 | CodeStyleManager.getInstance(project).reformat(javaFile);
96 | JavaCodeStyleManager.getInstance(project).optimizeImports(javaFile);
97 | JavaCodeStyleManager.getInstance(project).shortenClassReferences(javaFile);
98 | }
99 |
100 | } catch (Exception e) {
101 | e.printStackTrace();
102 | }
103 | }
104 | virtualFiles.clear();
105 | }
106 | }.execute());
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/idea-study-01/src/org/xujin/idea/right/utils/PisFileByFreeMarkerUtil.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import com.intellij.ide.projectView.ProjectView;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import com.intellij.openapi.fileEditor.FileEditorManager;
6 | import com.intellij.openapi.fileEditor.OpenFileDescriptor;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.util.io.FileUtil;
9 | import com.intellij.openapi.util.text.StringUtil;
10 | import com.intellij.openapi.vfs.LocalFileSystem;
11 | import com.intellij.openapi.vfs.VirtualFile;
12 | import com.intellij.openapi.wm.ToolWindow;
13 | import com.intellij.openapi.wm.ToolWindowManager;
14 | import com.intellij.util.OpenSourceUtil;
15 | import freemarker.template.Template;
16 | import org.xujin.idea.right.model.NewRightModel;
17 |
18 | import java.io.StringWriter;
19 |
20 | /**
21 | * @author xujin
22 | */
23 | public class PisFileByFreeMarkerUtil {
24 |
25 | public static FreemarkerConfiguration freemarker = new FreemarkerConfiguration("/templates");
26 |
27 | /**
28 | * 右键创建扩展点
29 | * @param project
30 | * @param model
31 | * @param moduleRootPath
32 | * @throws Exception
33 | */
34 | public static void createFile(Project project, Object model, String moduleRootPath,String ftlName) throws Exception {
35 |
36 | NewRightModel rightModel =(NewRightModel)model;
37 | VirtualFile vf = createPackageDir(rightModel.getSelectedPackage(),moduleRootPath);
38 | //可以使用virtualfile.createChildData()方法创建文件实例
39 | VirtualFile virtualFile=vf.createChildData(project, rightModel.getClassName()+".java");
40 | StringWriter sw = new StringWriter();
41 | Template template = PisFileByFreeMarkerUtil.freemarker.getTemplate(ftlName);
42 | template.process(model, sw);
43 | //使用VirtualFile.setBinaryContent()写一些数据到对应的文件中
44 | virtualFile.setBinaryContent(sw.toString().getBytes(HaloIdeaUtils.DEFAULT_CHARSET));
45 | //HaloIdeaUtils.addWaitOptimizeFile(virtualFile);
46 |
47 | FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
48 | if (fileEditorManager.isFileOpen(virtualFile)) {
49 | OpenSourceUtil.navigate(true, new OpenFileDescriptor(project, virtualFile));
50 | ProjectView.getInstance(project).select(null, virtualFile, true);
51 | return;
52 | }
53 | fileEditorManager.openFile(virtualFile, true);
54 | ProjectView.getInstance(project).select(null, virtualFile, true);
55 | ApplicationManager.getApplication().invokeLater(() -> {
56 | ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project");
57 | toolWindow.activate(null, true);
58 | });
59 | }
60 |
61 |
62 |
63 | private static VirtualFile createPackageDir(String packageName, String moduleRootPath) {
64 | packageName = "src/main/java/" + packageName;
65 | String path = FileUtil.toSystemIndependentName(moduleRootPath + "/" + StringUtil.replace(packageName, ".", "/"));
66 | //new File(path).mkdirs();
67 | return LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
68 | }
69 |
70 |
71 |
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/idea-study-02/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' }
4 | }
5 |
6 | }
7 |
8 | plugins {
9 | id 'java'
10 | id 'org.jetbrains.intellij' version '0.4.9'
11 | }
12 |
13 | repositories {
14 | mavenLocal()
15 | mavenCentral()
16 | }
17 |
18 | dependencies {
19 | // compile group: 'commons-io', name: 'commons-io', version: '2.5'
20 | //compile group: 'com.alibaba', name: 'fastjson', version: '1.2.58'
21 | compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
22 | //compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.24'
23 |
24 | }
25 |
26 | apply plugin: 'java'
27 |
28 | sourceCompatibility = JavaVersion.VERSION_1_8
29 | targetCompatibility = JavaVersion.VERSION_1_8
30 |
31 | tasks.withType(JavaCompile) {
32 | options.encoding = "UTF-8"
33 | }
34 |
35 | sourceSets {
36 | main {
37 | java.srcDirs 'src'
38 | resources.srcDirs 'resources'
39 | }
40 | test {
41 | java.srcDirs 'test'
42 | resources.srcDirs 'test-resources'
43 | }
44 | }
45 |
46 | intellij {
47 | version ideaVersion //调试插件IDEA的版本
48 | pluginName 'HaloTools'
49 | updateSinceUntilBuild false
50 | sandboxDirectory = "${rootProject.projectDir}/idea-sandbox/idea-${ideaVersion}"
51 | plugins 'maven'
52 | }
53 |
54 | group 'org.xujin.idea'
55 | version pluginVersion
56 |
57 |
--------------------------------------------------------------------------------
/idea-study-02/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.xujin.idea.plugin
4 | HaloTools
5 | 1.0
6 | xujin.org
7 |
8 |
9 | <p>Enhances your productivity when developing applications based on Halo Framework.</p>
10 |
11 |
12 | com.intellij.modules.lang
13 | com.intellij.modules.platform
14 | com.intellij.modules.java
15 | org.jetbrains.idea.maven
16 |
17 |
18 |
19 |
20 |
21 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/idea-study-02/resources/META-INF/pluginIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/idea-study-02/resources/META-INF/pluginIcon_dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/idea-study-02/resources/icons/halo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-02/resources/icons/halo.png
--------------------------------------------------------------------------------
/idea-study-02/resources/icons/right/HaloBasic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-02/resources/icons/right/HaloBasic.png
--------------------------------------------------------------------------------
/idea-study-02/resources/icons/right/controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-02/resources/icons/right/controller.png
--------------------------------------------------------------------------------
/idea-study-02/resources/icons/right/mapper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareKing/idea-study/e7b085f4c75e49ada5d90360578832cbf11bd3f3/idea-study-02/resources/icons/right/mapper.png
--------------------------------------------------------------------------------
/idea-study-02/resources/templates/Controller.java.ftl:
--------------------------------------------------------------------------------
1 | package ${selectedPackage};
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.*;
5 |
6 | @RestController
7 | @RequestMapping("/")
8 | public class ${className} {
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/BasicActionOpenDialog.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.ide.util.projectWizard.ModuleWizardStep;
4 | import com.intellij.ide.wizard.AbstractWizard;
5 | import com.intellij.openapi.module.Module;
6 | import com.intellij.openapi.options.ConfigurationException;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.ui.Messages;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | /**
12 | * Halo Basic组创建
13 | * @author xujin
14 | */
15 | public class BasicActionOpenDialog extends AbstractWizard {
16 |
17 | private Project myProject;
18 | private Module myModule;
19 |
20 | public BasicActionOpenDialog(Project project, Module module) {
21 | super("Create Halo Basic Class", project);
22 | myProject = project;
23 | myModule = module;
24 | ModuleWizardStep[] wizardSteps = createWizardSteps();
25 | for (ModuleWizardStep wizardStep : wizardSteps) {
26 | addStep(wizardStep);
27 | }
28 | init();
29 | }
30 |
31 | public ModuleWizardStep[] createWizardSteps() {
32 | return new ModuleWizardStep[]{
33 | new BasicCreateSelectInfoStep(myProject,myModule)
34 | };
35 | }
36 |
37 | /**
38 | * 点击Ok,之后去生成对应的扩展点
39 | */
40 | @Override
41 | protected void doOKAction() {
42 | ModuleWizardStep step = getCurrentStepObject();
43 | try {
44 | if (step.validate()) {
45 | super.doOKAction();
46 | }
47 | } catch (ConfigurationException e) {
48 | Messages.showErrorDialog(step.getComponent(), e.getMessage(), e.getTitle());
49 | }
50 | }
51 |
52 | @Nullable
53 | @Override
54 | protected String getHelpID() {
55 | return BasicActionOpenDialog.class.getName();
56 | }
57 |
58 |
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/BasicComBoxRenderer.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 |
4 | import org.xujin.idea.right.model.SelectedTypeModel;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * 下拉列表渲染
15 | */
16 | public class BasicComBoxRenderer extends DefaultListCellRenderer {
17 | private Map iconMap = new HashMap<>();
18 | private Color background = new Color(0, 100, 255, 15);
19 | private Color defaultBackground = (Color) UIManager.get("List.background");
20 |
21 | public BasicComBoxRenderer() {
22 | iconMap.put(HaloConstant.COMBOX_CONTROLLER,new ImageIcon(getClass().getResource("/icons/right/controller.png")));
23 | iconMap.put(HaloConstant.COMBOX_MAPPER,new ImageIcon(getClass().getResource("/icons/right/mapper.png")));
24 |
25 | }
26 |
27 | public static List getSelectedList(){
28 | List list=new ArrayList();
29 | SelectedTypeModel blank=new SelectedTypeModel();
30 | blank.setName("");
31 | blank.setValue(HaloConstant.COMBOX_BLANK);
32 | list.add(blank);
33 |
34 | SelectedTypeModel controller=new SelectedTypeModel();
35 | controller.setName("Controller");
36 | controller.setValue(HaloConstant.COMBOX_CONTROLLER);
37 | list.add(controller);
38 |
39 | SelectedTypeModel mapper=new SelectedTypeModel();
40 | mapper.setName("Mapper");
41 | mapper.setValue(HaloConstant.COMBOX_MAPPER);
42 | list.add(mapper);
43 |
44 |
45 |
46 | return list;
47 | }
48 |
49 | @Override
50 | public Component getListCellRendererComponent(JList> list, Object value, int index,
51 | boolean isSelected, boolean cellHasFocus) {
52 | super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
53 | SelectedTypeModel emp = (SelectedTypeModel) value;
54 | this.setText(emp.getName());
55 | this.setIcon(iconMap.get(emp.getValue()));
56 | if (!isSelected) {
57 | this.setBackground(index % 2 == 0 ? background : defaultBackground);
58 | }
59 | return this;
60 | }
61 | }
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/BasicCreateSelectInfoStep.form:
--------------------------------------------------------------------------------
1 |
2 |
101 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/BasicCreateSelectInfoStep.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.ide.util.projectWizard.ModuleWizardStep;
4 | import com.intellij.openapi.module.Module;
5 | import com.intellij.openapi.options.ConfigurationException;
6 | import com.intellij.openapi.project.Project;
7 | import org.xujin.idea.right.model.NewRightContext;
8 | import org.xujin.idea.right.model.SelectedTypeModel;
9 |
10 | import javax.swing.*;
11 | import java.awt.event.ItemEvent;
12 | import java.awt.event.ItemListener;
13 | import java.util.List;
14 |
15 | /**
16 | * @author xujin
17 | */
18 | public class BasicCreateSelectInfoStep extends ModuleWizardStep {
19 |
20 | private JPanel myMainPanel;
21 |
22 | private JPanel myPackagePanel;
23 |
24 | /**
25 | * 类名
26 | */
27 | private JTextField className;
28 |
29 | /**
30 | * 下拉列表框
31 | */
32 | private JComboBox kind;
33 |
34 |
35 |
36 |
37 | private Project myProject;
38 | private Module myModule;
39 |
40 |
41 |
42 |
43 | /**
44 | * 创建Mapper选择数据对象相关
45 | */
46 | private JLabel dataObjectTip;
47 | private JTextField dataObjectValue;
48 | private JButton dataObjectChooseButton;
49 |
50 | /**
51 | * @param project
52 | * @param module
53 | */
54 | public BasicCreateSelectInfoStep(Project project, Module module) {
55 | myProject = project;
56 | myModule = module;
57 | initComBox();
58 | dataObjectTip.setVisible(false);
59 | dataObjectValue.setVisible(false);
60 | dataObjectChooseButton.setVisible(false);
61 |
62 | kind.addItemListener(new ItemListener() {
63 | @Override
64 | public void itemStateChanged(ItemEvent e) {
65 | SelectedTypeModel selectedTypeModel = (SelectedTypeModel) e.getItem();
66 | switch (selectedTypeModel.getValue()) {
67 | case HaloConstant.COMBOX_CONTROLLER:
68 | NewRightContext.setClassType(HaloConstant.COMBOX_CONTROLLER);
69 | break;
70 | default:
71 | NewRightContext.setClassType(null);
72 | }
73 |
74 | }
75 | });
76 | }
77 |
78 |
79 |
80 | private void initComBox() {
81 |
82 | List list = BasicComBoxRenderer.getSelectedList();
83 | for (SelectedTypeModel seleType : list) {
84 | kind.addItem(seleType);
85 | }
86 | kind.setRenderer(new BasicComBoxRenderer());
87 | //Trinity trinity=new Trinity<>("Class", IconUtil.HALO , JavaTemplateUtil.INTERNAL_CLASS_TEMPLATE_NAME);
88 | //comboBox1.addItem(trinity);
89 |
90 |
91 | }
92 |
93 | @Override
94 | public JComponent getComponent() {
95 | return myMainPanel;
96 | }
97 |
98 | @Override
99 | public boolean validate() throws ConfigurationException {
100 | if (className.getText().isEmpty()) {
101 | throw new ConfigurationException("Class name cannot be empty", "Create Class Tips");
102 | }
103 | NewRightContext.setClassName(className.getText());
104 | return super.validate();
105 | }
106 |
107 |
108 | @Override
109 | public void updateDataModel() {
110 |
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/HaloConstant.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | /**
4 | * Halo Constant
5 | * @author xujin
6 | */
7 | public interface HaloConstant {
8 |
9 | String COMBOX_BLANK="0";
10 |
11 | /**
12 | * 创建Controller
13 | */
14 | String COMBOX_CONTROLLER="1";
15 |
16 |
17 | /**
18 | * 创建Mapper
19 | */
20 | String COMBOX_MAPPER="2";
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/NewBasicExeAction.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.DataKeys;
6 | import com.intellij.openapi.application.Result;
7 | import com.intellij.openapi.command.WriteCommandAction;
8 | import com.intellij.openapi.module.Module;
9 | import com.intellij.openapi.module.ModuleUtil;
10 | import com.intellij.openapi.project.DumbAwareRunnable;
11 | import com.intellij.openapi.project.DumbService;
12 | import com.intellij.openapi.project.Project;
13 | import com.intellij.openapi.roots.ModuleRootManager;
14 | import com.intellij.openapi.vfs.VirtualFile;
15 | import org.apache.commons.lang3.StringUtils;
16 | import org.jetbrains.annotations.NotNull;
17 | import org.jetbrains.idea.maven.project.MavenProjectsManager;
18 | import org.xujin.idea.right.model.NewRightContext;
19 | import org.xujin.idea.right.model.NewRightModel;
20 | import org.xujin.idea.right.utils.HaloIdeaUtils;
21 | import org.xujin.idea.right.utils.PisFileByFreeMarkerUtil;
22 |
23 |
24 | /**
25 | * 右键创建Basic Action
26 | * @author xujin
27 | */
28 | public class NewBasicExeAction extends AnAction {
29 |
30 | @Override
31 | public void actionPerformed(AnActionEvent e) {
32 |
33 | Project project = e.getProject();
34 | /**
35 | * 从Action中得到一个虚拟文件
36 | */
37 | VirtualFile virtualFile = e.getData(DataKeys.VIRTUAL_FILE);
38 | if (!virtualFile.isDirectory()) {
39 | virtualFile = virtualFile.getParent();
40 | }
41 | Module module = ModuleUtil.findModuleForFile(virtualFile, project);
42 |
43 | String moduleRootPath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
44 | String actionDir = virtualFile.getPath();
45 | String str = StringUtils.substringAfter(actionDir, moduleRootPath + "/src/main/java/");
46 | //获取右键后的路径
47 | String basePackage = StringUtils.replace(str, "/", ".");
48 | NewRightContext.clearAllSet();
49 | NewRightContext.setSelectedPackage(basePackage);
50 | BasicActionOpenDialog dialog = new BasicActionOpenDialog(project, module);
51 | if (!dialog.showAndGet()) {
52 | return;
53 | }
54 |
55 | DumbService.getInstance(project).runWhenSmart((DumbAwareRunnable) () -> new WriteCommandAction(project) {
56 | @Override
57 | protected void run(@NotNull Result result) {
58 | switch (NewRightContext.getClassType()) {
59 | case HaloConstant.COMBOX_CONTROLLER:
60 | createByFtl(project, moduleRootPath,"Controller.java.ftl");
61 | break;
62 | }
63 | MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
64 | //解决依赖
65 | manager.forceUpdateAllProjectsOrFindAllAvailablePomFiles();
66 | //优化生成的所有Java类
67 | HaloIdeaUtils.doOptimize(project);
68 |
69 | }
70 | }.execute());
71 |
72 | }
73 |
74 |
75 | /**
76 | * 通过ftl创建 Controller
77 | * @param project
78 | * @param moduleRootPath
79 | */
80 | private void createByFtl(Project project, String moduleRootPath, String ftlName) {
81 | NewRightModel newRightModel= NewRightContext.copyToNewRightModel();
82 | try {
83 | PisFileByFreeMarkerUtil.createFile(project, newRightModel, moduleRootPath,ftlName);
84 | NewRightContext.clearAllSet();
85 | } catch (Exception ex) {
86 | ex.printStackTrace();
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/linemarker/AppMgmtNavigationHandler.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.linemarker;
2 |
3 | import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
4 | import com.intellij.psi.PsiElement;
5 |
6 | import java.awt.event.MouseEvent;
7 |
8 |
9 | /**
10 | * Domain行标记修改
11 | * @author xujin
12 | */
13 | public class AppMgmtNavigationHandler implements GutterIconNavigationHandler {
14 |
15 | @Override
16 | public void navigate(MouseEvent mouseEvent, PsiElement psiElement) {
17 |
18 |
19 | }
20 |
21 |
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/linemarker/FunctionTooltip.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.linemarker;
2 |
3 | import com.intellij.util.Function;
4 |
5 | /**
6 | *
7 | * @author xujin
8 | */
9 | public class FunctionTooltip implements Function {
10 |
11 | String msg = "点我快速切换至对应文件";
12 |
13 | public FunctionTooltip() {
14 | }
15 |
16 | public FunctionTooltip(String msg) {
17 | this.msg = msg;
18 | }
19 |
20 |
21 | @Override
22 | public Object fun(Object o) {
23 | return msg;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/linemarker/HaloLineMarker.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.linemarker;
2 |
3 | import com.intellij.codeInsight.daemon.LineMarkerInfo;
4 | import com.intellij.codeInsight.daemon.LineMarkerProvider;
5 | import com.intellij.openapi.editor.markup.GutterIconRenderer;
6 | import com.intellij.openapi.util.IconLoader;
7 | import com.intellij.psi.PsiAnnotation;
8 | import com.intellij.psi.PsiClass;
9 | import com.intellij.psi.PsiElement;
10 | import com.intellij.psi.impl.source.PsiClassImpl;
11 | import org.jetbrains.annotations.NotNull;
12 | import org.jetbrains.annotations.Nullable;
13 |
14 | import java.util.Collection;
15 | import java.util.List;
16 |
17 | public class HaloLineMarker implements LineMarkerProvider {
18 |
19 | @Nullable
20 | @Override
21 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) {
22 | LineMarkerInfo lineMarkerInfo= null;
23 | try {
24 | lineMarkerInfo = null;
25 | String anno="org.springframework.boot.autoconfigure.SpringBootApplication";
26 | if(!judgeHaveAnnotation(psiElement,anno)){
27 | return lineMarkerInfo;
28 | }
29 | PsiClassImpl field = ((PsiClassImpl) psiElement);
30 | PsiAnnotation psiAnnotation = field.getAnnotation(anno);
31 | lineMarkerInfo = new LineMarkerInfo<>(psiAnnotation, psiAnnotation.getTextRange(), IconLoader.findIcon("/icons/right/HaloBasic.png"),
32 | new FunctionTooltip("快速导航"),
33 | new AppMgmtNavigationHandler(),
34 | GutterIconRenderer.Alignment.LEFT);
35 | //根据不同的行标记分配不同的行标记处理器
36 | } catch (Exception e) {
37 | e.printStackTrace();
38 | }
39 | return lineMarkerInfo;
40 | }
41 |
42 | @Override
43 | public void collectSlowLineMarkers(@NotNull List list, @NotNull Collection collection) {
44 | }
45 |
46 | private boolean judgeHaveAnnotation(@NotNull PsiElement psiElement, String anno) {
47 | if (psiElement instanceof PsiClass) {
48 | PsiClassImpl field = ((PsiClassImpl) psiElement);
49 | PsiAnnotation psiAnnotation = field.getAnnotation(anno);
50 | if (null != psiAnnotation) {
51 | return true;
52 | }
53 | return false;
54 | }
55 | return false;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/model/NewRightContext.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | public class NewRightContext {
4 |
5 | /**
6 | * 类名
7 | */
8 | private static String className;
9 |
10 | /**
11 | * 所选择的类的类型
12 | */
13 | private static String classType;
14 |
15 | /**
16 | * 创建java类所在的包
17 | */
18 | private static String selectedPackage;
19 |
20 |
21 | public static String getClassType() {
22 | return classType;
23 | }
24 |
25 | public static void setClassType(String classType) {
26 | NewRightContext.classType = classType;
27 | }
28 |
29 | public static String getClassName() {
30 | return className;
31 | }
32 |
33 | public static void setClassName(String className) {
34 | NewRightContext.className = className;
35 | }
36 |
37 | public static String getSelectedPackage() {
38 | return selectedPackage;
39 | }
40 |
41 | public static void setSelectedPackage(String selectedPackage) {
42 | NewRightContext.selectedPackage = selectedPackage;
43 | }
44 |
45 | public static void clearAllSet() {
46 | classType = null;
47 | className = null;
48 | selectedPackage = null;
49 | }
50 |
51 | public static NewRightModel copyToNewRightModel() {
52 | NewRightModel newRightModel = new NewRightModel();
53 | newRightModel.setClassName(className);
54 | newRightModel.setSelectedPackage(selectedPackage);
55 | return newRightModel;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/model/NewRightModel.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | public class NewRightModel {
4 |
5 | /**
6 | * 类名
7 | */
8 | private String className;
9 |
10 | /**
11 | * 所选择的类的类型
12 | */
13 | private String classType;
14 |
15 | /**
16 | * 创建java类所在的包
17 | */
18 | private String selectedPackage;
19 |
20 | public String getClassName() {
21 | return className;
22 | }
23 |
24 | public void setClassName(String className) {
25 | this.className = className;
26 | }
27 |
28 | public String getClassType() {
29 | return classType;
30 | }
31 |
32 | public void setClassType(String classType) {
33 | this.classType = classType;
34 | }
35 |
36 | public String getSelectedPackage() {
37 | return selectedPackage;
38 | }
39 |
40 | public void setSelectedPackage(String selectedPackage) {
41 | this.selectedPackage = selectedPackage;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/model/SelectedTypeModel.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.model;
2 |
3 | /**
4 | * 下拉列表选中模型
5 | * @author xujin
6 | */
7 | public class SelectedTypeModel {
8 |
9 | /**
10 | * 下拉列表显示的名称
11 | */
12 | private String name;
13 |
14 | /**
15 | * 下拉列表的value
16 | */
17 | private String value;
18 |
19 | public String getName() {
20 | return name;
21 | }
22 |
23 | public void setName(String name) {
24 | this.name = name;
25 | }
26 |
27 | public String getValue() {
28 | return value;
29 | }
30 |
31 | public void setValue(String value) {
32 | this.value = value;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/utils/FreemarkerConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import freemarker.template.Configuration;
4 |
5 | public class FreemarkerConfiguration extends Configuration {
6 | private String basePackagePath;
7 |
8 | public FreemarkerConfiguration() {
9 | this("");
10 | }
11 |
12 | public FreemarkerConfiguration(String basePackagePath) {
13 | super(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
14 | setClassForTemplateLoading(getClass(), basePackagePath);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/utils/HaloIdeaUtils.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import com.intellij.openapi.application.ApplicationManager;
4 | import com.intellij.openapi.application.ModalityState;
5 | import com.intellij.openapi.application.Result;
6 | import com.intellij.openapi.command.WriteCommandAction;
7 | import com.intellij.openapi.project.DumbAwareRunnable;
8 | import com.intellij.openapi.project.DumbService;
9 | import com.intellij.openapi.project.Project;
10 | import com.intellij.openapi.startup.StartupManager;
11 | import com.intellij.openapi.vfs.VirtualFile;
12 | import com.intellij.psi.PsiJavaFile;
13 | import com.intellij.psi.PsiManager;
14 | import com.intellij.psi.codeStyle.CodeStyleManager;
15 | import com.intellij.psi.codeStyle.JavaCodeStyleManager;
16 | import com.intellij.util.DisposeAwareRunnable;
17 | import org.jetbrains.annotations.NotNull;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * @author xujin
24 | */
25 | public class HaloIdeaUtils {
26 | public static final String DEFAULT_CHARSET = "UTF-8";
27 |
28 | public static void invokeAndWait(Project p, Runnable r) {
29 | invokeAndWait(p, ModalityState.defaultModalityState(), r);
30 | }
31 |
32 | public static void invokeAndWait(Project p, ModalityState state, Runnable r) {
33 | if (isNoBackgroundMode()) {
34 | r.run();
35 | } else {
36 | ApplicationManager.getApplication().invokeAndWait(DisposeAwareRunnable.create(r, p), state);
37 | }
38 | }
39 |
40 | public static void invokeLater(Project p, Runnable r) {
41 | invokeLater(p, ModalityState.defaultModalityState(), r);
42 | }
43 |
44 | public static void invokeLater(Project p, ModalityState state, Runnable r) {
45 | if (isNoBackgroundMode()) {
46 | r.run();
47 | } else {
48 | ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state);
49 | }
50 |
51 | }
52 |
53 | public static void runWhenInitialized(final Project project, final Runnable r) {
54 | if (project.isDisposed()) {
55 | return;
56 | }
57 | if (isNoBackgroundMode()) {
58 | r.run();
59 | return;
60 | }
61 | if (!project.isInitialized()) {
62 | StartupManager.getInstance(project).registerPostStartupActivity(DisposeAwareRunnable.create(r, project));
63 | return;
64 | }
65 | runDumbAware(project, r);
66 | }
67 |
68 | public static boolean isNoBackgroundMode() {
69 | return (ApplicationManager.getApplication().isUnitTestMode()
70 | || ApplicationManager.getApplication().isHeadlessEnvironment());
71 | }
72 |
73 | public static void runDumbAware(final Project project, final Runnable r) {
74 | if (DumbService.isDumbAware(r)) {
75 | r.run();
76 | } else {
77 | DumbService.getInstance(project).runWhenSmart(DisposeAwareRunnable.create(r, project));
78 | }
79 | }
80 |
81 | private static List virtualFiles = new ArrayList<>();
82 |
83 | public static void addWaitOptimizeFile(VirtualFile virtualFile) {
84 | virtualFiles.add(virtualFile);
85 | }
86 |
87 | public static void doOptimize(Project project) {
88 | DumbService.getInstance(project).runWhenSmart((DumbAwareRunnable) () -> new WriteCommandAction(project) {
89 | @Override
90 | protected void run(@NotNull Result result) {
91 | for (VirtualFile virtualFile : virtualFiles) {
92 | try {
93 | PsiJavaFile javaFile = (PsiJavaFile) PsiManager.getInstance(project).findFile(virtualFile);
94 | if (javaFile != null) {
95 | CodeStyleManager.getInstance(project).reformat(javaFile);
96 | JavaCodeStyleManager.getInstance(project).optimizeImports(javaFile);
97 | JavaCodeStyleManager.getInstance(project).shortenClassReferences(javaFile);
98 | }
99 |
100 | } catch (Exception e) {
101 | e.printStackTrace();
102 | }
103 | }
104 | virtualFiles.clear();
105 | }
106 | }.execute());
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/idea-study-02/src/org/xujin/idea/right/utils/PisFileByFreeMarkerUtil.java:
--------------------------------------------------------------------------------
1 | package org.xujin.idea.right.utils;
2 |
3 | import com.intellij.ide.projectView.ProjectView;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import com.intellij.openapi.fileEditor.FileEditorManager;
6 | import com.intellij.openapi.fileEditor.OpenFileDescriptor;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.util.io.FileUtil;
9 | import com.intellij.openapi.util.text.StringUtil;
10 | import com.intellij.openapi.vfs.LocalFileSystem;
11 | import com.intellij.openapi.vfs.VirtualFile;
12 | import com.intellij.openapi.wm.ToolWindow;
13 | import com.intellij.openapi.wm.ToolWindowManager;
14 | import com.intellij.util.OpenSourceUtil;
15 | import freemarker.template.Template;
16 | import org.xujin.idea.right.model.NewRightModel;
17 |
18 | import java.io.StringWriter;
19 |
20 | /**
21 | * @author xujin
22 | */
23 | public class PisFileByFreeMarkerUtil {
24 |
25 | public static FreemarkerConfiguration freemarker = new FreemarkerConfiguration("/templates");
26 |
27 | /**
28 | * 右键创建扩展点
29 | * @param project
30 | * @param model
31 | * @param moduleRootPath
32 | * @throws Exception
33 | */
34 | public static void createFile(Project project, Object model, String moduleRootPath,String ftlName) throws Exception {
35 |
36 | NewRightModel rightModel =(NewRightModel)model;
37 | VirtualFile vf = createPackageDir(rightModel.getSelectedPackage(),moduleRootPath);
38 | //可以使用virtualfile.createChildData()方法创建文件实例
39 | VirtualFile virtualFile=vf.createChildData(project, rightModel.getClassName()+".java");
40 | StringWriter sw = new StringWriter();
41 | Template template = PisFileByFreeMarkerUtil.freemarker.getTemplate(ftlName);
42 | template.process(model, sw);
43 | //使用VirtualFile.setBinaryContent()写一些数据到对应的文件中
44 | virtualFile.setBinaryContent(sw.toString().getBytes(HaloIdeaUtils.DEFAULT_CHARSET));
45 | //HaloIdeaUtils.addWaitOptimizeFile(virtualFile);
46 |
47 | FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
48 | if (fileEditorManager.isFileOpen(virtualFile)) {
49 | OpenSourceUtil.navigate(true, new OpenFileDescriptor(project, virtualFile));
50 | ProjectView.getInstance(project).select(null, virtualFile, true);
51 | return;
52 | }
53 | fileEditorManager.openFile(virtualFile, true);
54 | ProjectView.getInstance(project).select(null, virtualFile, true);
55 | ApplicationManager.getApplication().invokeLater(() -> {
56 | ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project");
57 | toolWindow.activate(null, true);
58 | });
59 | }
60 |
61 |
62 |
63 | private static VirtualFile createPackageDir(String packageName, String moduleRootPath) {
64 | packageName = "src/main/java/" + packageName;
65 | String path = FileUtil.toSystemIndependentName(moduleRootPath + "/" + StringUtil.replace(packageName, ".", "/"));
66 | //new File(path).mkdirs();
67 | return LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
68 | }
69 |
70 |
71 |
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'idea-study'
2 | include(':idea-study-01')
3 | include(':idea-study-02')
4 |
5 |
6 |
--------------------------------------------------------------------------------