diff --git a/README.md b/README.md index fbea56a..2e927f6 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,22 @@ # object-helper-plugin -![](https://img.shields.io/badge/version-v1.3.0-blue) -![](https://img.shields.io/badge/license-Apache%202-red) -![](https://img.shields.io/badge/size-64%20kB-yellowgreen) -![](https://img.shields.io/badge/download-1.7k-green) +
+ +
+
+
+ + + + +
-插件地址:[object-helper-plugin](https://plugins.jetbrains.com/plugin/15788-objecthelper) +JetBrains Intellij IDEA ObjectHelper 插件旨在减少开发者重复低效的劳动,使开发者能够更专注于业务逻辑的开发。 -JetBrains Intellij IDEA ObjectHelper插件,包含以下功能: +该插件包含以下功能: - 对象拷贝 + set模式: ![](https://image.bigcoder.cn/7fce876e-fa94-4780-bb14-584068c35963.gif) @@ -17,29 +24,47 @@ JetBrains Intellij IDEA ObjectHelper插件,包含以下功能: ![](https://image.bigcoder.cn/20220916173117.png) + 当对象中包含`builder` 或者 `newBuilder`方法时,则插件默认会采用 builder 模式生成代码: + + ![](https://image.bigcoder.cn/20240505142735.gif) + + 如果你的builder类生成的方法名与插件默认生成的不同,可以在设置中更改: + + ![](https://image.bigcoder.cn/20240505143027.png) + - Java类转JSON - ![](https://image.bigcoder.cn/20210227223302.gif) + ![](https://image.bigcoder.cn/20231224171155.gif) - Java类转Thrift IDL + ![](https://image.bigcoder.cn/6eee7a02-8e4e-4f11-9b8c-81d661a920c5.gif) - Java类转XML - ![](https://image.bigcoder.cn/20220916170144.gif) + + ![](https://image.bigcoder.cn/20231224171113.gif) - 插件配置 -File->settings->Tools->Object Helper 即可进入插件的配置页面 +File->Settings->Tools->Object Helper 即可进入插件的配置页面 + +![](https://image.bigcoder.cn/20231224170305.png) + +- `generate field mode = target` 代表以方法返回类型的字段为基础生成对象拷贝; + `generate field mode = source` 代表以方法入参类型的字段为基础生成对象拷贝。 -![](https://image.bigcoder.cn/20220916173227.png) +- `non-existent field generate annotation = yes` 代表当目标字段在源对象中不存在时,是否以注释的形式生成代码,如果为 `no`,则代表不生成这一个字段拷贝代码。 ## 未来功能支持计划 object-helper插件未来功能支持计划: -- [x] Class转IDL(Class To Thrift IDL) -- [x] Class转XML(Class To XML) -- [ ] JSON转Class(JSON TO Class) +- [x] Class 转 IDL(Class To Thrift IDL) +- [x] Class 转 XML(Class To XML) +- [x] 个性化配置 +- [x] Object Copy Method 功能支持 Builder 模式 +- [ ] Object Copy Method 功能支持 Lambda 表达式 +- [ ] JSON 转 Class(JSON To Class) +- [ ] Class 转 Protobuf IDL(JSON To Class) - [ ] All Setter - [ ] 菜单分组显示 -- [x] 个性化配置 \ No newline at end of file diff --git a/build.gradle b/build.gradle index f419e84..196c339 100644 --- a/build.gradle +++ b/build.gradle @@ -1,29 +1,38 @@ plugins { - id 'org.jetbrains.intellij' version '1.8.0' + // https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md + id 'org.jetbrains.intellij' version '1.16.1' id 'java' } group 'cn.bigcoder.plugin' -version '1.3.0' +version '1.3.3' repositories { mavenCentral() } dependencies { + implementation 'org.apache.commons:commons-lang3:3.13.0' + / object 转 xml 依赖 开始/ + implementation 'com.fasterxml.jackson.core:jackson-core:2.13.3' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.3' + / object 转 xml 依赖 结束/ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' } // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { - version = '2021.2.1' + version = '2023.3.1' plugins = ['com.intellij.java'] } patchPluginXml { + sinceBuild = '211' + untilBuild = '281' changeNotes = """ - Add change notes here.
- most HTML tags may be used""" + 1. new feature: Object Copy Method support builder mode. + """ } test { useJUnitPlatform() diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java new file mode 100644 index 0000000..365eeb0 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java @@ -0,0 +1,28 @@ +package cn.bigcoder.plugin.objecthelper.action; + +import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.jetbrains.annotations.NotNull; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + **/ +public abstract class AbstractClassAnAction extends AnAction { + + /** + * 是否开启该功能 + * @return true代表开启该功能,false表示关闭该功能 + */ + public abstract boolean actionShow(AnActionEvent anActionEvent); + + @Override + public void update(@NotNull AnActionEvent anActionEvent) { + if (!actionShow(anActionEvent)) { + setActionInvisible(anActionEvent); + } + super.update(anActionEvent); + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToJsonAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToJsonAction.java index 1183e6f..8e96e8c 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToJsonAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToJsonAction.java @@ -1,23 +1,21 @@ package cn.bigcoder.plugin.objecthelper.action; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; import cn.bigcoder.plugin.objecthelper.common.util.NotificationUtils; import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.generator.Generator; import cn.bigcoder.plugin.objecthelper.generator.json.ClassJsonGenerator; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.psi.PsiClass; -import org.jetbrains.annotations.NotNull; import java.awt.datatransfer.StringSelection; import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getOperatePsiClass; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; -public class ClassToJsonAction extends AnAction { +public class ClassToJsonAction extends AbstractClassAnAction { @Override public void actionPerformed(AnActionEvent anAction) { @@ -27,18 +25,13 @@ public void actionPerformed(AnActionEvent anAction) { } String json = getGenerator(psiClass).generate(); CopyPasteManager.getInstance().setContents(new StringSelection(json)); - NotificationUtils.notifyInfo(anAction.getProject(), "JSON字符串成功置入剪贴板:
" + json); + NotificationUtils.notifyInfo(anAction.getProject(), "JSON字符串成功置入剪贴板:
" + json); } @Override - public void update(@NotNull AnActionEvent anActionEvent) { - if (!PluginConfigState.getInstance().isJsonSwitch()) { - setActionInvisible(anActionEvent); - } else if (getOperatePsiClass(anActionEvent) == null) { - // 如果当前光标不在类名上,则不显示ConvertToJson组件 - setActionInvisible(anActionEvent); - } - super.update(anActionEvent); + public boolean actionShow(AnActionEvent anActionEvent) { + return PluginConfigState.getInstance().getJsonSwitch() == FunctionSwitchEnum.OPEN + && getOperatePsiClass(anActionEvent) != null; } protected Generator getGenerator(PsiClass psiClass) { diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToThriftIDLAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToThriftIDLAction.java index 6af3f62..d25b2bd 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToThriftIDLAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToThriftIDLAction.java @@ -1,9 +1,9 @@ package cn.bigcoder.plugin.objecthelper.action; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; import cn.bigcoder.plugin.objecthelper.common.util.NotificationUtils; import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.generator.idl.ThriftIDLGenerator; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.psi.PsiClass; @@ -12,13 +12,12 @@ import java.awt.datatransfer.StringSelection; import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getOperatePsiClass; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; /** * @author: Jindong.Tian * @date: 2021-08-21 **/ -public class ClassToThriftIDLAction extends AnAction { +public class ClassToThriftIDLAction extends AbstractClassAnAction { @Override public void actionPerformed(@NotNull AnActionEvent anActionEvent) { PsiClass psiClass = getOperatePsiClass(anActionEvent); @@ -31,13 +30,8 @@ public void actionPerformed(@NotNull AnActionEvent anActionEvent) { } @Override - public void update(@NotNull AnActionEvent anActionEvent) { - if (!PluginConfigState.getInstance().isThriftSwitch()) { - setActionInvisible(anActionEvent); - } else if (getOperatePsiClass(anActionEvent) == null) { - // 如果当前光标不在类名上,则不显示ConvertToJson组件 - setActionInvisible(anActionEvent); - } - super.update(anActionEvent); + public boolean actionShow(@NotNull AnActionEvent anActionEvent) { + return PluginConfigState.getInstance().getThriftSwitch() == FunctionSwitchEnum.OPEN + && getOperatePsiClass(anActionEvent) != null; } } \ No newline at end of file diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToXMLAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToXMLAction.java index 5a38a49..82cb64c 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToXMLAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ClassToXMLAction.java @@ -1,24 +1,21 @@ package cn.bigcoder.plugin.objecthelper.action; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; import cn.bigcoder.plugin.objecthelper.common.util.NotificationUtils; import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.generator.Generator; -import cn.bigcoder.plugin.objecthelper.generator.json.ClassJsonGenerator; import cn.bigcoder.plugin.objecthelper.generator.xml.ClassXMLGenerator; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.psi.PsiClass; -import org.jetbrains.annotations.NotNull; +import groovy.json.StringEscapeUtils; import java.awt.datatransfer.StringSelection; +import org.jetbrains.annotations.NotNull; import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getOperatePsiClass; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; -public class ClassToXMLAction extends AnAction { +public class ClassToXMLAction extends AbstractClassAnAction { @Override public void actionPerformed(AnActionEvent anAction) { @@ -26,20 +23,15 @@ public void actionPerformed(AnActionEvent anAction) { if (psiClass == null) { return; } - String json = getGenerator(psiClass).generate(); - CopyPasteManager.getInstance().setContents(new StringSelection(json)); - NotificationUtils.notifyInfo(anAction.getProject(), "XML字符串成功置入剪贴板:
" + json); + String xmlStr = getGenerator(psiClass).generate(); + CopyPasteManager.getInstance().setContents(new StringSelection(xmlStr)); + NotificationUtils.notifyInfo(anAction.getProject(), "XML字符串成功置入剪贴板"); } @Override - public void update(@NotNull AnActionEvent anActionEvent) { - if (!PluginConfigState.getInstance().isXmlSwitch()) { - setActionInvisible(anActionEvent); - } else if (getOperatePsiClass(anActionEvent) == null) { - // 如果当前光标不在类名上,则不显示ConvertToJson组件 - setActionInvisible(anActionEvent); - } - super.update(anActionEvent); + public boolean actionShow(@NotNull AnActionEvent anActionEvent) { + return PluginConfigState.getInstance().getXmlSwitch() == FunctionSwitchEnum.OPEN + && getOperatePsiClass(anActionEvent) != null; } protected Generator getGenerator(PsiClass psiClass) { diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyMethodAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyMethodAction.java index 9cc5808..8b8fe9e 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyMethodAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyMethodAction.java @@ -1,23 +1,20 @@ package cn.bigcoder.plugin.objecthelper.action; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; import cn.bigcoder.plugin.objecthelper.common.util.PsiUtils; import cn.bigcoder.plugin.objecthelper.common.util.StringUtils; import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.generator.Generator; import cn.bigcoder.plugin.objecthelper.generator.method.ObjectCopyMethodGenerator; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiMethod; -import org.jetbrains.annotations.NotNull; import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.VOID; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getOperatePsiClass; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; -public class ObjectCopyMethodAction extends AnAction { +public class ObjectCopyMethodAction extends AbstractClassAnAction { @Override public void actionPerformed(AnActionEvent anActionEvent) { @@ -27,14 +24,9 @@ public void actionPerformed(AnActionEvent anActionEvent) { } @Override - public void update(@NotNull AnActionEvent anActionEvent) { - if (!PluginConfigState.getInstance().isObjectCopySwitch()) { - PsiUtils.setActionDisabled(anActionEvent); - } else if (!check(PsiUtils.getCursorPsiMethod(anActionEvent))) { - // 如果当前光标不在方法中,则不显示Object Copy组件 - PsiUtils.setActionDisabled(anActionEvent); - } - super.update(anActionEvent); + public boolean actionShow(AnActionEvent anActionEvent) { + return PluginConfigState.getInstance().getObjectCopySwitch() == FunctionSwitchEnum.OPEN + && check(PsiUtils.getCursorPsiMethod(anActionEvent)); } private void generateO2O(PsiMethod psiMethod) { @@ -64,7 +56,7 @@ private void generateO2O(PsiMethod psiMethod) { */ private boolean check(PsiMethod psiMethod) { if (psiMethod == null - || PsiUtils.getPsiParameters(psiMethod).size() == 0 + || PsiUtils.getPsiParameters(psiMethod).isEmpty() || VOID.equals(PsiUtils.getMethodReturnClassName(psiMethod))) { return false; } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/constant/JavaClassName.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/constant/JavaClassName.java index 8360806..297cf03 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/constant/JavaClassName.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/constant/JavaClassName.java @@ -16,6 +16,12 @@ public class JavaClassName { public static final String LOCAL_DATE_TYPE = "java.time.LocalDate"; public static final String LOCAL_DATE_TIME_TYPE = "java.time.LocalDateTime"; public static final String BIG_DECIMAL = "java.math.BigDecimal"; + public static final String BASE_INT_TYPE = "int"; + public static final String BASE_LONG_TYPE = "long"; + public static final String BASE_SHORT_TYPE = "short"; + public static final String BASE_BYTE_TYPE = "byte"; + public static final String BASE_DOUBLE_TYPE = "double"; + public static final String BASE_FLOAT_TYPE = "float"; public static final String COLLECTION_TYPE = "java.util.Collection"; public static final String MAP_TYPE = "java.util.Map"; diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/CommonEnum.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/CommonEnum.java new file mode 100644 index 0000000..f470499 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/CommonEnum.java @@ -0,0 +1,11 @@ +package cn.bigcoder.plugin.objecthelper.common.enums; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + * @description: + **/ +public interface CommonEnum { + + String getCode(); +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FieldGenerateModeEnum.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FieldGenerateModeEnum.java new file mode 100644 index 0000000..4ff4899 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FieldGenerateModeEnum.java @@ -0,0 +1,34 @@ +package cn.bigcoder.plugin.objecthelper.common.enums; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + **/ +public enum FieldGenerateModeEnum implements CommonEnum { + SOURCE("source"), + TARGET("target"), + ; + private String code; + + FieldGenerateModeEnum(String code) { + this.code = code; + } + + + public static FieldGenerateModeEnum nameOf(String modify) { + if (modify == null) { + return null; + } + for (FieldGenerateModeEnum item : values()) { + if (modify.equals(item.getCode())) { + return item; + } + } + return null; + } + + @Override + public String getCode() { + return code; + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FunctionSwitchEnum.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FunctionSwitchEnum.java new file mode 100644 index 0000000..866c40f --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/FunctionSwitchEnum.java @@ -0,0 +1,32 @@ +package cn.bigcoder.plugin.objecthelper.common.enums; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + **/ +public enum FunctionSwitchEnum implements CommonEnum { + OPEN("open"), + CLOSE("close"), + ; + private String code; + + FunctionSwitchEnum(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public static FunctionSwitchEnum nameOf(String modify) { + if (modify == null) { + return null; + } + for (FunctionSwitchEnum item : values()) { + if (modify.equals(item.getCode())) { + return item; + } + } + return null; + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModify.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModifyEnum.java similarity index 77% rename from src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModify.java rename to src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModifyEnum.java index f5d106a..c599104 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModify.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/JavaModifyEnum.java @@ -4,7 +4,7 @@ * @author: Jindong.Tian * @date: 2021-01-09 **/ -public enum JavaModify { +public enum JavaModifyEnum { PUBLIC("public", 1), PROTECTED("protected", 1), PRIVATE("private", 1), @@ -14,7 +14,7 @@ public enum JavaModify { private String name; private Integer priority; - JavaModify(String name, Integer priority) { + JavaModifyEnum(String name, Integer priority) { this.name = name; this.priority = priority; } @@ -23,11 +23,11 @@ public String getName() { return name; } - public JavaModify nameOf(String modify){ + public JavaModifyEnum nameOf(String modify){ if (modify == null){ return null; } - for (JavaModify item : values()) { + for (JavaModifyEnum item : values()) { if (modify.equals(item.getName())){ return item; } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/ObjectCopyStrategyEnum.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/ObjectCopyStrategyEnum.java new file mode 100644 index 0000000..2cb0bd6 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/ObjectCopyStrategyEnum.java @@ -0,0 +1,17 @@ +package cn.bigcoder.plugin.objecthelper.common.enums; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + **/ +public enum ObjectCopyStrategyEnum { + /** + * 普通SET模式 + */ + SET, + /** + * builder模式 + */ + BUILDER, + ; +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/WhetherEnum.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/WhetherEnum.java new file mode 100644 index 0000000..918c484 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/enums/WhetherEnum.java @@ -0,0 +1,32 @@ +package cn.bigcoder.plugin.objecthelper.common.enums; + +/** + * @author: Jindong.Tian + * @date: 2023-12-24 + **/ +public enum WhetherEnum implements CommonEnum { + YES("yes"), + NO("no"), + ; + private String code; + + WhetherEnum(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public static WhetherEnum nameOf(String modify) { + if (modify == null) { + return null; + } + for (WhetherEnum item : values()) { + if (modify.equals(item.getCode())) { + return item; + } + } + return null; + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/exception/ObjectHeplerPluginException.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/exception/ObjectHeplerPluginException.java new file mode 100644 index 0000000..08d0c3d --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/exception/ObjectHeplerPluginException.java @@ -0,0 +1,28 @@ +package cn.bigcoder.plugin.objecthelper.common.exception; + +/** + * @author: Jindong.Tian + * @date: 2024-05-05 + **/ +public class ObjectHeplerPluginException extends RuntimeException{ + + public ObjectHeplerPluginException() { + } + + public ObjectHeplerPluginException(String message) { + super(message); + } + + public ObjectHeplerPluginException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectHeplerPluginException(Throwable cause) { + super(cause); + } + + public ObjectHeplerPluginException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/NotificationUtils.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/NotificationUtils.java index 78b2453..f0b9d48 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/NotificationUtils.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/NotificationUtils.java @@ -1,7 +1,7 @@ package cn.bigcoder.plugin.objecthelper.common.util; -import com.intellij.notification.NotificationDisplayType; import com.intellij.notification.NotificationGroup; +import com.intellij.notification.NotificationGroupManager; import com.intellij.notification.NotificationType; import com.intellij.openapi.project.Project; @@ -14,7 +14,8 @@ public class NotificationUtils { /** * 从2020.3版本方式,通知组改由Plugin.xml注册。详见:https://plugins.jetbrains.com/docs/intellij/notifications.html#top-level-notifications */ - private static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup("ObjectHelper Notification Group", NotificationDisplayType.BALLOON, true); + private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroupManager.getInstance() + .getNotificationGroup("ObjectHelper Notification Group"); public static void notifyInfo(Project project, String content) { NOTIFICATION_GROUP.createNotification(content, NotificationType.INFORMATION).notify(project); diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiTypeUtils.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiTypeUtils.java index 0f00f1a..9dccef7 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiTypeUtils.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiTypeUtils.java @@ -4,14 +4,17 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiType; -import org.apache.commons.lang.time.DateFormatUtils; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import org.apache.commons.lang3.time.DateFormatUtils; import static cn.bigcoder.plugin.objecthelper.common.constant.JavaClassName.*; +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaClassName.BASE_BYTE_TYPE; /** * @author: Jindong.Tian @@ -19,6 +22,29 @@ **/ public class PsiTypeUtils { + private static final Set DATA_TYPES; + + static { + DATA_TYPES = new HashSet<>(); + DATA_TYPES.add(STRING_TYPE); + DATA_TYPES.add(INTEGER_TYPE); + DATA_TYPES.add(BASE_INT_TYPE); + DATA_TYPES.add(LONG_TYPE); + DATA_TYPES.add(BASE_LONG_TYPE); + DATA_TYPES.add(SHORT_TYPE); + DATA_TYPES.add(BASE_SHORT_TYPE); + DATA_TYPES.add(BYTE_TYPE); + DATA_TYPES.add(BASE_BYTE_TYPE); + DATA_TYPES.add(DOUBLE_TYPE); + DATA_TYPES.add(BASE_DOUBLE_TYPE); + DATA_TYPES.add(FLOAT_TYPE); + DATA_TYPES.add(BASE_FLOAT_TYPE); + DATA_TYPES.add(DATE_TYPE); + DATA_TYPES.add(LOCAL_DATE_TYPE); + DATA_TYPES.add(LOCAL_DATE_TIME_TYPE); + DATA_TYPES.add(BIG_DECIMAL); + } + /** * 获取数据类型的默认值 * @@ -33,17 +59,23 @@ public static Object getDataTypeDefaultValue(String canonicalText) { case STRING_TYPE: return ""; case INTEGER_TYPE: + case BASE_INT_TYPE: return 1; case LONG_TYPE: + case BASE_LONG_TYPE: return 1L; case SHORT_TYPE: + case BASE_SHORT_TYPE: return (short) 1; case BYTE_TYPE: + case BASE_BYTE_TYPE: return (byte) 1; case DOUBLE_TYPE: - return 1.0; + case BASE_DOUBLE_TYPE: + return 1.1; case FLOAT_TYPE: - return 1.0f; + case BASE_FLOAT_TYPE: + return 1.1f; case DATE_TYPE: return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"); case LOCAL_DATE_TYPE: @@ -62,21 +94,7 @@ public static Object getDataTypeDefaultValue(String canonicalText) { * @return */ public static boolean isDataType(PsiType psiType) { - String canonicalName = psiType.getCanonicalText(); - if (STRING_TYPE.equals(canonicalName) - || INTEGER_TYPE.equals(canonicalName) - || LONG_TYPE.equals(canonicalName) - || SHORT_TYPE.equals(canonicalName) - || BYTE_TYPE.equals(canonicalName) - || DOUBLE_TYPE.equals(canonicalName) - || FLOAT_TYPE.equals(canonicalName) - || DATE_TYPE.equals(canonicalName) - || LOCAL_DATE_TYPE.equals(canonicalName) - || LOCAL_DATE_TIME_TYPE.equals(canonicalName) - || BIG_DECIMAL.equals(canonicalName)) { - return true; - } - return false; + return DATA_TYPES.contains(psiType.getCanonicalText()); } /** @@ -132,11 +150,12 @@ public static boolean isMapType(PsiType psiType) { /** * 判断一个类是否是指定类型子类 - * @param psiType psiType + * + * @param psiType psiType * @param qualifiedName 全限定名称 * @return */ - public static boolean isSpecifiedType(PsiType psiType, String qualifiedName){ + public static boolean isSpecifiedType(PsiType psiType, String qualifiedName) { if (!(psiType instanceof PsiClassType)) { return false; } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiUtils.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiUtils.java index a727e5c..c0cc060 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiUtils.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiUtils.java @@ -1,7 +1,7 @@ package cn.bigcoder.plugin.objecthelper.common.util; import cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord; -import cn.bigcoder.plugin.objecthelper.common.enums.JavaModify; +import cn.bigcoder.plugin.objecthelper.common.enums.JavaModifyEnum; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.actionSystem.PlatformDataKeys; @@ -12,7 +12,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiIdentifier; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiModifierList; import com.intellij.psi.PsiParameter; import com.intellij.psi.PsiType; @@ -24,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.jetbrains.annotations.Nullable; /** * @author: Jindong.Tian @@ -152,6 +155,21 @@ public static String getMethodReturnClassName(PsiMethod psiMethod) { return returnType.getPresentableText(); } + /** + * 获取PsiClass 名称 + * + * @param psiClass + * @return + */ + @Nullable + public static String getPsiClassName(PsiClass psiClass) { + PsiIdentifier nameIdentifier = psiClass.getNameIdentifier(); + if (nameIdentifier == null) { + return null; + } + return nameIdentifier.getText(); + } + /** * 获取方法的参数列表 * @@ -170,20 +188,20 @@ public static List getPsiParameters(PsiMethod psiMethod) { * @return */ @NotNull - public static List getMethodModifies(PsiModifierList modifierList) { - List result = new ArrayList<>(); - if (modifierList.hasModifierProperty(JavaModify.PUBLIC.getName())) { - result.add(JavaModify.PUBLIC); - } else if (modifierList.hasModifierProperty(JavaModify.PROTECTED.getName())) { - result.add(JavaModify.PROTECTED); - } else if (modifierList.hasModifierProperty(JavaModify.PRIVATE.getName())) { - result.add(JavaModify.PRIVATE); + public static List getMethodModifies(PsiModifierList modifierList) { + List result = new ArrayList<>(); + if (modifierList.hasModifierProperty(JavaModifyEnum.PUBLIC.getName())) { + result.add(JavaModifyEnum.PUBLIC); + } else if (modifierList.hasModifierProperty(JavaModifyEnum.PROTECTED.getName())) { + result.add(JavaModifyEnum.PROTECTED); + } else if (modifierList.hasModifierProperty(JavaModifyEnum.PRIVATE.getName())) { + result.add(JavaModifyEnum.PRIVATE); } - if (modifierList.hasModifierProperty(JavaModify.STATIC.getName())) { - result.add(JavaModify.STATIC); + if (modifierList.hasModifierProperty(JavaModifyEnum.STATIC.getName())) { + result.add(JavaModifyEnum.STATIC); } - if (modifierList.hasModifierProperty(JavaModify.FINAL.getName())) { - result.add(JavaModify.FINAL); + if (modifierList.hasModifierProperty(JavaModifyEnum.FINAL.getName())) { + result.add(JavaModifyEnum.FINAL); } return result; } @@ -201,6 +219,23 @@ public static List getAllPsiFields(PsiClass psiClass) { return result; } + /** + * 判断一个字段是否是类的成员属性 + * + * @param psiField + * @return + */ + public static boolean isMemberField(PsiField psiField) { + PsiModifierList modifierList = psiField.getModifierList(); + if (modifierList == null || + modifierList.hasModifierProperty(PsiModifier.STATIC) || + modifierList.hasModifierProperty(PsiModifier.FINAL) || + modifierList.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { + return false; + } + return true; + } + /** * 递归获取类中所有字段 * diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/XMLUtils.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/XMLUtils.java index d1ec63f..d55f516 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/XMLUtils.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/XMLUtils.java @@ -1,16 +1,10 @@ package cn.bigcoder.plugin.objecthelper.common.util; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.IOException; -import java.io.StringWriter; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.Map; /** @@ -18,45 +12,33 @@ * @date: 2022-08-26 **/ public class XMLUtils { - /** - * 将Map转换为XML格式的字符串 - * - * @param data Map类型数据 - * @return XML格式的字符串 - * @throws Exception - */ - public static String mapToXml(Map data) { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - String output = null; //.replaceAll("\n|\r", ""); - try { - DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder(); - org.w3c.dom.Document document = documentBuilder.newDocument(); - org.w3c.dom.Element root = document.createElement("xml"); - document.appendChild(root); - for (String key: data.keySet()) { - String value = data.get(key).toString(); - value = value.trim(); - org.w3c.dom.Element filed = document.createElement(key); - filed.appendChild(document.createTextNode(value)); - root.appendChild(filed); - } - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - DOMSource source = new DOMSource(document); - transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - StringWriter writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - transformer.transform(source, result); - output = writer.getBuffer().toString(); - writer.close(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (TransformerException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + + /** + * 将Map转换为XML格式的字符串 + * + * @param data Map类型数据 + * @return XML格式的字符串 + * @throws Exception + */ + public static String mapToXml(Map data) { + ObjectMapper objectMapper = new XmlMapper(); + // 修正根元素名称 + objectMapper.addMixIn(Map.class, MapMixin.class); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + String xmlString = ""; + try { + xmlString = objectMapper.writeValueAsString(data); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + return xmlString; + } + + /** + * 用于修正根元素名称 + */ + @JacksonXmlRootElement(localName = "root") + public static abstract class MapMixin { + } - return output; - } } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/config/ObjectHelperConfigurable.java b/src/main/java/cn/bigcoder/plugin/objecthelper/config/ObjectHelperConfigurable.java index 7d2b187..46b9b29 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/config/ObjectHelperConfigurable.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/config/ObjectHelperConfigurable.java @@ -44,10 +44,13 @@ public boolean isModified() { public void apply() { PluginConfigModel instance = PluginConfigState.getInstance(); PluginConfigModel currentConfigModel = configPage.getCurrentConfigModel(); - instance.setJsonSwitch(currentConfigModel.isJsonSwitch()); - instance.setThriftSwitch(currentConfigModel.isThriftSwitch()); - instance.setXmlSwitch(currentConfigModel.isXmlSwitch()); - instance.setObjectCopySwitch(currentConfigModel.isObjectCopySwitch()); + instance.setJsonSwitch(currentConfigModel.getJsonSwitch()); + instance.setThriftSwitch(currentConfigModel.getThriftSwitch()); + instance.setXmlSwitch(currentConfigModel.getXmlSwitch()); + instance.setObjectCopySwitch(currentConfigModel.getObjectCopySwitch()); + instance.setObjectCopyMethodFieldGenerateAnnotation(currentConfigModel.getObjectCopyMethodFieldGenerateAnnotation()); + instance.setObjectCopyMethodFieldGenerateMode(currentConfigModel.getObjectCopyMethodFieldGenerateMode()); + instance.setBuilderInstanceMethodName(currentConfigModel.getBuilderInstanceMethodName()); } } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/config/PluginConfigModel.java b/src/main/java/cn/bigcoder/plugin/objecthelper/config/PluginConfigModel.java index ef25e8e..66fc4b6 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/config/PluginConfigModel.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/config/PluginConfigModel.java @@ -1,5 +1,8 @@ package cn.bigcoder.plugin.objecthelper.config; +import cn.bigcoder.plugin.objecthelper.common.enums.FieldGenerateModeEnum; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; +import cn.bigcoder.plugin.objecthelper.common.enums.WhetherEnum; import java.util.Objects; /** @@ -7,65 +10,115 @@ * @date: 2022-08-31 **/ public class PluginConfigModel { + /** * 是否开启 Class To Json 功能,默认为开启状态 */ - private boolean jsonSwitch = true; + private FunctionSwitchEnum jsonSwitch = FunctionSwitchEnum.OPEN; /** * 是否开启 Class To Thrift IDL 功能,默认为开启状态 */ - private boolean thriftSwitch = true; + private FunctionSwitchEnum thriftSwitch = FunctionSwitchEnum.OPEN; /** * 是否开启 Class To XML 功能,默认为开启状态 */ - private boolean xmlSwitch = true; + private FunctionSwitchEnum xmlSwitch = FunctionSwitchEnum.OPEN; /** * 是否开启 Object Copy Method 功能,默认为开启状态 */ - private boolean objectCopySwitch = true; + private FunctionSwitchEnum objectCopySwitch = FunctionSwitchEnum.OPEN; + /** + * Object Copy Method 功能中,以Source/Target对象为基础生成字段拷贝 + */ + private FieldGenerateModeEnum objectCopyMethodFieldGenerateMode = FieldGenerateModeEnum.TARGET; + + /** + * Object Copy Method 功能中,Source 和 Target 对象之间差异的字段,是否以代码注释的形式生成代码 + */ + private WhetherEnum objectCopyMethodFieldGenerateAnnotation = WhetherEnum.YES; - public boolean isJsonSwitch() { + /** + * Object Copy Method 功能中,使用builder模式生成拷贝代码时的判断依据,当目标对象类中包含正则所指定的方法,则默认按照builder模式生成,否则使用set模式生成 + */ + private String builderInstanceMethodName = ".*(builder|newBuilder).*"; + + public FunctionSwitchEnum getJsonSwitch() { return jsonSwitch; } - public void setJsonSwitch(boolean jsonSwitch) { + public void setJsonSwitch(FunctionSwitchEnum jsonSwitch) { this.jsonSwitch = jsonSwitch; } - public boolean isThriftSwitch() { + public FunctionSwitchEnum getThriftSwitch() { return thriftSwitch; } - public void setThriftSwitch(boolean thriftSwitch) { + public void setThriftSwitch(FunctionSwitchEnum thriftSwitch) { this.thriftSwitch = thriftSwitch; } - public boolean isXmlSwitch() { + public FunctionSwitchEnum getXmlSwitch() { return xmlSwitch; } - public void setXmlSwitch(boolean xmlSwitch) { + public void setXmlSwitch(FunctionSwitchEnum xmlSwitch) { this.xmlSwitch = xmlSwitch; } - public boolean isObjectCopySwitch() { + public FunctionSwitchEnum getObjectCopySwitch() { return objectCopySwitch; } - public void setObjectCopySwitch(boolean objectCopySwitch) { + public void setObjectCopySwitch(FunctionSwitchEnum objectCopySwitch) { this.objectCopySwitch = objectCopySwitch; } + public FieldGenerateModeEnum getObjectCopyMethodFieldGenerateMode() { + return objectCopyMethodFieldGenerateMode; + } + + public void setObjectCopyMethodFieldGenerateMode( + FieldGenerateModeEnum objectCopyMethodFieldGenerateMode) { + this.objectCopyMethodFieldGenerateMode = objectCopyMethodFieldGenerateMode; + } + + public WhetherEnum getObjectCopyMethodFieldGenerateAnnotation() { + return objectCopyMethodFieldGenerateAnnotation; + } + + public void setObjectCopyMethodFieldGenerateAnnotation( + WhetherEnum objectCopyMethodFieldGenerateAnnotation) { + this.objectCopyMethodFieldGenerateAnnotation = objectCopyMethodFieldGenerateAnnotation; + } + + public String getBuilderInstanceMethodName() { + return builderInstanceMethodName; + } + + public void setBuilderInstanceMethodName(String builderInstanceMethodName) { + this.builderInstanceMethodName = builderInstanceMethodName; + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PluginConfigModel that = (PluginConfigModel) o; - return jsonSwitch == that.jsonSwitch && thriftSwitch == that.thriftSwitch && xmlSwitch == that.xmlSwitch && objectCopySwitch == that.objectCopySwitch; + return jsonSwitch == that.jsonSwitch && thriftSwitch == that.thriftSwitch && xmlSwitch == that.xmlSwitch + && objectCopySwitch == that.objectCopySwitch + && objectCopyMethodFieldGenerateMode == that.objectCopyMethodFieldGenerateMode + && objectCopyMethodFieldGenerateAnnotation == that.objectCopyMethodFieldGenerateAnnotation + && Objects.equals(builderInstanceMethodName, that.builderInstanceMethodName); } @Override public int hashCode() { - return Objects.hash(jsonSwitch, thriftSwitch, xmlSwitch, objectCopySwitch); + return Objects.hash(jsonSwitch, thriftSwitch, xmlSwitch, objectCopySwitch, objectCopyMethodFieldGenerateMode, + objectCopyMethodFieldGenerateAnnotation, builderInstanceMethodName); } } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java index e7d3384..d490bfe 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java @@ -11,11 +11,11 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.compress.utils.Lists; import org.apache.commons.compress.utils.Sets; -import org.apache.commons.lang.ArrayUtils; - import java.util.List; import java.util.Map; + import java.util.Set; +import org.apache.commons.lang3.ArrayUtils; /** * @author: Jindong.Tian diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractMethodGenerator.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractMethodGenerator.java index abb3ad1..c3912c2 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractMethodGenerator.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractMethodGenerator.java @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiParameter; +import com.intellij.psi.PsiType; import org.apache.commons.collections.CollectionUtils; import java.util.List; @@ -66,4 +67,8 @@ protected boolean check() { protected List getParameters() { return getPsiParameters(psiMethod); } + + protected PsiType getReturnType() { + return psiMethod.getReturnType(); + } } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/AbstractObjectCopyStrategy.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/AbstractObjectCopyStrategy.java new file mode 100644 index 0000000..5e27888 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/AbstractObjectCopyStrategy.java @@ -0,0 +1,98 @@ +package cn.bigcoder.plugin.objecthelper.generator.copy; + +import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getPsiClassName; + +import cn.bigcoder.plugin.objecthelper.common.enums.FieldGenerateModeEnum; +import cn.bigcoder.plugin.objecthelper.common.enums.WhetherEnum; +import cn.bigcoder.plugin.objecthelper.common.util.PsiUtils; +import cn.bigcoder.plugin.objecthelper.common.util.StringUtils; +import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; +import cn.bigcoder.plugin.objecthelper.generator.Generator; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author: Jindong.Tian + * @date: 2024-05-05 + **/ +public abstract class AbstractObjectCopyStrategy implements Generator { + + /** + * 对象拷贝源对象类型 + */ + protected PsiClass sourceClass; + /** + * 对象拷贝目标对象类型 + */ + protected PsiClass targetClass; + /** + * 对象拷贝源参数名称 + */ + protected String sourceParamName; + /** + * 对象拷贝目标参数名称 + */ + protected String targetParamName; + + public AbstractObjectCopyStrategy(PsiClass sourceClass, PsiClass targetClass, String sourceParamName) { + this.sourceClass = sourceClass; + this.targetClass = targetClass; + this.sourceParamName = sourceParamName; + // 生成参数名 + this.targetParamName = StringUtils.firstLowerCase(Objects.requireNonNull(getPsiClassName(targetClass))); + // 防止方法入参和返回参数名称一致 + if (sourceParamName.equals(this.targetParamName)) { + this.targetParamName = this.targetParamName + "Res"; + } + } + + @Override + public String generate() { + StringBuilder result = new StringBuilder(); + // 生成前缀 + result.append(generatePrefix()); + + // 字段copy模式 + FieldGenerateModeEnum generateModeEnum = PluginConfigState.getInstance().getObjectCopyMethodFieldGenerateMode(); + + // mainClass 代表以哪个类字段为基础生成字段拷贝代码 + PsiClass mainClass = targetClass; + PsiClass secondClass = sourceClass; + if (generateModeEnum == FieldGenerateModeEnum.SOURCE) { + // 字段拷贝使用源字段为蓝本拷贝 + mainClass = sourceClass; + secondClass = targetClass; + } + + Set secondFieldNames = PsiUtils.getAllPsiFields(secondClass).stream().filter(PsiUtils::isMemberField) + .map(PsiField::getName).collect(Collectors.toSet()); + + List annotationLine = new LinkedList<>(); + for (PsiField field : PsiUtils.getAllPsiFields(mainClass)) { + if (!PsiUtils.isMemberField(field)) { + continue; + } + if (secondFieldNames.contains(field.getName())) { + result.append(generateFiledCopy(field)); + } else if (PluginConfigState.getInstance().getObjectCopyMethodFieldGenerateAnnotation() + == WhetherEnum.YES) { + // 如果源对象没有该字段,且开启了以注释模式生成代码的开关,则生成注释 + annotationLine.add("// " + generateFiledCopy(field)); + } + } + annotationLine.forEach(result::append); + result.append(generateSuffix()); + return result.toString(); + } + + protected abstract String generatePrefix(); + + protected abstract String generateFiledCopy(PsiField field); + + protected abstract String generateSuffix(); +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/BuilderObjectCopyStrategy.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/BuilderObjectCopyStrategy.java new file mode 100644 index 0000000..fb72f61 --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/BuilderObjectCopyStrategy.java @@ -0,0 +1,60 @@ +package cn.bigcoder.plugin.objecthelper.generator.copy.strategy; + +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.BLANK_SEPARATOR; +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.LINE_SEPARATOR; +import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getPsiClassName; + +import cn.bigcoder.plugin.objecthelper.common.util.StringUtils; +import cn.bigcoder.plugin.objecthelper.generator.copy.AbstractObjectCopyStrategy; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; + +/** + * @author: Jindong.Tian + * @date: 2024-05-05 + **/ +public class BuilderObjectCopyStrategy extends AbstractObjectCopyStrategy { + + public BuilderObjectCopyStrategy(PsiClass sourceClass, PsiClass targetClass, String sourceParamName) { + super(sourceClass, targetClass, sourceParamName); + } + + + /** + * 生成类似如下代码: + * + * if (user == null) { + * return null; + * } + * return UserDto.builder() + * + * @return + */ + @Override + protected String generatePrefix() { + return generateNullCheck(sourceParamName) + LINE_SEPARATOR + + "return" + BLANK_SEPARATOR + getPsiClassName(targetClass) + ".builder()" + LINE_SEPARATOR; + } + + @Override + protected String generateFiledCopy(PsiField field) { + return "." + field.getName() + "(" + + sourceParamName + ".get" + StringUtils.firstUpperCase(field.getName()) + "())" + + LINE_SEPARATOR; + } + + + @Override + protected String generateSuffix() { + return ".build();" + LINE_SEPARATOR; + } + + /** + * 生成示例:{@code if (user == null) {return null;}} + * + * @return + */ + private String generateNullCheck(String sourceParamName) { + return "if(" + sourceParamName + "==null){return null;}"; + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/SetObjectCopyStrategy.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/SetObjectCopyStrategy.java new file mode 100644 index 0000000..48dc32a --- /dev/null +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/copy/strategy/SetObjectCopyStrategy.java @@ -0,0 +1,59 @@ +package cn.bigcoder.plugin.objecthelper.generator.copy.strategy; + +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.BLANK_SEPARATOR; +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.LINE_SEPARATOR; +import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.SEMICOLON_SEPARATOR; +import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getPsiClassName; + +import cn.bigcoder.plugin.objecthelper.common.util.StringUtils; +import cn.bigcoder.plugin.objecthelper.generator.copy.AbstractObjectCopyStrategy; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; + +/** + * @author: Jindong.Tian + * @date: 2024-05-05 + **/ +public class SetObjectCopyStrategy extends AbstractObjectCopyStrategy { + + public SetObjectCopyStrategy(PsiClass sourceClass, PsiClass targetClass, String sourceParamName) { + super(sourceClass, targetClass, sourceParamName); + } + + /** + * 生成类似如下代码: + * + * if (user == null) { + * return null; + * } + * UserDto userDto = new UserDto(); + * + * @return + */ + @Override + protected String generatePrefix() { + String psiClassName = getPsiClassName(targetClass); + return generateNullCheck(sourceParamName) + LINE_SEPARATOR + + psiClassName + BLANK_SEPARATOR + targetParamName + "= new " + psiClassName + "();" + LINE_SEPARATOR; + } + + @Override + protected String generateFiledCopy(PsiField field) { + return targetParamName + ".set" + StringUtils.firstUpperCase(field.getName()) + "(" + sourceParamName + ".get" + StringUtils.firstUpperCase(field.getName()) + "());" + LINE_SEPARATOR; + } + + + @Override + protected String generateSuffix() { + return "return " + targetParamName + SEMICOLON_SEPARATOR; + } + + /** + * 生成示例:{@code if (user == null) {return null;}} + * + * @return + */ + private String generateNullCheck(String sourceParamName) { + return "if(" + sourceParamName + "==null){return null;}"; + } +} diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/idl/ThriftIDLGenerator.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/idl/ThriftIDLGenerator.java index 6ab6a57..0679bdd 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/idl/ThriftIDLGenerator.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/idl/ThriftIDLGenerator.java @@ -12,10 +12,10 @@ import com.intellij.psi.impl.source.PsiClassReferenceType; import org.apache.commons.compress.utils.Lists; import org.apache.commons.compress.utils.Sets; -import org.apache.commons.lang.ArrayUtils; import java.util.List; import java.util.Set; +import org.apache.commons.lang3.ArrayUtils; /** * @author: Jindong.Tian @@ -46,6 +46,9 @@ public String generate() { * @return */ private StringBuilder generateStructCode(PsiClass psiClass) { + if (psiClass == null) { + return new StringBuilder(); + } if (recursiveCache.contains(psiClass.getQualifiedName())) { return new StringBuilder(); } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/method/ObjectCopyMethodGenerator.java b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/method/ObjectCopyMethodGenerator.java index 1203fd6..63a4b78 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/method/ObjectCopyMethodGenerator.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/method/ObjectCopyMethodGenerator.java @@ -1,19 +1,16 @@ package cn.bigcoder.plugin.objecthelper.generator.method; -import cn.bigcoder.plugin.objecthelper.common.util.PsiUtils; -import cn.bigcoder.plugin.objecthelper.common.util.StringUtils; +import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getPsiClass; + +import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.generator.AbstractMethodGenerator; +import cn.bigcoder.plugin.objecthelper.generator.copy.AbstractObjectCopyStrategy; +import cn.bigcoder.plugin.objecthelper.generator.copy.strategy.BuilderObjectCopyStrategy; +import cn.bigcoder.plugin.objecthelper.generator.copy.strategy.SetObjectCopyStrategy; import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiModifierList; import com.intellij.psi.PsiParameter; -import org.jetbrains.annotations.NotNull; - -import static cn.bigcoder.plugin.objecthelper.common.constant.JavaKeyWord.*; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getMethodReturnClassName; -import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.getPsiClass; +import java.util.regex.Pattern; /** * @author: Jindong.Tian @@ -25,10 +22,6 @@ public class ObjectCopyMethodGenerator extends AbstractMethodGenerator { * 方法第一个参数名称 */ private String firstParameterName; - /** - * 方法返回局部变量名称 - */ - private String returnObjName; private void init(PsiMethod psiMethod) { if (psiMethod == null) { @@ -37,11 +30,6 @@ private void init(PsiMethod psiMethod) { super.project = psiMethod.getProject(); super.psiMethod = psiMethod; this.firstParameterName = getFirstParameter().getName(); - this.returnObjName = StringUtils.firstLowerCase(getMethodReturnClassName(psiMethod)); - // 防止方法入参和返回参数名称一致 - if (firstParameterName.equals(returnObjName)) { - this.returnObjName = this.returnObjName + "1"; - } } public static ObjectCopyMethodGenerator getInstance(PsiMethod psiMethod) { @@ -57,61 +45,23 @@ public static ObjectCopyMethodGenerator getInstance(PsiMethod psiMethod) { */ @Override protected String generateMethodBody() { - StringBuilder result = new StringBuilder(); - result.append(generateNullCheck()); - result.append(generateObjectCreateLine()); - for (PsiField field : PsiUtils.getAllPsiFields(getFirstParameterClass())) { - PsiModifierList modifierList = field.getModifierList(); - if (modifierList == null || - modifierList.hasModifierProperty(PsiModifier.STATIC) || - modifierList.hasModifierProperty(PsiModifier.FINAL) || - modifierList.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { - continue; - } - result.append(generateFieldCopyLine(field)); - } - result.append(generateReturnLine()); - return result.toString(); + AbstractObjectCopyStrategy copyStrategy = getCopyStrategy(); + return copyStrategy.generate(); } - /** - * 生成示例:{@code UserDTO userDTO = new UserDTO();} - * - * @return - */ - @NotNull - private String generateObjectCreateLine() { - return getMethodReturnClassName(psiMethod) + BLANK_SEPARATOR + returnObjName + "= new " + getMethodReturnClassName(psiMethod) + "();" + LINE_SEPARATOR; - } + private AbstractObjectCopyStrategy getCopyStrategy() { + // mainClass 代表以哪个类字段为基础生成字段拷贝代码 + PsiClass returnClass = getReturnClass(); + PsiClass sourceClass = getFirstParameterClass(); + String builderRegex = PluginConfigState.getInstance().getBuilderInstanceMethodName(); - /** - * 生成示例:{@code userDTO.setId(user.getId());} - * - * @param field - * @return - */ - @NotNull - private String generateFieldCopyLine(PsiField field) { - return returnObjName + ".set" + StringUtils.firstUpperCase(field.getName()) + "(" + firstParameterName + ".get" + StringUtils.firstUpperCase(field.getName()) + "());" + LINE_SEPARATOR; - } - - /** - * 生成示例:{@code return userDTO;} - * - * @return - */ - @NotNull - private String generateReturnLine() { - return "return " + returnObjName + SEMICOLON_SEPARATOR; - } - - /** - * 生成示例:{@code if (user == null) {return null;}} - * - * @return - */ - private String generateNullCheck() { - return "if(" + getFirstParameter().getName() + "==null){return null;}"; + Pattern pattern = Pattern.compile(builderRegex); + for (PsiMethod method : returnClass.getMethods()) { + if (pattern.matcher(method.getName()).matches()) { + return new BuilderObjectCopyStrategy(sourceClass, returnClass, this.firstParameterName); + } + } + return new SetObjectCopyStrategy(sourceClass, returnClass, this.firstParameterName); } /** @@ -123,6 +73,7 @@ private PsiParameter getFirstParameter() { return getParameters().get(FIRST_INDEX); } + /** * 获取参数列表第一个参数的{@code PsiClass} * @@ -131,4 +82,8 @@ private PsiParameter getFirstParameter() { private PsiClass getFirstParameterClass() { return getPsiClass(getFirstParameter().getType(), project); } + + private PsiClass getReturnClass() { + return getPsiClass(getReturnType(), project); + } } \ No newline at end of file diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.form b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.form index f4c3584..ec970d0 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.form +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.form @@ -8,15 +8,24 @@ - + + + + + + + + + + - + - + @@ -47,7 +56,7 @@ - + @@ -60,7 +69,7 @@ - + @@ -72,7 +81,7 @@ - + @@ -93,7 +102,7 @@ - + @@ -103,6 +112,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.java b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.java index 8ccee25..985abb4 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ConfigPage.java @@ -1,8 +1,12 @@ package cn.bigcoder.plugin.objecthelper.ui; +import cn.bigcoder.plugin.objecthelper.common.enums.FieldGenerateModeEnum; +import cn.bigcoder.plugin.objecthelper.common.enums.FunctionSwitchEnum; +import cn.bigcoder.plugin.objecthelper.common.enums.WhetherEnum; import cn.bigcoder.plugin.objecthelper.config.PluginConfigState; import cn.bigcoder.plugin.objecthelper.config.PluginConfigModel; +import java.util.Optional; import javax.swing.*; /** @@ -11,13 +15,15 @@ **/ public class ConfigPage { - private static final String OPEN_STATUS = "open"; - private JPanel mainPanel; private JComboBox classToJsonSwitch; private JComboBox classToThriftSwitch; private JComboBox classToXmlSwitch; private JComboBox objectCopyMethodSwitch; + private JButton tipsButton; + private JComboBox objectCopyMethodGenerateMode; + private JComboBox objectCopyMethodGenerateAnnotation; + private JTextField builderInstanceMethodName; public JPanel getMainPanel() { initField(); @@ -29,10 +35,13 @@ public JPanel getMainPanel() { */ public void initField() { PluginConfigModel instance = PluginConfigState.getInstance(); - this.classToJsonSwitch.setSelectedItem(convertComboBoxItem(instance.isJsonSwitch())); - this.classToThriftSwitch.setSelectedItem(convertComboBoxItem(instance.isThriftSwitch())); - this.classToXmlSwitch.setSelectedItem(convertComboBoxItem(instance.isXmlSwitch())); - this.objectCopyMethodSwitch.setSelectedItem(convertComboBoxItem(instance.isObjectCopySwitch())); + this.classToJsonSwitch.setSelectedItem(instance.getJsonSwitch().getCode()); + this.classToThriftSwitch.setSelectedItem(instance.getThriftSwitch().getCode()); + this.classToXmlSwitch.setSelectedItem(instance.getXmlSwitch().getCode()); + this.objectCopyMethodSwitch.setSelectedItem(instance.getObjectCopySwitch().getCode()); + this.objectCopyMethodGenerateAnnotation.setSelectedItem(instance.getObjectCopyMethodFieldGenerateAnnotation().getCode()); + this.objectCopyMethodGenerateMode.setSelectedItem(instance.getObjectCopyMethodFieldGenerateMode().getCode()); + this.builderInstanceMethodName.setText(instance.getBuilderInstanceMethodName()); } /** @@ -42,17 +51,35 @@ public void initField() { */ public PluginConfigModel getCurrentConfigModel() { PluginConfigModel pluginConfigModel = new PluginConfigModel(); - pluginConfigModel.setJsonSwitch(this.classToJsonSwitch.getSelectedItem().equals(OPEN_STATUS)); - pluginConfigModel.setThriftSwitch(this.classToThriftSwitch.getSelectedItem().equals(OPEN_STATUS)); - pluginConfigModel.setXmlSwitch(this.classToXmlSwitch.getSelectedItem().equals(OPEN_STATUS)); - pluginConfigModel.setObjectCopySwitch(this.objectCopyMethodSwitch.getSelectedItem().equals(OPEN_STATUS)); + + Optional.ofNullable(this.classToJsonSwitch.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setJsonSwitch(FunctionSwitchEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.classToThriftSwitch.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setThriftSwitch(FunctionSwitchEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.classToXmlSwitch.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setXmlSwitch(FunctionSwitchEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.objectCopyMethodSwitch.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setObjectCopySwitch(FunctionSwitchEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.objectCopyMethodGenerateMode.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setObjectCopyMethodFieldGenerateMode(FieldGenerateModeEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.objectCopyMethodGenerateAnnotation.getSelectedItem()).ifPresent(e -> { + pluginConfigModel.setObjectCopyMethodFieldGenerateAnnotation(WhetherEnum.nameOf(e.toString())); + } + ); + Optional.ofNullable(this.builderInstanceMethodName.getText()).ifPresent( + pluginConfigModel::setBuilderInstanceMethodName + ); return pluginConfigModel; } - private static String convertComboBoxItem(boolean switchTag) { - if (switchTag) { - return "open"; - } - return "close"; - } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9fcb614..1581439 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,7 +1,7 @@ cn.bigcoder.plugin.objecthelper ObjectHelper - 1.3.0 + 1.3.2 HearingSmile New feature:Added the ability to quickly convert Java classes to XML -
  • New feature:Customize to enable specified functions
  • +
  • add feature:Optimize the class to xml generation results
  • +
  • fix feature:Optimize the class to xml generation results
  • +
  • fix bug:Fix class to Thrift-IDL function NPE problem
  • ]]>
    - + @@ -37,6 +38,10 @@ instance="cn.bigcoder.plugin.objecthelper.config.ObjectHelperConfigurable"/> + +