diff --git a/build.gradle.kts b/build.gradle.kts index 13e9c6838bfe30d848ee0157acf5f8dc7c171653..a35d106a06eb18d87c5f8f7798ed1ee076eaf168 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,7 +44,7 @@ tasks { } patchPluginXml { - sinceBuild.set("193.*") + sinceBuild.set("222.3345.*") untilBuild.set("232.*") } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fae08049a6f0b348887286874d6669e9d5ffcc06..ecf160808b548a354ae59e174702cc907533fb14 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/club/bigtian/mf/plugin/action/TableAction.java b/src/main/java/club/bigtian/mf/plugin/action/flex/TableAction.java similarity index 95% rename from src/main/java/club/bigtian/mf/plugin/action/TableAction.java rename to src/main/java/club/bigtian/mf/plugin/action/flex/TableAction.java index 64310c0b14c6cd476a5a0e2d6be19dfe912a3974..509b1d9175a2c069b96ddc4d2985d65fa76b3e29 100644 --- a/src/main/java/club/bigtian/mf/plugin/action/TableAction.java +++ b/src/main/java/club/bigtian/mf/plugin/action/flex/TableAction.java @@ -1,4 +1,4 @@ -package club.bigtian.mf.plugin.action; +package club.bigtian.mf.plugin.action.flex; import club.bigtian.mf.plugin.windows.MybatisFlexCodeGenerateDialog; import com.intellij.database.model.DasTable; diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/ClearAllAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/ClearAllAction.java new file mode 100644 index 0000000000000000000000000000000000000000..e3fd8b572b3c555846ffcb0ecba341b6a6336fe9 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/ClearAllAction.java @@ -0,0 +1,45 @@ +package club.bigtian.mf.plugin.action.log; + +import com.intellij.execution.ExecutionBundle; +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.DumbAwareAction; +import org.jetbrains.annotations.NotNull; + +/** + * ClearAllAction + * @author huangxingguang + * @see ConsoleViewImpl.ClearAllAction + */ +public class ClearAllAction extends DumbAwareAction { + private final ConsoleViewImpl consoleView; + + public ClearAllAction(ConsoleViewImpl consoleView) { + super(ExecutionBundle.message("clear.all.from.console.action.name"), "Clear All", AllIcons.Actions.GC); + this.consoleView = consoleView; + } + + @Override + public void update(@NotNull AnActionEvent e) { + boolean enabled = consoleView.getContentSize() > 0; + if (!enabled) { + enabled = e.getData(LangDataKeys.CONSOLE_VIEW) != null; + Editor editor = e.getData(CommonDataKeys.EDITOR); + if (editor != null && editor.getDocument().getTextLength() == 0) { + enabled = false; + } + } + e.getPresentation().setEnabled(enabled); + } + + @Override + public void actionPerformed(@NotNull final AnActionEvent e) { + if (consoleView != null) { + consoleView.clear(); + } + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/JumpSqlAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/JumpSqlAction.java new file mode 100644 index 0000000000000000000000000000000000000000..2e2794dfb19ccc96033e2a94e3a3512c82859a13 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/JumpSqlAction.java @@ -0,0 +1,69 @@ +package club.bigtian.mf.plugin.action.log; + +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.ex.MarkupIterator; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; +import com.intellij.openapi.wm.IdeFocusManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * JumpSqlAction + * @author huangxingguang + */ +public abstract class JumpSqlAction extends AnAction { + + public static final int SQL_LAYER = 506; + + protected final ConsoleViewImpl consoleView; + protected final Editor editor; + + public JumpSqlAction(@Nullable String text, @Nullable String description, @Nullable Icon icon, ConsoleViewImpl consoleView) { + super(text, description, icon); + this.consoleView = consoleView; + this.editor = consoleView.getEditor(); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + if (!e.getInputEvent().isShiftDown()) { + editor.getSelectionModel().removeSelection(); + } + } + + protected int jump(int startOffset, int endOffset, boolean canBreak) { + final MarkupModelEx model = (MarkupModelEx) editor.getMarkupModel(); + final MarkupIterator iterator = model.overlappingIterator(startOffset, endOffset); + + int movedOffset = -1; + + try { + while (iterator.hasNext()) { + final RangeHighlighterEx next = iterator.next(); + if (isValid(next, startOffset, endOffset)) { + editor.getCaretModel().getPrimaryCaret().moveToOffset(movedOffset = next.getStartOffset()); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(editor.getContentComponent(), true)); + if (canBreak) { + break; + } + } + } + } finally { + iterator.dispose(); + } + + return movedOffset; + } + + protected boolean isValid(RangeHighlighterEx next, int startOffset, int endOffset) { + return next.isValid() && next.getLayer() == SQL_LAYER; + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/MyBatisLogAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/MyBatisLogAction.java new file mode 100644 index 0000000000000000000000000000000000000000..678c44ae8c9e8133dc03b6a3cc2b1099472bbe1b --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/MyBatisLogAction.java @@ -0,0 +1,42 @@ +package club.bigtian.mf.plugin.action.log; + +import club.bigtian.mf.plugin.core.log.MyBatisLogManager; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * MyBatisLogAction + * + * @author huangxingguang + */ +public class MyBatisLogAction extends DumbAwareAction { + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + final Project project = e.getProject(); + // final MyBatisLogManager manager = MyBatisLogManager.getInstance(project); + // if (Objects.nonNull(manager) && manager.getToolWindow().isAvailable()) { + // if (!manager.isRunning()) { + // manager.run(); + // } + // manager.getToolWindow().activate(null); + // return; + // } + rerun(project); + } + + public void rerun(final Project project) { + MyBatisLogManager manager = MyBatisLogManager.getInstance(project); + if (Objects.nonNull(manager)) { + Disposer.dispose(manager); + } + MyBatisLogManager.createInstance(project).run(); + manager = MyBatisLogManager.getInstance(project); + manager.println("日志功能搬运于Github 开源项目 mybatis-log-free 项目地址:https://github.com/starxg/mybatis-log-plugin-free.git"); + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/NextSqlAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/NextSqlAction.java new file mode 100644 index 0000000000000000000000000000000000000000..cdeca6830ca75f2c9ee97a5e1b999ed100725d1b --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/NextSqlAction.java @@ -0,0 +1,69 @@ +package club.bigtian.mf.plugin.action.log; + +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.editor.ex.MarkupIterator; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; +import org.jetbrains.annotations.NotNull; + +/** + * NextSqlAction + * @author huangxingguang + */ +public class NextSqlAction extends JumpSqlAction { + + public NextSqlAction(ConsoleViewImpl consoleView) { + super("Next SQL", "Next SQL", AllIcons.Actions.NextOccurence, consoleView); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + + super.actionPerformed(e); + + final int offset = editor.getCaretModel().getPrimaryCaret().getOffset() + 2; + final int textLength = editor.getDocument().getTextLength(); + + if (offset >= textLength) { + return; + } + + final int movedOffset = jump(offset, textLength, true); + if (movedOffset > -1) { + if (e.getInputEvent().isShiftDown()) { + editor.getSelectionModel().setSelection(offset - 2, movedOffset); + } + } + } + + @Override + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabled(hasNext()); + } + + @Override + protected boolean isValid(RangeHighlighterEx next, int startOffset, int endOffset) { + return super.isValid(next, startOffset, endOffset) && startOffset >= 0 && editor.getDocument().getLineNumber(startOffset) != editor.getDocument().getLineNumber(next.getStartOffset()); + } + + private boolean hasNext() { + final int offset = editor.getCaretModel().getPrimaryCaret().getOffset() + 2; + final int textLength = editor.getDocument().getTextLength(); + + if (offset >= textLength) { + return false; + } + + final MarkupModelEx model = (MarkupModelEx) editor.getMarkupModel(); + final MarkupIterator iterator = model.overlappingIterator(offset, textLength); + try { + return iterator.hasNext() && isValid(iterator.next(), offset, textLength); + } finally { + iterator.dispose(); + } + + } + +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/PrettyPrintToggleAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/PrettyPrintToggleAction.java new file mode 100644 index 0000000000000000000000000000000000000000..45d67aef3f85a6953724f6f0a154f0319e147ff7 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/PrettyPrintToggleAction.java @@ -0,0 +1,39 @@ +package club.bigtian.mf.plugin.action.log; + +import club.bigtian.mf.plugin.core.icons.Icons; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.ToggleAction; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * PrettyPrintToggleAction + * @author huangxingguang + */ +public class PrettyPrintToggleAction extends ToggleAction { + + public PrettyPrintToggleAction() { + super("Pretty Print", "Pretty Print", Icons.PRETTY_PRINT); + } + + @Override + public boolean isSelected(@NotNull AnActionEvent e) { + if (Objects.isNull(e.getProject())) { + return false; + } + return PropertiesComponent.getInstance(e.getProject()).getBoolean(PrettyPrintToggleAction.class.getName()); + } + + @Override + public void setSelected(@NotNull AnActionEvent e, boolean state) { + if (Objects.isNull(e.getProject())) { + return; + } + + PropertiesComponent.getInstance(e.getProject()).setValue(PrettyPrintToggleAction.class.getName(), state); + + } + +} \ No newline at end of file diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/PreviousSqlAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/PreviousSqlAction.java new file mode 100644 index 0000000000000000000000000000000000000000..114927db586870567c2e7ba2ff2864567dab0962 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/PreviousSqlAction.java @@ -0,0 +1,66 @@ +package club.bigtian.mf.plugin.action.log; + +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.editor.ex.MarkupIterator; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; +import org.jetbrains.annotations.NotNull; + +/** + * PreviousSqlAction + * @author huangxingguang + */ +public class PreviousSqlAction extends JumpSqlAction { + + public PreviousSqlAction(ConsoleViewImpl consoleView) { + super("Previous SQL", "Previous SQL", AllIcons.Actions.PreviousOccurence, consoleView); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + + super.actionPerformed(e); + + final int offset = editor.getCaretModel().getPrimaryCaret().getOffset(); + if (offset <= 1) { + return; + } + + final int movedOffset = jump(0, offset - 1, false); + + if (movedOffset > -1) { + if (e.getInputEvent().isShiftDown()) { + editor.getSelectionModel().setSelection(offset, movedOffset); + } + } + } + + @Override + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabled(hasPrev()); + } + + @Override + protected boolean isValid(RangeHighlighterEx next, int startOffset, int endOffset) { + return super.isValid(next, startOffset, endOffset) && editor.getDocument().getLineNumber(endOffset) != editor.getDocument().getLineNumber(next.getStartOffset()); + } + + private boolean hasPrev() { + + final int offset = editor.getCaretModel().getPrimaryCaret().getOffset(); + if (offset <= 1) { + return false; + } + + final MarkupModelEx model = (MarkupModelEx) editor.getMarkupModel(); + final MarkupIterator iterator = model.overlappingIterator(0, offset - 1); + try { + return iterator.hasNext() && isValid(iterator.next(), 0, offset - 1); + } finally { + iterator.dispose(); + } + + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/RerunAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/RerunAction.java new file mode 100644 index 0000000000000000000000000000000000000000..10f2d4a70f16cd607d62fc87730a580eddbff9f1 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/RerunAction.java @@ -0,0 +1,27 @@ +package club.bigtian.mf.plugin.action.log; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * RerunAction + * @author huangxingguang + */ +public class RerunAction extends AnAction { + + public RerunAction() { + super("Rerun", "Rerun", AllIcons.Actions.Restart); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + if (Objects.nonNull(e.getProject())) { + new MyBatisLogAction().rerun(e.getProject()); + } + } + +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/SettingsAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/SettingsAction.java new file mode 100644 index 0000000000000000000000000000000000000000..8699a12cbc9c35711467a1325cdc2502d1a5afca --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/SettingsAction.java @@ -0,0 +1,31 @@ +package club.bigtian.mf.plugin.action.log; + +import club.bigtian.mf.plugin.core.log.MyBatisLogManager; +import club.bigtian.mf.plugin.windows.SettingsDialogWrapper; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * SettingsAction + */ +public class SettingsAction extends AnAction { + private final MyBatisLogManager manager; + + public SettingsAction(MyBatisLogManager manager) { + super("Settings", "Settings", AllIcons.General.GearPlain); + this.manager = manager; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + if (Objects.isNull(e.getProject())) { + return; + } + new SettingsDialogWrapper(e.getProject(), manager).showAndGet(); + } + +} diff --git a/src/main/java/club/bigtian/mf/plugin/action/log/StopAction.java b/src/main/java/club/bigtian/mf/plugin/action/log/StopAction.java new file mode 100644 index 0000000000000000000000000000000000000000..6c294de35cd5b4e59d5d4150afccfe78d8c1ca0d --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/action/log/StopAction.java @@ -0,0 +1,32 @@ +package club.bigtian.mf.plugin.action.log; + +import club.bigtian.mf.plugin.core.log.MyBatisLogManager; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.jetbrains.annotations.NotNull; + +/** + * StopAction + * @author huangxingguang + */ +public class StopAction extends AnAction { + + private final MyBatisLogManager manager; + + public StopAction(MyBatisLogManager manager) { + super("Stop", "Stop", AllIcons.Actions.Suspend); + this.manager = manager; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + manager.stop(); + } + + @Override + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabled(manager.isRunning()); + } + +} \ No newline at end of file diff --git a/src/main/java/club/bigtian/mf/plugin/core/console/MyBatisFlexConsoleFilterProvider.java b/src/main/java/club/bigtian/mf/plugin/core/console/MyBatisFlexConsoleFilterProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..6aa9774865f04a42fbf3b4f342211cd2aade7a99 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/console/MyBatisFlexConsoleFilterProvider.java @@ -0,0 +1,24 @@ +package club.bigtian.mf.plugin.core.console; + +import club.bigtian.mf.plugin.core.log.MyBatisFlexLogConsoleFilter; +import com.intellij.execution.filters.ConsoleFilterProvider; +import com.intellij.execution.filters.Filter; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class MyBatisFlexConsoleFilterProvider implements ConsoleFilterProvider { + private final Key key = Key.create(MyBatisFlexLogConsoleFilter.class.getName()); + + @Override + public Filter @NotNull [] getDefaultFilters(@NotNull Project project) { + MyBatisFlexLogConsoleFilter filter = project.getUserData(key); + if (Objects.isNull(filter)) { + filter = new MyBatisFlexLogConsoleFilter(project); + project.putUserData(key, filter); + } + return new Filter[] { filter }; + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/core/icons/Icons.java b/src/main/java/club/bigtian/mf/plugin/core/icons/Icons.java new file mode 100644 index 0000000000000000000000000000000000000000..83f26ad4cd6627aad42054f75800016947cc909f --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/icons/Icons.java @@ -0,0 +1,18 @@ +package club.bigtian.mf.plugin.core.icons; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +/** + * Icons + * + * https://jetbrains.design/intellij/resources/icons_list/ + * + * @author huangxingguang + */ +public class Icons { + public static final Icon MY_BATIS = IconLoader.getIcon("/icons/ibatis.svg", Icons.class); + public static final Icon DONATE = IconLoader.getIcon("/icons/coffee.svg", Icons.class); + public static final Icon PRETTY_PRINT = IconLoader.getIcon("/icons/prettyPrint.svg", Icons.class); +} \ No newline at end of file diff --git a/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisFlexLogConsoleFilter.java b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisFlexLogConsoleFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..82f171b8bc7bda75ac6618841e40946c2190a349 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisFlexLogConsoleFilter.java @@ -0,0 +1,158 @@ +package club.bigtian.mf.plugin.core.log; + +import com.intellij.execution.filters.Filter; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.project.Project; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * MyBatisFlexLogConsoleFilter + * 从https://github.com/bigtian99/mybatis-log-plugin-free.git中搬运过来,感谢原作者 + */ +public class MyBatisFlexLogConsoleFilter implements Filter { + + public static final String PREPARING_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".Preparing"; + public static final String PARAMETERS_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".Parameters"; + public static final String KEYWORDS_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".Keywords"; + + public static final String INSERT_SQL_COLOR_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".InsertSQLColor"; + public static final String DELETE_SQL_COLOR_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".DeleteSQLColor"; + public static final String UPDATE_SQL_COLOR_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".UpdateSQLColor"; + public static final String SELECT_SQL_COLOR_KEY = MyBatisFlexLogConsoleFilter.class.getName() + ".SelectSQLColor"; + + private static final char MARK = '?'; + + private static final Set NEED_BRACKETS; + + private final Project project; + + + private String sql = null; + + static { + Set types = new HashSet<>(8); + types.add("String"); + types.add("Date"); + types.add("Time"); + types.add("LocalDate"); + types.add("LocalTime"); + types.add("LocalDateTime"); + types.add("BigDecimal"); + types.add("Timestamp"); + NEED_BRACKETS = Collections.unmodifiableSet(types); + } + + public MyBatisFlexLogConsoleFilter(Project project) { + this.project = project; + } + + + @Override + public @Nullable Result applyFilter(@NotNull String line, int entireLength) { + final MyBatisLogManager manager = MyBatisLogManager.getInstance(project); + if (Objects.isNull(manager)) { + return null; + } + + if (!manager.isRunning()) { + return null; + } + + final String preparing = manager.getPreparing(); + final String parameters = manager.getParameters(); + final List keywords = manager.getKeywords(); + + if (CollectionUtils.isNotEmpty(keywords)) { + for (String keyword : keywords) { + if (line.contains(keyword)) { + sql = null; + return null; + } + } + } + + if (line.contains(preparing)) { + sql = line; + return null; + } + + if ((StringUtils.isNotBlank(sql) && !line.contains(parameters))||StringUtils.isBlank(sql)) { + return null; + } + + final String logPrefix = StringUtils.substringBefore(sql, preparing); + final String wholeSql = parseSql(StringUtils.substringAfter(sql, preparing), parseParams(StringUtils.substringAfter(line, parameters))).toString(); + + final String key; + if (StringUtils.startsWithIgnoreCase(wholeSql, "insert")) { + key = INSERT_SQL_COLOR_KEY; + } else if (StringUtils.startsWithIgnoreCase(wholeSql, "delete")) { + key = DELETE_SQL_COLOR_KEY; + } else if (StringUtils.startsWithIgnoreCase(wholeSql, "update")) { + key = UPDATE_SQL_COLOR_KEY; + } else if (StringUtils.startsWithIgnoreCase(wholeSql, "select")) { + key = SELECT_SQL_COLOR_KEY; + } else { + key = "unknown"; + } + + manager.println(logPrefix, wholeSql, PropertiesComponent.getInstance(project).getInt(key, ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB())); + + return null; + } + + static StringBuilder parseSql(String sql, Queue> params) { + + final StringBuilder sb = new StringBuilder(sql); + + for (int i = 0; i < sb.length(); i++) { + if (sb.charAt(i) != MARK) { + continue; + } + + final Map.Entry entry = params.poll(); + if (Objects.isNull(entry)) { + continue; + } + + + sb.deleteCharAt(i); + + if (NEED_BRACKETS.contains(entry.getValue())) { + sb.insert(i, String.format("'%s'", entry.getKey())); + } else { + sb.insert(i, entry.getKey()); + } + + + } + + return sb; + } + + static Queue> parseParams(String line) { + line = StringUtils.removeEnd(line, "\n"); + + final String[] strings = StringUtils.splitByWholeSeparator(line, ", "); + final Queue> queue = new ArrayDeque<>(strings.length); + + for (String s : strings) { + String value = StringUtils.substringBeforeLast(s, "("); + String type = StringUtils.substringBetween(s, "(", ")"); + if (StringUtils.isEmpty(type)) { + queue.offer(new AbstractMap.SimpleEntry<>(value, null)); + } else { + queue.offer(new AbstractMap.SimpleEntry<>(value, type)); + } + } + + return queue; + } + +} diff --git a/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogExecutor.java b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..85c259b677f76968efbdb53d9b903070ab387617 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogExecutor.java @@ -0,0 +1,75 @@ +package club.bigtian.mf.plugin.core.log; + +import club.bigtian.mf.plugin.core.icons.Icons; +import com.intellij.execution.Executor; +import com.intellij.execution.ExecutorRegistry; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * MyBatisLogExecutor + * + * @author huangxingguang + */ +class MyBatisLogExecutor extends Executor { + + public static final String TOOL_WINDOW_ID = "MyBatis Log"; + + @Override + public @NotNull String getToolWindowId() { + return TOOL_WINDOW_ID; + } + + @Override + public @NotNull Icon getToolWindowIcon() { + return getIcon(); + } + + @Override + public @NotNull Icon getIcon() { + return Icons.MY_BATIS; + } + + @Override + public Icon getDisabledIcon() { + return Icons.MY_BATIS; + } + + @Override + public String getDescription() { + return "MyBatis Log"; + } + + @NotNull + @Override + public String getActionName() { + return getDescription(); + } + + @NotNull + @Override + public String getId() { + return TOOL_WINDOW_ID; + } + + @NotNull + @Override + public String getStartActionText() { + return getDescription(); + } + + @Override + public String getContextActionId() { + return getDescription(); + } + + @Override + public String getHelpId() { + return TOOL_WINDOW_ID; + } + + public static Executor getInstance() { + return ExecutorRegistry.getInstance().getExecutorById(TOOL_WINDOW_ID); + } +} \ No newline at end of file diff --git a/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogManager.java b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogManager.java new file mode 100644 index 0000000000000000000000000000000000000000..268e07e60c521d13ee4a454d165fceb557f13683 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/log/MyBatisLogManager.java @@ -0,0 +1,369 @@ +package club.bigtian.mf.plugin.core.log; + +import club.bigtian.mf.plugin.action.log.*; +import club.bigtian.mf.plugin.core.icons.Icons; +import club.bigtian.mf.plugin.core.util.BasicFormatter; +import com.intellij.execution.DefaultExecutionResult; +import com.intellij.execution.ExecutionManager; +import com.intellij.execution.Executor; +import com.intellij.execution.configurations.RunProfile; +import com.intellij.execution.configurations.RunProfileState; +import com.intellij.execution.filters.TextConsoleBuilder; +import com.intellij.execution.filters.TextConsoleBuilderFactory; +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.ui.ConsoleView; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.execution.ui.RunnerLayoutUi; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actions.ScrollToTheEndToolbarAction; +import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; +import com.intellij.openapi.editor.markup.HighlighterTargetArea; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.ex.ToolWindowManagerListener; +import com.intellij.ui.JBColor; +import com.intellij.ui.content.Content; +import com.intellij.util.messages.MessageBusConnection; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.List; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static club.bigtian.mf.plugin.core.log.MyBatisFlexLogConsoleFilter.*; + + +/** + * MyBatisLogManager + * + * @author huangxingguang + */ +public class MyBatisLogManager implements Disposable { + + private static final Key KEY = Key.create(MyBatisLogManager.class.getName()); + private static final BasicFormatter FORMATTER = new BasicFormatter(); + + private final Map consoleViewContentTypes = new ConcurrentHashMap<>(); + + private final ConsoleViewImpl consoleView; + private final Project project; + private final RunContentDescriptor descriptor; + + private final AtomicInteger counter; + private volatile String preparing; + private volatile String parameters; + private volatile boolean running = false; + + + private final List keywords = new ArrayList<>(0); + + private MyBatisLogManager(@NotNull Project project) { + this.project = project; + + this.consoleView = createConsoleView(); + + final JPanel panel = createConsolePanel(this.consoleView); + + RunnerLayoutUi layoutUi = getRunnerLayoutUi(); + + Content content = layoutUi.createContent(UUID.randomUUID().toString(), panel, "SQL", Icons.MY_BATIS, panel); + + content.setCloseable(true); + layoutUi.addContent(content); + + layoutUi.getOptions().setLeftToolbar(createActionToolbar(), "RunnerToolbar"); + + final MessageBusConnection messageBusConnection = project.getMessageBus().connect(); + + this.counter = new AtomicInteger(); + this.descriptor = getRunContentDescriptor(layoutUi); + + Disposer.register(this, consoleView); + Disposer.register(this, content); + Disposer.register(this, layoutUi.getContentManager()); + Disposer.register(this, messageBusConnection); + Disposer.register(project, this); + + final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(project); + this.preparing = propertiesComponent.getValue(PREPARING_KEY, "Preparing: "); + this.parameters = propertiesComponent.getValue(PARAMETERS_KEY, "Parameters: "); + resetKeywords(propertiesComponent.getValue(KEYWORDS_KEY, StringUtils.EMPTY)); + + messageBusConnection.subscribe(ToolWindowManagerListener.TOPIC, new ToolWindowManagerListener() { + @Override + public void toolWindowRegistered(@NotNull String id) { + + } + + @Override + public void stateChanged() { + if (!getToolWindow().isAvailable()) { + Disposer.dispose(MyBatisLogManager.this); + } + } + }); + + ExecutionManager.getInstance(project).getContentManager().showRunContent(MyBatisLogExecutor.getInstance(), + descriptor); + + getToolWindow().activate(null); + } + + + private ActionGroup createActionToolbar() { + + final ConsoleViewImpl consoleView = this.consoleView; + + final DefaultActionGroup actionGroup = new DefaultActionGroup(); + actionGroup.add(new RerunAction()); + actionGroup.add(new StopAction(this)); + actionGroup.add(new SettingsAction(this)); + actionGroup.addSeparator(); + actionGroup.add(new PreviousSqlAction(consoleView)); + actionGroup.add(new NextSqlAction(consoleView)); + actionGroup.addSeparator(); + + actionGroup.add(new ToggleUseSoftWrapsToolbarAction(SoftWrapAppliancePlaces.CONSOLE) { + @Nullable + @Override + protected Editor getEditor(@NotNull AnActionEvent e) { + return consoleView.getEditor(); + } + }); + + actionGroup.add(new ScrollToTheEndToolbarAction(consoleView.getEditor())); + actionGroup.add(new PrettyPrintToggleAction()); + actionGroup.addSeparator(); + actionGroup.add(new ClearAllAction(consoleView)); + actionGroup.addSeparator(); + return actionGroup; + } + + private JPanel createConsolePanel(ConsoleView consoleView) { + final JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(consoleView.getComponent(), BorderLayout.CENTER); + return panel; + } + + private RunContentDescriptor getRunContentDescriptor(RunnerLayoutUi layoutUi) { + RunContentDescriptor descriptor = new RunContentDescriptor(new RunProfile() { + @Nullable + @Override + public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) { + return null; + } + + @NotNull + @Override + public String getName() { + return "SQL"; + } + + @Override + @Nullable + public Icon getIcon() { + return null; + } + }, new DefaultExecutionResult(), layoutUi); + descriptor.setExecutionId(System.nanoTime()); +// Add this line to disable the close button + + return descriptor; + } + + private RunnerLayoutUi getRunnerLayoutUi() { + + return RunnerLayoutUi.Factory.getInstance(project).create("MyBatis Log", "MyBatis Log", "MyBatis Log", project); + } + + public void println(String logPrefix, String sql, int rgb) { + final ConsoleViewContentType consoleViewContentType = consoleViewContentTypes.computeIfAbsent(rgb, k -> new ConsoleViewContentType(String.valueOf(rgb), new TextAttributes(new JBColor(rgb, rgb), null, null, null, Font.PLAIN))); + consoleView.print(String.format("-- %s -- %s\n", counter.incrementAndGet(), logPrefix), ConsoleViewContentType.USER_INPUT); + consoleView.print(String.format("%s\n", isFormat() ? FORMATTER.format(sql) : StringUtils.removeEnd(sql, "\n")), consoleViewContentType); + } + + public void println(String msg) { + consoleView.print(String.format("-- %s\n", msg), ConsoleViewContentType.USER_INPUT); + } + + private boolean isFormat() { + return PropertiesComponent.getInstance(project).getBoolean(PrettyPrintToggleAction.class.getName()); + } + + public void run() { + + if (running) { + return; + } + + running = true; + + } + + public void stop() { + if (!running) { + return; + } + running = false; + + } + + @Nullable + public static MyBatisLogManager getInstance(@NotNull Project project) { + + MyBatisLogManager manager = project.getUserData(KEY); + + if (Objects.nonNull(manager)) { + if (!manager.getToolWindow().isAvailable()) { + Disposer.dispose(manager); + manager = null; + } + } + + return manager; + + } + + @NotNull + public static MyBatisLogManager createInstance(@NotNull Project project) { + + MyBatisLogManager manager = getInstance(project); + + if (Objects.nonNull(manager) && !Disposer.isDisposed(manager)) { + Disposer.dispose(manager); + } + + manager = new MyBatisLogManager(project); + project.putUserData(KEY, manager); + + return manager; + + } + + public ToolWindow getToolWindow() { + return ToolWindowManager.getInstance(project).getToolWindow(MyBatisLogExecutor.TOOL_WINDOW_ID); + } + + public void resetKeywords(String text) { + + keywords.clear(); + + if (StringUtils.isBlank(text)) { + return; + } + + final String[] split = text.split("\n"); + + final List keywords = new ArrayList<>(split.length); + + for (String keyword : split) { + if (StringUtils.isBlank(keyword)) { + continue; + } + + keywords.add(keyword); + + } + + this.keywords.addAll(keywords); + } + + public String getPreparing() { + return preparing; + } + + public void setPreparing(String preparing) { + this.preparing = preparing; + } + + public void setParameters(String parameters) { + this.parameters = parameters; + } + + public boolean isRunning() { + return running; + } + + public String getParameters() { + return parameters; + } + + public List getKeywords() { + return keywords; + } + + @Override + public void dispose() { + + project.putUserData(KEY, null); + + stop(); + + ExecutionManager.getInstance(project).getContentManager().removeRunContent(MyBatisLogExecutor.getInstance(), + descriptor); + + } + + private ConsoleViewImpl createConsoleView() { + TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project); + final ConsoleViewImpl console = (ConsoleViewImpl) consoleBuilder.getConsole(); + // init editor + console.getComponent(); + + final Editor editor = console.getEditor(); + editor.getDocument().addDocumentListener(new RangeHighlighterDocumentListener(editor)); + + return console; + } + + private static final class RangeHighlighterDocumentListener implements DocumentListener { + + private final Editor editor; + + private RangeHighlighterDocumentListener(Editor editor) { + this.editor = editor; + } + + @Override + public void documentChanged(@NotNull DocumentEvent event) { + final Document document = event.getDocument(); + final int textLength = document.getTextLength(); + if (textLength < 1) { + return; + } + + for (int i = event.getOffset(); i < textLength; ) { + final int endOffset = document.getLineEndOffset(document.getLineNumber(i)); + final String text = document.getText(TextRange.create(i, endOffset)); + if (text.matches("^-- [\\d]+ -- .*")) { + editor.getMarkupModel().addRangeHighlighter(i, i + 1, JumpSqlAction.SQL_LAYER, TextAttributes.ERASE_MARKER, HighlighterTargetArea.EXACT_RANGE); + } + i = endOffset + 1; + } + } + } + + +} \ No newline at end of file diff --git a/src/main/java/club/bigtian/mf/plugin/core/util/BasicFormatter.java b/src/main/java/club/bigtian/mf/plugin/core/util/BasicFormatter.java new file mode 100644 index 0000000000000000000000000000000000000000..8b2594feadcf4115b9edc5a1b8569af0043ac8a5 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/core/util/BasicFormatter.java @@ -0,0 +1,361 @@ +package club.bigtian.mf.plugin.core.util; + +import java.util.*; + +/* + * Original class is here: + * https://github.com/hibernate/hibernate-orm/blob/a30635f14ae272fd63a653f9a9e1a9aeb390fad4/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/BasicFormatterImpl.java + * + * it imported org.hibernate.internal.util.StringHelper, but it doesn't really need that. + */ + +/** + * Performs formatting of basic SQL statements (DML + query). + * + * @author Gavin King + * @author Steve Ebersole + */ +public class BasicFormatter { + + public static final String FORMAT_KEY = BasicFormatter.class.getName() + ".FORMAT"; + + // MOD: from org.hibernate.internal.util.StringHelper + private static final String WHITESPACE = " \n\r\f\t"; + + private static final Set BEGIN_CLAUSES = new HashSet<>(); + private static final Set END_CLAUSES = new HashSet<>(); + private static final Set LOGICAL = new HashSet<>(); + private static final Set QUANTIFIERS = new HashSet<>(); + private static final Set DML = new HashSet<>(); + private static final Set MISC = new HashSet<>(); + + static { + BEGIN_CLAUSES.add("left"); + BEGIN_CLAUSES.add("right"); + BEGIN_CLAUSES.add("inner"); + BEGIN_CLAUSES.add("outer"); + BEGIN_CLAUSES.add("group"); + BEGIN_CLAUSES.add("order"); + + END_CLAUSES.add("where"); + END_CLAUSES.add("set"); + END_CLAUSES.add("having"); + END_CLAUSES.add("join"); + END_CLAUSES.add("from"); + END_CLAUSES.add("by"); + END_CLAUSES.add("into"); + END_CLAUSES.add("union"); + + LOGICAL.add("and"); + LOGICAL.add("or"); + LOGICAL.add("when"); + LOGICAL.add("else"); + LOGICAL.add("end"); + + QUANTIFIERS.add("in"); + QUANTIFIERS.add("all"); + QUANTIFIERS.add("exists"); + QUANTIFIERS.add("some"); + QUANTIFIERS.add("any"); + + DML.add("insert"); + DML.add("update"); + DML.add("delete"); + + MISC.add("select"); + MISC.add("on"); + } + + private static final String INDENT_STRING = " "; + // MOD: Make initial indent zero + /* System.lineSeparator() + INDENT_STRING */ + private static final String INITIAL = ""; + + public String format(String source) { + return new FormatProcess(source).perform(); + } + + private static class FormatProcess { + boolean beginLine = true; + boolean afterBeginBeforeEnd; + boolean afterByOrSetOrFromOrSelect; + boolean afterValues; + boolean afterOn; + boolean afterBetween; + boolean afterInsert; + int inFunction; + int parensSinceSelect; + private final LinkedList parenCounts = new LinkedList<>(); + private final LinkedList afterByOrFromOrSelects = new LinkedList<>(); + + // MOD: Make BOL indent zero + int indent = /* 1 */0; + + StringBuilder result = new StringBuilder(); + StringTokenizer tokens; + String lastToken; + String token; + String lcToken; + + public FormatProcess(String sql) { + tokens = new StringTokenizer(sql, "()+*/-=<>'`\"[]," + /* StringHelper. */WHITESPACE, true); + } + + public String perform() { + + result.append(INITIAL); + + while (tokens.hasMoreTokens()) { + token = tokens.nextToken(); + lcToken = token.toLowerCase(Locale.ROOT); + + switch (token) { + case "'": { + String t; + do { + t = tokens.nextToken(); + token += t; + } + // cannot handle single quotes + while (!"'".equals(t) && tokens.hasMoreTokens()); + break; + } + case "\"": { + String t; + do { + t = tokens.nextToken(); + token += t; + } while (!"\"".equals(t) && tokens.hasMoreTokens()); + break; + } + // SQL Server uses "[" and "]" to escape reserved words + // see SQLServerDialect.openQuote and SQLServerDialect.closeQuote + case "[": { + String t; + do { + t = tokens.nextToken(); + token += t; + } while (!"]".equals(t) && tokens.hasMoreTokens()); + break; + } + } + + if (afterByOrSetOrFromOrSelect && ",".equals(token)) { + commaAfterByOrFromOrSelect(); + } else if (afterOn && ",".equals(token)) { + commaAfterOn(); + } else if ("(".equals(token)) { + openParen(); + } else if (")".equals(token)) { + closeParen(); + } else if (BEGIN_CLAUSES.contains(lcToken)) { + beginNewClause(); + } else if (END_CLAUSES.contains(lcToken)) { + endNewClause(); + } else if ("select".equals(lcToken)) { + select(); + } else if (DML.contains(lcToken)) { + updateOrInsertOrDelete(); + } else if ("values".equals(lcToken)) { + values(); + } else if ("on".equals(lcToken)) { + on(); + } else if (afterBetween && "and".equals(lcToken)) { + misc(); + afterBetween = false; + } else if (LOGICAL.contains(lcToken)) { + logical(); + } else if (isWhitespace(token)) { + white(); + } else { + misc(); + } + + if (!isWhitespace(token)) { + lastToken = lcToken; + } + + } + return result.toString(); + } + + private void commaAfterOn() { + out(); + indent--; + newline(); + afterOn = false; + afterByOrSetOrFromOrSelect = true; + } + + private void commaAfterByOrFromOrSelect() { + out(); + newline(); + } + + private void logical() { + if ("end".equals(lcToken)) { + indent--; + } + newline(); + out(); + beginLine = false; + } + + private void on() { + indent++; + afterOn = true; + newline(); + out(); + beginLine = false; + } + + private void misc() { + out(); + if ("between".equals(lcToken)) { + afterBetween = true; + } + if (afterInsert) { + newline(); + afterInsert = false; + } else { + beginLine = false; + if ("case".equals(lcToken)) { + indent++; + } + } + } + + private void white() { + if (!beginLine) { + result.append(" "); + } + } + + private void updateOrInsertOrDelete() { + out(); + indent++; + beginLine = false; + if ("update".equals(lcToken)) { + newline(); + } + if ("insert".equals(lcToken)) { + afterInsert = true; + } + } + + private void select() { + out(); + indent++; + newline(); + parenCounts.addLast(parensSinceSelect); + afterByOrFromOrSelects.addLast(afterByOrSetOrFromOrSelect); + parensSinceSelect = 0; + afterByOrSetOrFromOrSelect = true; + } + + private void out() { + result.append(token); + } + + private void endNewClause() { + if (!afterBeginBeforeEnd) { + indent--; + if (afterOn) { + indent--; + afterOn = false; + } + newline(); + } + out(); + if (!"union".equals(lcToken)) { + indent++; + } + newline(); + afterBeginBeforeEnd = false; + afterByOrSetOrFromOrSelect = "by".equals(lcToken) || "set".equals(lcToken) || "from".equals(lcToken); + } + + private void beginNewClause() { + if (!afterBeginBeforeEnd) { + if (afterOn) { + indent--; + afterOn = false; + } + indent--; + newline(); + } + out(); + beginLine = false; + afterBeginBeforeEnd = true; + } + + private void values() { + indent--; + newline(); + out(); + indent++; + newline(); + afterValues = true; + } + + private void closeParen() { + parensSinceSelect--; + if (parensSinceSelect < 0) { + indent--; + parensSinceSelect = parenCounts.removeLast(); + afterByOrSetOrFromOrSelect = afterByOrFromOrSelects.removeLast(); + } + if (inFunction > 0) { + inFunction--; + } else { + if (!afterByOrSetOrFromOrSelect) { + indent--; + newline(); + } + } + out(); + beginLine = false; + } + + private void openParen() { + if (isFunctionName(lastToken) || inFunction > 0) { + inFunction++; + } + beginLine = false; + if (inFunction > 0) { + out(); + } else { + out(); + if (!afterByOrSetOrFromOrSelect) { + indent++; + newline(); + beginLine = true; + } + } + parensSinceSelect++; + } + + private static boolean isFunctionName(String tok) { + if (tok == null || tok.length() == 0) { + return false; + } + + final char begin = tok.charAt(0); + final boolean isIdentifier = Character.isJavaIdentifierStart(begin) || '"' == begin; + return isIdentifier && !LOGICAL.contains(tok) && !END_CLAUSES.contains(tok) && !QUANTIFIERS.contains(tok) + && !DML.contains(tok) && !MISC.contains(tok); + } + + private static boolean isWhitespace(String token) { + return /* StringHelper. */WHITESPACE.contains(token); + } + + private void newline() { + result.append(System.lineSeparator()); + for (int i = 0; i < indent; i++) { + result.append(INDENT_STRING); + } + beginLine = true; + } + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/windows/DonateDialogWrapper.java b/src/main/java/club/bigtian/mf/plugin/windows/DonateDialogWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..0fa1abf06ebe04986b977f90663b6b9f8cb8b93e --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/windows/DonateDialogWrapper.java @@ -0,0 +1,117 @@ +package club.bigtian.mf.plugin.windows; + +import club.bigtian.mf.plugin.core.icons.Icons; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.HyperlinkLabel; +import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.util.Objects; + +/** + * DonateDialogWrapper + * + * @author huangxingguang + */ +public class DonateDialogWrapper extends DialogWrapper { + + public DonateDialogWrapper(@Nullable Project project) { + super(project, false); + + init(); + + setTitle("Donate - Thank You Very Much!"); + + setResizable(false); + + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + final JPanel panel = new JPanel(); + final GridBagLayout layout = new GridBagLayout(); + layout.columnWidths = new int[] { 0, 0, 0 }; + layout.rowHeights = new int[] { 0, 0, 0 }; + layout.columnWeights = new double[] { 1, 1, 1 }; + layout.rowWeights = new double[] { 1, 1, 1 }; + panel.setLayout(layout); + + try { + + final JLabel alipay = new JLabel(new ImageIcon( + ImageIO.read(Objects.requireNonNull(getClass().getResource("/images/alipay.png"), "alipay.png")) + .getScaledInstance(200, 200, Image.SCALE_SMOOTH))); + final JLabel wechatpay = new JLabel(new ImageIcon(ImageIO + .read(Objects.requireNonNull(getClass().getResource("/images/wechatpay.png"), "wechatpay.png")) + .getScaledInstance(200, 200, Image.SCALE_SMOOTH))); + + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.insets = JBUI.insets(10); + c.gridy = 0; + c.gridx = 0; + panel.add(new JLabel("Alipay", JLabel.CENTER), c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.insets = JBUI.insets(0, 0, 0, 10); + c.gridy = 0; + c.gridx = 1; + panel.add(new JLabel("WeChat Pay", JLabel.CENTER), c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.insets = JBUI.insets(0, 0, 0, 10); + c.gridy = 1; + c.gridx = 0; + panel.add(alipay, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.gridy = 1; + c.gridx = 1; + panel.add(wechatpay, c); + + c = new GridBagConstraints(); + c.insets = JBUI.insets(10); + c.gridy = 2; + c.gridx = 0; + final HyperlinkLabel kofi = new HyperlinkLabel(); + kofi.setIcon(Icons.DONATE); + kofi.setHyperlinkText("Donate on Ko-fi"); + kofi.setUseIconAsLink(true); + kofi.setHyperlinkTarget("https://ko-fi.com/huangxingguang"); + panel.add(kofi, c); + + c = new GridBagConstraints(); + c.insets = JBUI.insets(10); + c.gridy = 2; + c.gridx = 1; + final HyperlinkLabel paypal = new HyperlinkLabel(); + paypal.setIcon(Icons.DONATE); + paypal.setHyperlinkText("Donate on PayPal"); + paypal.setUseIconAsLink(true); + paypal.setHyperlinkTarget("https://paypal.me/huangxingguang"); + + panel.add(paypal, c); + + } catch (IOException e) { + Logger.getInstance(getClass()).error(e.getMessage(), e); + } + + return panel; + } + + @Override + protected Action @NotNull [] createActions() { + return new Action[] { getOKAction() }; + } +} diff --git a/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.form b/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.form new file mode 100644 index 0000000000000000000000000000000000000000..688ea326b20ad1651c845daed10509333c25fb95 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.form @@ -0,0 +1,193 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.java b/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..a8a8678fdd52cc69da088b0fa9344b3060fdeef0 --- /dev/null +++ b/src/main/java/club/bigtian/mf/plugin/windows/SettingsDialogWrapper.java @@ -0,0 +1,188 @@ +package club.bigtian.mf.plugin.windows; + +import club.bigtian.mf.plugin.core.log.MyBatisLogManager; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.ColorChooserService; +import com.intellij.ui.JBColor; +import com.intellij.ui.components.JBTextArea; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Collections; +import java.util.Objects; + +import static club.bigtian.mf.plugin.core.log.MyBatisFlexLogConsoleFilter.*; + + +/** + * SettingsDialogWrapper + */ +public class SettingsDialogWrapper extends DialogWrapper { + + private final Project project; + private final MyBatisLogManager manager; + + private JPanel rootPanel; + private JPanel filterTab; + private JPanel colorTab; + private JTextField txtPreparing; + private JTextField txtParameters; + private JBTextArea txtKeywords; + private JPanel insertColor; + private JPanel deleteColor; + private JPanel updateColor; + private JPanel selectColor; + + + public SettingsDialogWrapper(Project project, MyBatisLogManager manager) { + super(Objects.requireNonNull(project, "project"), false); + + this.project = project; + this.manager = manager; + + setTitle("Settings"); + + init(); + + initColorEvent(); + + getWindow().addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + if (isOK()) { + saveProperties(); + } + } + }); + + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + + rootPanel.setPreferredSize(new Dimension(600, 400)); + + final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(project); + + final int insertColorRGB = propertiesComponent.getInt(INSERT_SQL_COLOR_KEY, ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + final int deleteColorRGB = propertiesComponent.getInt(DELETE_SQL_COLOR_KEY, ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + final int updateColorRGB = propertiesComponent.getInt(UPDATE_SQL_COLOR_KEY, ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + final int selectColorRGB = propertiesComponent.getInt(SELECT_SQL_COLOR_KEY, ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + + insertColor.setBackground(new JBColor(insertColorRGB, insertColorRGB)); + deleteColor.setBackground(new JBColor(deleteColorRGB, deleteColorRGB)); + updateColor.setBackground(new JBColor(updateColorRGB, updateColorRGB)); + selectColor.setBackground(new JBColor(selectColorRGB, selectColorRGB)); + + insertColor.setMinimumSize(new Dimension(20, 20)); + deleteColor.setMinimumSize(new Dimension(20, 20)); + updateColor.setMinimumSize(new Dimension(20, 20)); + selectColor.setMinimumSize(new Dimension(20, 20)); + + filterTab.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + colorTab.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + + txtPreparing.setText(propertiesComponent.getValue(PREPARING_KEY, "Preparing: ")); + txtParameters.setText(propertiesComponent.getValue(PARAMETERS_KEY, "Parameters: ")); + txtKeywords.setText(StringUtils.defaultString(propertiesComponent.getValue(KEYWORDS_KEY))); + txtKeywords.setBorder(new LineBorder(JBColor.border(), 1)); + + return rootPanel; + } + + private void initColorEvent() { + + final MouseAdapter listener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (!(e.getSource() instanceof JPanel)) { + return; + } + + final String title; + if (e.getSource() == insertColor) { + title = "Insert"; + } else if (e.getSource() == deleteColor) { + title = "Delete"; + } else if (e.getSource() == updateColor) { + title = "Update"; + } else if (e.getSource() == selectColor) { + title = "Select"; + } else { + title = StringUtils.EMPTY; + } + + final Color color = ColorChooserService.getInstance().showDialog(project, getContentPane(), title + " SQL Color", ((JPanel) e.getSource()).getBackground(), true, Collections.emptyList(), true); + if (Objects.nonNull(color)) { + ((JPanel) e.getSource()).setBackground(color); + } + + } + }; + + insertColor.addMouseListener(listener); + deleteColor.addMouseListener(listener); + updateColor.addMouseListener(listener); + selectColor.addMouseListener(listener); + } + + private void saveProperties() { + final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(project); + final String preparing = getPreparing(); + final String parameters = getParameters(); + final String keywords = getKeywords(); + + propertiesComponent.setValue(PREPARING_KEY, getPreparing()); + propertiesComponent.setValue(PARAMETERS_KEY, getParameters()); + propertiesComponent.setValue(KEYWORDS_KEY, getKeywords()); + + propertiesComponent.setValue(INSERT_SQL_COLOR_KEY, getInsertColorRGB(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + propertiesComponent.setValue(DELETE_SQL_COLOR_KEY, getDeleteColorRGB(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + propertiesComponent.setValue(UPDATE_SQL_COLOR_KEY, getUpdateColorRGB(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + propertiesComponent.setValue(SELECT_SQL_COLOR_KEY, getSelectColorRGB(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes().getForegroundColor().getRGB()); + + + manager.setPreparing(preparing); + manager.setParameters(parameters); + manager.resetKeywords(keywords); + } + + public int getInsertColorRGB() { + return insertColor.getBackground().getRGB(); + } + + public int getDeleteColorRGB() { + return deleteColor.getBackground().getRGB(); + } + + public int getUpdateColorRGB() { + return updateColor.getBackground().getRGB(); + } + + public int getSelectColorRGB() { + return selectColor.getBackground().getRGB(); + } + + public String getPreparing() { + return StringUtils.defaultIfBlank(txtPreparing.getText(), "Preparing: "); + } + + public String getParameters() { + return StringUtils.defaultIfBlank(txtParameters.getText(), "Parameters: "); + } + + public String getKeywords() { + return txtKeywords.getText(); + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index d7e8531e6467415f105eb968e2f379650db6118e..c805624623b05ebea27c088caa390c24cbd875b2 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -28,18 +28,23 @@ mybatisFlex code generation is based on the official code generation template, b - - - - - + + - + + + + + - + \ No newline at end of file diff --git a/src/main/resources/icons/coffee.svg b/src/main/resources/icons/coffee.svg new file mode 100644 index 0000000000000000000000000000000000000000..4dd66136e39b297a96015fd5ef473a42f741648b --- /dev/null +++ b/src/main/resources/icons/coffee.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/main/resources/icons/ibatis.svg b/src/main/resources/icons/ibatis.svg new file mode 100644 index 0000000000000000000000000000000000000000..2bceefb0b08587af2056dd78cff86004dcb9577a --- /dev/null +++ b/src/main/resources/icons/ibatis.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/icons/prettyPrint.svg b/src/main/resources/icons/prettyPrint.svg new file mode 100644 index 0000000000000000000000000000000000000000..8f121be05cc280a21b669cd7280a8934428c958d --- /dev/null +++ b/src/main/resources/icons/prettyPrint.svg @@ -0,0 +1,5 @@ + + + + +