Skip to content

Commit 5d46cf3

Browse files
authored
Merge pull request #140 from jborgers/master
Deal properly with PMD processing errors, including NullPointerExceptions from PMD
2 parents 804ecfc + 5fd1fe8 commit 5d46cf3

File tree

7 files changed

+66
-26
lines changed

7 files changed

+66
-26
lines changed

src/main/java/com/intellij/plugins/bodhi/pmd/PMDInvoker.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public void run() {
160160
PMDResultPanel resultPanel = projectComponent.getResultPanel();
161161

162162
PMDRootNode rootNode = resultPanel.getRootNode();
163+
resultPanel.createProcessingErrorNode();
163164
PMDResultCollector.clearReport();
164165
rootNode.setFileCount(files.size());
165166
rootNode.setRuleSetCount(ruleSetPathArray.length);

src/main/java/com/intellij/plugins/bodhi/pmd/PMDResultPanel.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,11 +431,18 @@ public PMDRootNode getRootNode() {
431431
}
432432

433433
/**
434-
* Creates and returns the processingErrors branch node.
434+
* Returns the single processingErrors branch node. Created if needed.
435435
*
436-
* @return the new processingErrors branch node
436+
* @return the processingErrors branch node
437437
*/
438-
public PMDErrorBranchNode getNewProcessingErrorsNode() {
438+
public PMDErrorBranchNode getProcessingErrorsNode() {
439+
if (processingErrorsNode == null) {
440+
createProcessingErrorNode();
441+
}
442+
return processingErrorsNode;
443+
}
444+
445+
public PMDErrorBranchNode createProcessingErrorNode() {
439446
processingErrorsNode = new PMDErrorBranchNode("Processing errors");
440447
return processingErrorsNode;
441448
}

src/main/java/com/intellij/plugins/bodhi/pmd/core/PMDProcessingError.java

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,22 @@ public class PMDProcessingError implements HasPositionInFile {
1818

1919
public PMDProcessingError(Report.ProcessingError error) {
2020
processingError = error;
21-
String causeDetailMsg = error.getError().getCause().getMessage();
22-
// assumes format by PMD: 'Line \d+, Column \d+:'
23-
int atLinePos = causeDetailMsg.indexOf("Line ");
24-
int columnPos = causeDetailMsg.indexOf(", Column ");
25-
int colonPos = causeDetailMsg.indexOf(":", columnPos);
26-
if (atLinePos > -1 && columnPos > atLinePos && colonPos > columnPos) {
27-
try {
28-
String line = causeDetailMsg.substring(atLinePos + 5, columnPos);
29-
String col = causeDetailMsg.substring(columnPos + 9, colonPos);
30-
beginLine = Integer.parseInt(line);
31-
beginColumn = Integer.parseInt(col);
32-
}
33-
catch(NumberFormatException | StringIndexOutOfBoundsException e) { // no beginLine, beginColumn
21+
Throwable cause = error.getError().getCause(); // fix #137
22+
if (cause != null) {
23+
String causeDetailMsg = cause.getMessage();
24+
// assumes format by PMD: 'Line \d+, Column \d+:'
25+
int atLinePos = causeDetailMsg.indexOf("Line ");
26+
int columnPos = causeDetailMsg.indexOf(", Column ");
27+
int colonPos = causeDetailMsg.indexOf(":", columnPos);
28+
if (atLinePos > -1 && columnPos > atLinePos && colonPos > columnPos) {
29+
try {
30+
String line = causeDetailMsg.substring(atLinePos + 5, columnPos);
31+
String col = causeDetailMsg.substring(columnPos + 9, colonPos);
32+
beginLine = Integer.parseInt(line);
33+
beginColumn = Integer.parseInt(col);
34+
}
35+
catch(NumberFormatException | StringIndexOutOfBoundsException e) { // no beginLine, beginColumn
36+
}
3437
}
3538
}
3639
positionText = "(" + beginLine + ", " + beginColumn + ") ";
@@ -41,7 +44,14 @@ public PMDProcessingError(Report.ProcessingError error) {
4144
* @return the simple class name and the throwable detail message.
4245
*/
4346
public String getMsg() {
44-
return processingError.getMsg();
47+
// PMDException (deprecated) has a cause
48+
Throwable error = processingError.getError();
49+
if (error.getCause() != null) {
50+
// a proper PMDException indicating for instance wrong java version
51+
return processingError.getMsg(); // error class simple name and message
52+
}
53+
// error in PMD, for instance a NullPointerException, build our own message
54+
return error.getClass().getSimpleName() + ": Error while parsing " + processingError.getFile();
4555
}
4656

4757
/**
@@ -73,11 +83,20 @@ public Throwable getError() {
7383
* Returns the detail message of the cause of this throwable or {@code null} if the
7484
* cause is nonexistent or unknown. (The cause is the throwable that
7585
* caused this throwable to get thrown.)
76-
* @return the detail mesage of the cause throwable.
86+
* When cause == null, it returns throw location of the throwable itself.
87+
* @return the detail message of the cause throwable.
7788
*/
7889
public String getCauseMsg() {
79-
return processingError.getError().getCause().getMessage();
80-
}
90+
Throwable error = processingError.getError();
91+
Throwable cause = error.getCause();
92+
if (cause != null) {
93+
return cause.getMessage();
94+
}
95+
else {
96+
// if no cause, it may be a bug in PMD, get first stack element
97+
return error.getStackTrace()[0].toString();
98+
}
99+
}
81100

82101
/**
83102
* Returns the position text to render.

src/main/java/com/intellij/plugins/bodhi/pmd/core/PMDResultAsTreeRenderer.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public class PMDResultAsTreeRenderer extends AbstractIncrementingRenderer {
2626
private static final Log log = LogFactory.getLog(PMDResultAsTreeRenderer.class);
2727
private final List<PMDRuleSetEntryNode> pmdRuleResultNodes;
2828
private final PMDErrorBranchNode processingErrorsNode;
29-
private final Set<String> filesWithError = new HashSet<>();
3029
private final UselessSuppressionsHelper uselessSupHelper;
3130
private final Map<RuleKey, PMDRuleNode> ruleKeyToNodeMap = new TreeMap<>(); // order by priority and then name
3231

@@ -72,9 +71,9 @@ private void renderErrors() {
7271
PMDTreeNodeFactory nodeFactory = PMDTreeNodeFactory.getInstance();
7372
for (Report.ProcessingError error : errors) {
7473
try {
75-
if (!filesWithError.contains(error.getFile())) {
74+
if (!processingErrorsNode.hasFile(error.getFile())) {
7675
processingErrorsNode.add(nodeFactory.createErrorLeafNode(new PMDProcessingError(error)));
77-
filesWithError.add(error.getFile());
76+
processingErrorsNode.registerFile(error.getFile());
7877
}
7978
}
8079
catch(Exception e) {

src/main/java/com/intellij/plugins/bodhi/pmd/core/PMDResultCollector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public List<PMDRuleSetEntryNode> runPMDAndGetResults(List<File> files, String ru
6868
try {
6969
PMDConfiguration pmdConfig = getPmdConfig(ruleSetPath, options, project);
7070

71-
PMDErrorBranchNode errorsNode = comp.getResultPanel().getNewProcessingErrorsNode();
71+
PMDErrorBranchNode errorsNode = comp.getResultPanel().getProcessingErrorsNode();
7272
PMDResultAsTreeRenderer treeRenderer = new PMDResultAsTreeRenderer(pmdRuleSetResults, errorsNode, ruleSetPath);
7373
treeRenderer.setWriter(IOUtil.createWriter(pmdConfig.getReportFile()));
7474
treeRenderer.start();
@@ -95,7 +95,7 @@ public List<PMDRuleSetEntryNode> runPMDAndGetResults(List<File> files, String ru
9595
return pmdRuleSetResults;
9696
}
9797

98-
private PMDJsonExportingRenderer addExportRenderer(Map<String, String> options) throws IOException {
98+
private PMDJsonExportingRenderer addExportRenderer(Map<String, String> options) {
9999
PMDJsonExportingRenderer exportingRenderer = null;
100100
String exportUrlFromForm = options.get(PMDConfigurationForm.STATISTICS_URL);
101101
boolean exportStats = (PMDUtil.isValidUrl(exportUrlFromForm));

src/main/java/com/intellij/plugins/bodhi/pmd/tree/PMDErrorBranchNode.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
package com.intellij.plugins.bodhi.pmd.tree;
22

3+
import java.util.HashSet;
4+
import java.util.Set;
5+
36
/**
47
* PMD branch tree node for processing errors. It has a Severity.BLOCKER icon.
8+
* It registers files with errors in order to limit the number of errors per file to 1.
59
*
610
* @author jborgers
711
*/
812
public class PMDErrorBranchNode extends PMDBranchNode {
13+
14+
private final Set<String> filesWithError = new HashSet<>();
15+
916
public PMDErrorBranchNode(String name) {
1017
super(name);
1118
}
1219

20+
public boolean hasFile(String file) {
21+
return filesWithError.contains(file);
22+
}
23+
24+
public void registerFile(String file) {
25+
filesWithError.add(file);
26+
}
1327
@Override
1428
public synchronized void render(PMDCellRenderer cellRenderer, boolean expanded) {
1529
cellRenderer.setIcon(Severity.BLOCKER.getIcon());

src/main/java/com/intellij/plugins/bodhi/pmd/tree/PMDErrorNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void render(PMDCellRenderer cellRenderer, boolean expanded) {
2727
cellRenderer.setIcon(Severity.BLOCKER.getIcon());
2828
// Show error position greyed, like idea shows.
2929
cellRenderer.append(pmdProcessingError.getPositionText(), GRAYED_ATTRIBUTES);
30-
cellRenderer.append(pmdProcessingError.getErrorMsg()); // includes file name
30+
cellRenderer.append(pmdProcessingError.getMsg()); // includes simple class and file name
3131
}
3232

3333
@Override

0 commit comments

Comments
 (0)