From f8cca7501fb6e2590acdb8b448f4e4906d6cc960 Mon Sep 17 00:00:00 2001 From: "Jindong.Tian" Date: Sat, 21 Jun 2025 22:02:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E6=94=B9=E5=96=84=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=201.=20=E4=BF=AE=E5=A4=8D=20Class=20To=20Jso?= =?UTF-8?q?n=20=E5=AF=B9boolean=E7=B1=BB=E5=9E=8B=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=202.=20=E6=96=B0=E5=A2=9E=20Class=20To=20Jso?= =?UTF-8?q?n=20=E5=AF=B9Map=E7=B1=BB=E5=9E=8B=E5=AD=97=E6=AE=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=203.=20=E4=BC=98=E5=8C=96=20Object=20Copy=20=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E4=BB=A3=E7=A0=81=E4=BD=93=E9=AA=8C=204.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8F=92=E4=BB=B6=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- build.gradle | 9 +- .../action/AbstractClassAnAction.java | 7 + .../objecthelper/action/ObjectCopyAction.java | 124 ++++++++++++---- .../common/constant/JavaClassName.java | 2 + .../common/util/PsiTypeUtils.java | 5 + .../AbstractDataObjectGenerator.java | 134 +++++++++++------- .../objecthelper/ui/ClassSearchDialog.java | 83 ++++++++--- src/main/resources/META-INF/plugin.xml | 4 +- 9 files changed, 272 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index 4ab3a4e..d4be63d 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@
- + - +
JetBrains Intellij ObjectHelper 插件致力于消除开发者重复性的低效工作,助力开发者将更多精力聚焦于核心业务逻辑开发,显著提升开发效率。 diff --git a/build.gradle b/build.gradle index 731142b..44ee143 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group 'cn.bigcoder.plugin' -version '1.4.0' +version '1.4.1' repositories { mavenCentral() @@ -28,10 +28,13 @@ intellij { plugins = ['com.intellij.java'] } patchPluginXml { - sinceBuild = '211' + sinceBuild = '231' untilBuild = '301.*' changeNotes = """ - 1. new feature: Object Copy support lambda and common scene. + 1.Fixed the support for boolean type fields in class to json conversion. + 2.Added support for Map type fields in class to json conversion. + 3.Optimized the code experience of the Object Copy function. + 4.Optimized the plugin compatibility. """ } test { diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java index 365eeb0..0fe3612 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/AbstractClassAnAction.java @@ -2,6 +2,7 @@ import static cn.bigcoder.plugin.objecthelper.common.util.PsiUtils.setActionInvisible; +import com.intellij.openapi.actionSystem.ActionUpdateThread; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import org.jetbrains.annotations.NotNull; @@ -25,4 +26,10 @@ public void update(@NotNull AnActionEvent anActionEvent) { } super.update(anActionEvent); } + + @Override + public @NotNull ActionUpdateThread getActionUpdateThread() { + return ActionUpdateThread.BGT; + } + } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyAction.java b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyAction.java index 55f8358..6e8f918 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyAction.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/action/ObjectCopyAction.java @@ -9,6 +9,7 @@ import cn.bigcoder.plugin.objecthelper.generator.Generator; import cn.bigcoder.plugin.objecthelper.generator.copy.SmartObjectCopyGenerator; import cn.bigcoder.plugin.objecthelper.ui.ClassSearchDialog; +import com.intellij.openapi.actionSystem.ActionUpdateThread; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.CaretModel; @@ -22,6 +23,7 @@ public class ObjectCopyAction extends AbstractClassAnAction { + @Override public void actionPerformed(@NotNull AnActionEvent anAction) { PsiClass sourcePsiClass = getOperatePsiClass(anAction); @@ -62,6 +64,10 @@ public void actionPerformed(@NotNull AnActionEvent anAction) { * @param copyCodeStr */ private void insertCode(Project project, String copyCodeStr) { + // 检查代码末尾是否有换行符,没有则添加 + if (!copyCodeStr.endsWith("\n")) { + copyCodeStr += "\n"; + } Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); if (editor == null) { return; @@ -69,43 +75,113 @@ private void insertCode(Project project, String copyCodeStr) { CaretModel caretModel = editor.getCaretModel(); int offset = caretModel.getOffset(); Document document = editor.getDocument(); - // 删除光标所在的变量 - int startOffset = findVariableStartOffset(document, offset); - int endOffset = findVariableEndOffset(document, offset); - if (startOffset >= 0 && endOffset >= 0) { + + // 获取当前光标所在行号 + int lineNumber = document.getLineNumber(offset); + int lineStartOffset = document.getLineStartOffset(lineNumber); + int lineEndOffset = document.getLineEndOffset(lineNumber); + + // 检查当前行在光标之后是否有非空白字符 + CharSequence lineText = document.getCharsSequence().subSequence(offset, lineEndOffset); + boolean hasNonWhitespaceAfterCursor = !lineText.toString().trim().isEmpty(); + + // 获取当前行的缩进 + String indent = getLineIndent(document, lineNumber); + // 判断当前行是否为方法头 + String fullLineText = document.getCharsSequence().subSequence(lineStartOffset, lineEndOffset).toString(); + if (isMethodHeader(fullLineText)) { + // 若是方法头,缩进增加一格,假设一格为 4 个空格 + indent += " "; + } + + // 为插入的代码添加缩进 + String indentedCopyCodeStr = addIndentToCode(copyCodeStr, indent); + + if (!hasNonWhitespaceAfterCursor) { + // 如果光标之后没有非空白字符,删除当前行 WriteCommandAction.runWriteCommandAction(project, () -> { - document.deleteString(startOffset, endOffset); + document.deleteString(lineStartOffset, lineEndOffset); }); + offset = lineStartOffset; + } else { + // 如果光标之后有非空白字符,将插入位置移动到下一行开头 + int nextLineStart = document.getLineStartOffset(lineNumber + 1); + offset = nextLineStart; } + int finalOffset = offset; WriteCommandAction.runWriteCommandAction(project, () -> { - document.insertString(offset, copyCodeStr); + document.insertString(finalOffset, indentedCopyCodeStr); }); } - private int findVariableStartOffset(Document document, int offset) { - int start = offset; - while (start > 0) { - char c = document.getCharsSequence().charAt(start - 1); - if (!Character.isJavaIdentifierPart(c)) { - break; - } - start--; + /** + * 获取指定行的缩进 + * @param document 文档对象 + * @param lineNumber 行号 + * @return 缩进字符串 + */ + private String getLineIndent(Document document, int lineNumber) { + int lineStartOffset = document.getLineStartOffset(lineNumber); + int lineEndOffset = document.getLineEndOffset(lineNumber); + CharSequence lineText = document.getCharsSequence().subSequence(lineStartOffset, lineEndOffset); + int indentLength = 0; + while (indentLength < lineText.length() && Character.isWhitespace(lineText.charAt(indentLength))) { + indentLength++; + } + return lineText.subSequence(0, indentLength).toString(); + } + + /** + * 判断当前行是否为方法头 + * @param lineText 当前行的文本内容 + * @return 如果是方法头返回 true,否则返回 false + */ + private boolean isMethodHeader(String lineText) { + // 去除注释内容,避免注释中的括号影响判断 + lineText = removeComments(lineText); + // 去除前后空白字符 + lineText = lineText.trim(); + // 简单判断,包含 ( 和 ) 且不包含 ; 认为是方法头 + return lineText.contains("(") && lineText.contains(")") && !lineText.contains(";"); + } + + + /** + * 移除字符串中的注释内容 + * @param lineText 包含注释的字符串 + * @return 移除注释后的字符串 + */ + private String removeComments(String lineText) { + // 移除单行注释 + int singleCommentIndex = lineText.indexOf("//"); + if (singleCommentIndex != -1) { + lineText = lineText.substring(0, singleCommentIndex); } - return start; + // 移除多行注释开始标记之后的内容(简单处理,不处理嵌套情况) + int multiCommentStartIndex = lineText.indexOf("/*"); + if (multiCommentStartIndex != -1) { + lineText = lineText.substring(0, multiCommentStartIndex); + } + return lineText; } - private int findVariableEndOffset(Document document, int offset) { - int end = offset; - int length = document.getTextLength(); - while (end < length) { - char c = document.getCharsSequence().charAt(end); - if (!Character.isJavaIdentifierPart(c)) { - break; + /** + * 为代码的每一行添加缩进 + * @param code 原始代码 + * @param indent 缩进字符串 + * @return 添加缩进后的代码 + */ + private String addIndentToCode(String code, String indent) { + StringBuilder indentedCode = new StringBuilder(); + String[] lines = code.split("\\r?\\n"); + for (int i = 0; i < lines.length; i++) { + indentedCode.append(indent).append(lines[i]); + if (i < lines.length - 1) { + indentedCode.append("\n"); } - end++; } - return end; + return indentedCode.toString(); } @Override 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 297cf03..a1d4c22 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 @@ -10,6 +10,7 @@ public class JavaClassName { public static final String LONG_TYPE = "java.lang.Long"; public static final String SHORT_TYPE = "java.lang.Short"; public static final String BYTE_TYPE = "java.lang.Byte"; + public static final String BOOLEAN_TYPE = "java.lang.Boolean"; public static final String DOUBLE_TYPE = "java.lang.Double"; public static final String FLOAT_TYPE = "java.lang.Float"; public static final String DATE_TYPE = "java.util.Date"; @@ -22,6 +23,7 @@ public class JavaClassName { 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 BASE_BOOL_TYPE = "boolean"; 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/util/PsiTypeUtils.java b/src/main/java/cn/bigcoder/plugin/objecthelper/common/util/PsiTypeUtils.java index 9dccef7..ea71389 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 @@ -43,6 +43,8 @@ public class PsiTypeUtils { DATA_TYPES.add(LOCAL_DATE_TYPE); DATA_TYPES.add(LOCAL_DATE_TIME_TYPE); DATA_TYPES.add(BIG_DECIMAL); + DATA_TYPES.add(BOOLEAN_TYPE); + DATA_TYPES.add(BASE_BOOL_TYPE); } /** @@ -76,6 +78,9 @@ public static Object getDataTypeDefaultValue(String canonicalText) { case FLOAT_TYPE: case BASE_FLOAT_TYPE: return 1.1f; + case BOOLEAN_TYPE: + case BASE_BOOL_TYPE: + return true; case DATE_TYPE: return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"); case LOCAL_DATE_TYPE: 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 d490bfe..4d88424 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/generator/AbstractDataObjectGenerator.java @@ -1,5 +1,6 @@ package cn.bigcoder.plugin.objecthelper.generator; +import cn.bigcoder.plugin.objecthelper.common.constant.JavaClassName; import cn.bigcoder.plugin.objecthelper.common.util.PsiTypeUtils; import cn.bigcoder.plugin.objecthelper.common.util.PsiUtils; import com.google.common.collect.Maps; @@ -23,66 +24,91 @@ **/ public abstract class AbstractDataObjectGenerator implements Generator { - private PsiClass psiClass; + private PsiClass psiClass; - public AbstractDataObjectGenerator(PsiClass psiClass) { - this.psiClass = psiClass; - } - - /** - * 保存已经解析过的自定义类型名称,防止出现递归嵌套的情况 - */ - private Set recursiveCache = Sets.newHashSet(); + public AbstractDataObjectGenerator(PsiClass psiClass) { + this.psiClass = psiClass; + } - protected Map processFields() { - return processFields(psiClass); - } + /** + * 保存已经解析过的自定义类型名称,防止出现递归嵌套的情况 + */ + private Set recursiveCache = Sets.newHashSet(); - protected Map processFields(PsiClass psiClass) { - Map result = Maps.newLinkedHashMap(); - // 当前类所有字段 - List allPsiFields = PsiUtils.getAllPsiFields(psiClass); - if (CollectionUtils.isEmpty(allPsiFields)) { - return result; + protected Map processFields() { + return processFields(psiClass); } - for (PsiField psiField : allPsiFields) { - result.put(psiField.getName(), processField(psiField.getType())); + + protected Map processFields(PsiClass psiClass) { + Map result = Maps.newLinkedHashMap(); + // 当前类所有字段 + List allPsiFields = PsiUtils.getAllPsiFields(psiClass); + if (CollectionUtils.isEmpty(allPsiFields)) { + return result; + } + for (PsiField psiField : allPsiFields) { + // 过滤掉静态字段 + if (!psiField.hasModifierProperty(com.intellij.psi.PsiModifier.STATIC)) { + result.put(psiField.getName(), processField(psiField.getType())); + } + } + return result; } - return result; - } - private Object processField(PsiType psiType) { - Object defaultValue = null; - if (PsiTypeUtils.isDataType(psiType)) { - //如果是数据类型 - defaultValue = PsiTypeUtils.getDataTypeDefaultValue(psiType.getCanonicalText()); - } else if (PsiTypeUtils.isArrayType(psiType)) { - //如果是数组类型 - List list = Lists.newArrayList(); - PsiClass arrayContentClass = PsiUtils.getPsiClass(((PsiArrayType) psiType).getComponentType(), - psiClass.getProject()); - list.add(PsiTypeUtils.getDataTypeDefaultValue(arrayContentClass.getQualifiedName())); - defaultValue = list; - } else if (PsiTypeUtils.isCollectionType(psiType)) { - defaultValue = Lists.newArrayList(); - //如果是集合类型 - PsiType[] parameters = ((PsiClassReferenceType) psiType).getParameters(); - if (ArrayUtils.isEmpty(parameters)) { + private Object processField(PsiType psiType) { + Object defaultValue = null; + if (PsiTypeUtils.isDataType(psiType)) { + //如果是数据类型 + defaultValue = PsiTypeUtils.getDataTypeDefaultValue(psiType.getCanonicalText()); + } else if (PsiTypeUtils.isArrayType(psiType)) { + //如果是数组类型 + List list = Lists.newArrayList(); + PsiClass arrayContentClass = PsiUtils.getPsiClass(((PsiArrayType) psiType).getComponentType(), + psiClass.getProject()); + if (arrayContentClass == null) { + return list; + } + list.add(PsiTypeUtils.getDataTypeDefaultValue(arrayContentClass.getQualifiedName())); + defaultValue = list; + } else if (PsiTypeUtils.isCollectionType(psiType)) { + defaultValue = Lists.newArrayList(); + //如果是集合类型 + PsiType[] parameters = ((PsiClassReferenceType) psiType).getParameters(); + if (ArrayUtils.isEmpty(parameters)) { + return defaultValue; + } + //获取泛型 + PsiType genericType = parameters[0]; + ((List) defaultValue).add(processField(genericType)); + } else if (PsiTypeUtils.isMapType(psiType)) { + // 如果是 Map 类型 + Map map = Maps.newHashMap(); + PsiType[] parameters = ((PsiClassReferenceType) psiType).getParameters(); + if (ArrayUtils.isNotEmpty(parameters) && parameters.length >= 2) { + // 获取键和值的泛型类型 + PsiType keyType = parameters[0]; + PsiType valueType = parameters[1]; + Object keyDefaultValue; + // 判断 key 类型是否为 String + if (JavaClassName.STRING_TYPE.equals(keyType.getCanonicalText())) { + keyDefaultValue = "key"; + } else { + keyDefaultValue = processField(keyType); + } + Object valueDefaultValue = processField(valueType); + map.put(keyDefaultValue, valueDefaultValue); + } + defaultValue = map; + } else if (!PsiTypeUtils.isJavaOfficialType(psiType)) { + //如果是自定义类型 + if (recursiveCache.contains(psiType.getCanonicalText())) { + //出现递归嵌套 + return null; + } + recursiveCache.add(psiType.getCanonicalText()); + //如果是自定义类 + defaultValue = processFields(PsiUtils.getPsiClass(psiType, psiClass.getProject())); + } return defaultValue; - } - //获取泛型 - PsiType genericType = parameters[0]; - ((List) defaultValue).add(processField(genericType)); - } else if (!PsiTypeUtils.isJavaOfficialType(psiType)) { - //如果是自定义类型 - if (recursiveCache.contains(psiType.getCanonicalText())) { - //出现递归嵌套 - return null; - } - recursiveCache.add(psiType.getCanonicalText()); - //如果是自定义类 - defaultValue = processFields(PsiUtils.getPsiClass(psiType, psiClass.getProject())); } - return defaultValue; - } } diff --git a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ClassSearchDialog.java b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ClassSearchDialog.java index 7e49766..94e978a 100644 --- a/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ClassSearchDialog.java +++ b/src/main/java/cn/bigcoder/plugin/objecthelper/ui/ClassSearchDialog.java @@ -10,24 +10,24 @@ import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBTextField; import com.intellij.util.ArrayUtil; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Timer; import java.util.TimerTask; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import org.jetbrains.annotations.Nullable; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; public class ClassSearchDialog extends DialogWrapper { @@ -36,11 +36,13 @@ public class ClassSearchDialog extends DialogWrapper { private JBList classList; private PsiClass selectedClass; private Timer timer; - private static final int DEBOUNCE_DELAY = 500; // 防抖延迟时间,单位:毫秒 + private static final int DEBOUNCE_DELAY = 800; // 防抖延迟时间,单位:毫秒 // 定义默认宽度,可按需调整 private static final int DEFAULT_WIDTH = 700; // 定义默认高度,可按需调整 private static final int DEFAULT_HEIGHT = 600; + private JLabel loadingLabel; + private Map> searchCache = new HashMap<>(); public ClassSearchDialog(@Nullable Project project, String title) { super(project); @@ -57,7 +59,6 @@ protected void init() { SwingUtilities.invokeLater(() -> classNameField.requestFocusInWindow()); } - @Nullable @Override protected JComponent createCenterPanel() { @@ -71,9 +72,17 @@ protected JComponent createCenterPanel() { classList = new JBList<>(); classList.setCellRenderer(new ClassListCellRenderer()); JBScrollPane scrollPane = new JBScrollPane(classList); - panel.add(scrollPane, BorderLayout.CENTER); - // 输入框文本变化监听,添加防抖机制 + // 创建加载提示标签 + loadingLabel = new JLabel("Loading...", SwingConstants.CENTER); + loadingLabel.setVisible(false); // 初始状态隐藏 + + JPanel listPanel = new JPanel(new BorderLayout()); + listPanel.add(scrollPane, BorderLayout.CENTER); + listPanel.add(loadingLabel, BorderLayout.SOUTH); + + panel.add(listPanel, BorderLayout.CENTER); + classNameField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { @@ -141,7 +150,6 @@ public void keyTyped(KeyEvent e) { return panel; } - private void debounceUpdateClassList() { if (timer != null) { timer.cancel(); @@ -150,11 +158,55 @@ private void debounceUpdateClassList() { timer.schedule(new TimerTask() { @Override public void run() { - SwingUtilities.invokeLater(() -> updateClassList()); + // 显示加载提示 + SwingUtilities.invokeLater(() -> loadingLabel.setVisible(true)); + // 异步执行搜索操作 + SwingWorker, Void> worker = new SwingWorker<>() { + @Override + protected List doInBackground() { + return updateClassListInBackground(); + } + + @Override + protected void done() { + try { + List matchedClasses = get(); + SwingUtilities.invokeLater(() -> { + updateClassListUI(matchedClasses); + // 隐藏加载提示 + loadingLabel.setVisible(false); + }); + } catch (Exception e) { + e.printStackTrace(); + // 出现异常也隐藏加载提示 + SwingUtilities.invokeLater(() -> loadingLabel.setVisible(false)); + } + } + }; + worker.execute(); } }, DEBOUNCE_DELAY); } + private List updateClassListInBackground() { + String query = classNameField.getText().trim(); + if (!query.isEmpty()) { + if (searchCache.containsKey(query)) { + return searchCache.get(query); + } + List matchedClasses = PsiUtils.matchPsiClassByName(this.project, query); + // 按优先级排序 + matchedClasses.sort(this::compareClasses); + searchCache.put(query, matchedClasses); + return matchedClasses; + } + return Collections.emptyList(); + } + + private void updateClassListUI(List matchedClasses) { + classList.setListData(ArrayUtil.toObjectArray(matchedClasses, PsiClass.class)); + } + private void updateClassList() { String query = classNameField.getText().trim(); if (!query.isEmpty()) { @@ -273,5 +325,4 @@ private String highlightMatches(String input, String query) { return result.toString(); } } - } \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 21b6ba4..9bdb6dd 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -6,8 +6,10 @@ GitHub -
  • Copy the object
  • +
  • Object Copy Method
  • +
  • Object Copy
  • +
  • Class to JSON
  • Class to Thrift IDL