Skip to content

Commit 09cef4d

Browse files
author
banzhe
committed
feat: filter by FilterType
1 parent 2187ae4 commit 09cef4d

File tree

10 files changed

+241
-26
lines changed

10 files changed

+241
-26
lines changed

src/main/java/io/github/linyimin/plugin/ProcessResult.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,8 @@ public static <T> ProcessResult<T> fail(String errorMsg) {
7676
return new ProcessResult<>(false, null, errorMsg, null);
7777
}
7878

79+
public static <T> ProcessResult<T> fail(String errorMsg, T data) {
80+
return new ProcessResult<>(false, null, errorMsg, data);
81+
}
82+
7983
}

src/main/java/io/github/linyimin/plugin/component/SqlParamGenerateComponent.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ public static ProcessResult<MybatisSqlConfiguration> generate(PsiElement psiElem
5151

5252
}
5353

54-
55-
5654
if (psiElement instanceof XmlToken && psiElement.getParent() instanceof XmlTag) {
5755
List<PsiMethod> methods = MapperXmlProcessor.processMapperMethod(psiElement.getParent());
5856
psiMethod = methods.stream().findFirst().orElse(null);
@@ -69,13 +67,22 @@ public static ProcessResult<MybatisSqlConfiguration> generate(PsiElement psiElem
6967
// 找不到对应的接口方法
7068
sqlConfig.setMethod(statementId);
7169
sqlConfig.setParams("");
70+
return ProcessResult.fail(String.format("method of %s is not exist.", statementId), sqlConfig);
7271
}
73-
return ProcessResult.fail(String.format("method of %s is not exist.", statementId));
72+
73+
MybatisSqlConfiguration configuration = new MybatisSqlConfiguration();
74+
configuration.setPsiElement(psiElement);
75+
configuration.setMethod(statementId);
76+
configuration.setParams("{}");
77+
78+
return ProcessResult.success(configuration);
79+
7480
}
7581

7682
String params = generateMethodParam(psiMethod, parser);
7783

7884
if (cache) {
85+
sqlConfig.setPsiElement(psiElement);
7986
sqlConfig.setMethod(statementId);
8087
sqlConfig.setParams(params);
8188
sqlConfig.setUpdateSql(true);

src/main/java/io/github/linyimin/plugin/constant/Constant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,6 @@ public class Constant {
109109

110110
public static final String DOUBLE_CLICK_PROMPT = "-- Double-Click the 'statement', 'result' and 'stress' tab to update the sql with params\n";
111111

112+
public static final String ROOT_NAME = "Mybatis Sql";
113+
112114
}

src/main/java/io/github/linyimin/plugin/ui/MybatisSqlScannerPanel.java

Lines changed: 201 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,28 @@
2020
import io.github.linyimin.plugin.component.SqlParamGenerateComponent;
2121
import io.github.linyimin.plugin.configuration.model.MybatisSqlConfiguration;
2222
import io.github.linyimin.plugin.constant.Constant;
23+
import io.github.linyimin.plugin.pojo2json.DefaultPOJO2JSONParser;
2324
import io.github.linyimin.plugin.pojo2json.RandomPOJO2JSONParser;
25+
import io.github.linyimin.plugin.sql.checker.Checker;
26+
import io.github.linyimin.plugin.sql.checker.CheckerHolder;
27+
import io.github.linyimin.plugin.sql.checker.Report;
28+
import io.github.linyimin.plugin.sql.checker.enums.CheckScopeEnum;
29+
import io.github.linyimin.plugin.sql.parser.SqlParser;
2430
import io.github.linyimin.plugin.ui.tree.MethodTreeNode;
2531
import io.github.linyimin.plugin.ui.tree.NamespaceTreeNode;
2632
import io.github.linyimin.plugin.ui.tree.RootTreeNode;
2733
import io.github.linyimin.plugin.ui.tree.TreeListener;
34+
import io.github.linyimin.plugin.utils.IconUtils;
35+
import org.apache.commons.collections.CollectionUtils;
2836
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
2937
import org.fife.ui.rtextarea.RTextScrollPane;
3038
import org.jetbrains.annotations.NotNull;
3139

3240
import javax.swing.*;
3341
import javax.swing.border.EmptyBorder;
3442
import java.awt.*;
43+
import java.awt.event.ActionEvent;
44+
import java.util.Arrays;
3545
import java.util.List;
3646
import java.util.Set;
3747

@@ -67,7 +77,7 @@ public class MybatisSqlScannerPanel implements TabbedChangeListener {
6777
private final InfoPane infoPane;
6878
private final TreeListener treeListener;
6979

70-
private final RootTreeNode root = new RootTreeNode("Mybatis Sql");
80+
private RootTreeNode allRoot = new RootTreeNode(Constant.ROOT_NAME);
7181

7282
private final BackgroundTaskQueue backgroundTaskQueue;
7383

@@ -118,6 +128,66 @@ private void initRadioButtonGroup() {
118128
this.doesNotMeetSpecRadioButton.addMouseListener(new MouseCursorAdapter(this.doesNotMeetSpecRadioButton));
119129
this.fullTableScanRadioButton.addMouseListener(new MouseCursorAdapter(this.fullTableScanRadioButton));
120130

131+
this.allRadioButton.addActionListener(new AbstractAction() {
132+
@Override
133+
public void actionPerformed(ActionEvent e) {
134+
if (allRadioButton.isSelected()) {
135+
backgroundTaskQueue.run(new Task.Backgroundable(project, Constant.APPLICATION_NAME) {
136+
@Override
137+
public void run(@NotNull ProgressIndicator indicator) {
138+
RootTreeNode root = getRootByType(FilterType.all);
139+
createTree(root);
140+
}
141+
});
142+
}
143+
}
144+
});
145+
146+
this.complianceWithSpecRadioButton.addActionListener(new AbstractAction() {
147+
@Override
148+
public void actionPerformed(ActionEvent e) {
149+
if (complianceWithSpecRadioButton.isSelected()) {
150+
backgroundTaskQueue.run(new Task.Backgroundable(project, Constant.APPLICATION_NAME) {
151+
@Override
152+
public void run(@NotNull ProgressIndicator indicator) {
153+
RootTreeNode root = getRootByType(FilterType.compliance_spec);
154+
createTree(root);
155+
}
156+
});
157+
}
158+
}
159+
});
160+
161+
this.doesNotMeetSpecRadioButton.addActionListener(new AbstractAction() {
162+
@Override
163+
public void actionPerformed(ActionEvent e) {
164+
if (doesNotMeetSpecRadioButton.isSelected()) {
165+
backgroundTaskQueue.run(new Task.Backgroundable(project, Constant.APPLICATION_NAME) {
166+
@Override
167+
public void run(@NotNull ProgressIndicator indicator) {
168+
RootTreeNode root = getRootByType(FilterType.not_meet_spec);
169+
createTree(root);
170+
}
171+
});
172+
}
173+
}
174+
});
175+
176+
this.fullTableScanRadioButton.addActionListener(new AbstractAction() {
177+
@Override
178+
public void actionPerformed(ActionEvent e) {
179+
if (fullTableScanRadioButton.isSelected()) {
180+
backgroundTaskQueue.run(new Task.Backgroundable(project, Constant.APPLICATION_NAME) {
181+
@Override
182+
public void run(@NotNull ProgressIndicator indicator) {
183+
RootTreeNode root = getRootByType(FilterType.full_table_scan);
184+
createTree(root);
185+
}
186+
});
187+
}
188+
}
189+
});
190+
121191
}
122192

123193
private void initText() {
@@ -153,7 +223,8 @@ public void run(@NotNull ProgressIndicator indicator) {
153223
scannerResultPanel.add(infoPane.getInfoPane());
154224
infoPane.setText("Scan mybatis sql...");
155225
});
156-
createTree();
226+
allRoot = scanMybatisSql();
227+
createTree(allRoot);
157228
ApplicationManager.getApplication().invokeLater(() -> {
158229
scannerResultPanel.remove(infoPane.getInfoPane());
159230
scannerResultPanel.add(scannerResultContentPanel);
@@ -162,9 +233,41 @@ public void run(@NotNull ProgressIndicator indicator) {
162233
});
163234
}
164235

165-
private void createTree() {
236+
private RootTreeNode getRootByType(FilterType filterType) {
237+
RootTreeNode root = new RootTreeNode(Constant.ROOT_NAME);
238+
239+
SimpleNode[] simpleNodes = allRoot.getChildren();
240+
if (simpleNodes.length == 0) {
241+
return root;
242+
}
243+
for (SimpleNode node : simpleNodes) {
244+
245+
SimpleNode[] methodNodes = node.getChildren();
246+
if (methodNodes.length == 0) {
247+
continue;
248+
}
249+
250+
NamespaceTreeNode namespaceTreeNode = new NamespaceTreeNode(root, node.getName());
251+
root.add(namespaceTreeNode);
252+
253+
for (SimpleNode methodNode : methodNodes) {
254+
255+
Icon icon = methodNode.getPresentation().getIcon(true);
256+
257+
FilterType type = FilterType.resolveByIcon(icon);
166258

167-
scanMybatisSql();
259+
if (filterType == FilterType.all || icon == IconUtils.ERROR_ICON || filterType == type) {
260+
MethodTreeNode methodTreeNode = new MethodTreeNode(namespaceTreeNode, methodNode.getName(), icon);
261+
methodTreeNode.setMybatisSqlScannerPanel(this).setConfiguration(((MethodTreeNode)methodNode).getConfiguration());
262+
namespaceTreeNode.add(methodTreeNode);
263+
}
264+
}
265+
}
266+
267+
return root;
268+
}
269+
270+
private void createTree(RootTreeNode root) {
168271

169272
// 设置 tree structure
170273
SimpleTreeStructure treeStructure = new SimpleTreeStructure.Impl(root);
@@ -198,51 +301,110 @@ private void createTree() {
198301

199302
}
200303

201-
private void scanMybatisSql(String namespace) {
304+
private void scanMybatisSql(RootTreeNode root, String namespace) {
305+
202306
NamespaceTreeNode namespaceTreeNode = new NamespaceTreeNode(root, namespace);
203307
root.add(namespaceTreeNode);
204308

205309
Set<XmlTag> methods = ApplicationManager.getApplication().runReadAction((Computable<Set<XmlTag>>) () -> MybatisXmlContentCache.acquireMethodsByNamespace(project, namespace));
206310

207311
for (XmlTag method : methods) {
208312
ProcessResult<MybatisSqlConfiguration> result = ApplicationManager.getApplication().runReadAction(
209-
(Computable<ProcessResult<MybatisSqlConfiguration>>) () -> SqlParamGenerateComponent.generate(method.getFirstChild(), new RandomPOJO2JSONParser(), false)
313+
(Computable<ProcessResult<MybatisSqlConfiguration>>) () -> SqlParamGenerateComponent.generate(method.getFirstChild(), new DefaultPOJO2JSONParser(), false)
210314
);
315+
316+
MybatisSqlConfiguration configuration = result.getData();
317+
318+
MethodTreeNode methodTreeNode;
319+
211320
if (result.isSuccess()) {
212-
MybatisSqlConfiguration configuration = result.getData();
213-
MethodTreeNode methodTreeNode = new MethodTreeNode(namespaceTreeNode, configuration.getMethod());
214-
methodTreeNode.setMybatisSqlScannerPanel(this).setConfiguration(configuration);
215-
namespaceTreeNode.add(methodTreeNode);
216321

217322
ProcessResult<String> sqlResult = ApplicationManager.getApplication().runReadAction((Computable<ProcessResult<String>>) () -> SqlParamGenerateComponent.generateSql(project, configuration.getMethod(), configuration.getParams(), false));
218323

219324
if (sqlResult.isSuccess()) {
220325
configuration.setRawSql(sqlResult.getData());
326+
Icon icon = sqlCheck(sqlResult.getData());
327+
methodTreeNode = new MethodTreeNode(namespaceTreeNode, configuration.getMethod(), icon);
328+
221329
} else {
222-
// TODO: 无法生成错误提示
330+
methodTreeNode = new MethodTreeNode(namespaceTreeNode, configuration.getMethod(), IconUtils.ERROR_ICON);
223331
}
224332

225333
} else {
226-
// TODO: 无法生成错误提示
334+
methodTreeNode = new MethodTreeNode(namespaceTreeNode, configuration.getMethod(), IconUtils.ERROR_ICON);
335+
}
336+
methodTreeNode.setMybatisSqlScannerPanel(this).setConfiguration(configuration);
337+
namespaceTreeNode.add(methodTreeNode);
338+
}
339+
}
340+
341+
private Icon sqlCheck(String sql) {
342+
try {
343+
// 语法校验
344+
ProcessResult<String> validateResult = SqlParser.validate(sql);
345+
346+
if (!validateResult.isSuccess()) {
347+
return IconUtils.ERROR_ICON;
227348
}
228349

350+
// 索引检查
351+
ProcessResult<Boolean> indexCheckResult = checkIndex(sql);
352+
if (!indexCheckResult.isSuccess()) {
353+
return IconUtils.ERROR_ICON;
354+
}
355+
356+
if (!indexCheckResult.getData()) {
357+
return IconUtils.CRITICAL_ICON;
358+
}
359+
360+
ProcessResult<Boolean> ruleCheckResult = checkRule(sql);
361+
if (!ruleCheckResult.isSuccess()) {
362+
return IconUtils.ERROR_ICON;
363+
}
364+
365+
if (!ruleCheckResult.getData()) {
366+
return IconUtils.BLOCKED_ICON;
367+
}
368+
369+
return IconUtils.MAJOR_ICON;
370+
} catch (Exception e) {
371+
return IconUtils.ERROR_ICON;
229372
}
230373
}
231374

232-
private void scanMybatisSql() {
375+
private ProcessResult<Boolean> checkIndex(String sql) {
376+
// TODO:
377+
return ProcessResult.success(true);
378+
}
379+
380+
private ProcessResult<Boolean> checkRule(String sql) {
381+
382+
CheckScopeEnum scope = SqlParser.getCheckScope(sql);
383+
Checker checker = CheckerHolder.getChecker(scope);
384+
385+
if (checker == null) {
386+
return ProcessResult.success(true);
387+
}
388+
389+
List<Report> reports = checker.check(sql);
390+
if (CollectionUtils.isEmpty(reports)) {
391+
return ProcessResult.success(true);
392+
}
393+
394+
boolean meetRule = reports.stream().allMatch(Report::isPass);
395+
396+
return ProcessResult.success(meetRule);
397+
}
398+
399+
private RootTreeNode scanMybatisSql() {
400+
RootTreeNode root = new RootTreeNode(Constant.ROOT_NAME);
233401
// mapper 列表节点
234402
List<String> namespaces = ApplicationManager.getApplication().runReadAction((Computable<List<String>>) () -> MybatisXmlContentCache.acquireByNamespace(project, true));
235403
for (String namespace : namespaces) {
236-
scanMybatisSql(namespace);
404+
scanMybatisSql(root, namespace);
237405
}
238-
}
239-
240-
public JPanel getSqlContentPanel() {
241-
return sqlContentPanel;
242-
}
243406

244-
public JPanel getSqlPanel() {
245-
return sqlPanel;
407+
return root;
246408
}
247409

248410
public InfoPane getInfoPane() {
@@ -256,4 +418,22 @@ public JPanel getIndexPanel() {
256418
public JScrollPane getIndexScrollPane() {
257419
return indexScrollPane;
258420
}
421+
422+
public enum FilterType {
423+
424+
all(null),
425+
compliance_spec(IconUtils.MAJOR_ICON),
426+
not_meet_spec(IconUtils.BLOCKED_ICON),
427+
full_table_scan(IconUtils.CRITICAL_ICON);
428+
429+
private final Icon icon;
430+
431+
FilterType(Icon icon) {
432+
this.icon = icon;
433+
}
434+
435+
public static FilterType resolveByIcon(Icon icon) {
436+
return Arrays.stream(FilterType.values()).filter(type -> type.icon == icon).findFirst().orElse(FilterType.all);
437+
}
438+
}
259439
}

src/main/java/io/github/linyimin/plugin/ui/MybatisSqlViewerToolWindow.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import javax.swing.*;
1616
import javax.swing.border.EmptyBorder;
1717
import java.awt.*;
18+
import java.awt.event.MouseAdapter;
1819
import java.awt.event.MouseEvent;
1920
import java.io.IOException;
2021
import java.net.URI;
@@ -136,6 +137,15 @@ private void addComponentListener() {
136137
// 监听tabbedpane点击事件
137138
totalTabbedPanel.addChangeListener(e -> totalTabbedPanelListener());
138139

140+
this.totalTabbedPanel.addMouseListener(new MouseAdapter() {
141+
@Override
142+
public void mouseClicked(MouseEvent event) {
143+
if (event.getClickCount() == 2 && totalTabbedPanel.indexAtLocation(event.getX(), event.getY()) < TabbedComponentType.project.index) {
144+
mybatisSqlScannerPanel.listen();
145+
}
146+
}
147+
});
148+
139149
}
140150

141151
private void mybatisModeCheckBoxListener() {

src/main/java/io/github/linyimin/plugin/ui/SqlTabbedPane.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ private void validateSql(String sql) {
309309
CheckScopeEnum scope = SqlParser.getCheckScope(sql);
310310
Checker checker = CheckerHolder.getChecker(scope);
311311
if (checker == null) {
312-
statementRuleText.setText("No checker for the statement.");
312+
statementRuleText.setText("No rule checker for the statement.");
313313
return;
314314
}
315315

0 commit comments

Comments
 (0)