forked from phoedos/pmd
pmd: fix #1037 Facing a showstopper issue in PMD Report Class
* wrapping the report listeners in a thread safe (synchronized) class * overtaking the listeners for each thread / report
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
???? ??, 2012 - 5.0.2:
|
||||
|
||||
Fixed bug 1026: PMD doesn't handle 'value =' in SuppressWarnings annotation
|
||||
Fixed bug 1037: Facing a showstopper issue in PMD Report Class (report listeners)
|
||||
Fixed bug 1043: node.getEndLine() always returns 0 (ECMAscript)
|
||||
Fixed bug 1044: Unknown option: -excludemarker
|
||||
Fixed bug 1047: False Positive in 'for' loops for LocalVariableCouldBeFinal in 5.0.1
|
||||
|
@ -22,15 +22,18 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
public class Report {
|
||||
|
||||
public static Report createReport(RuleContext ctx, String fileName) {
|
||||
|
||||
Report report = new Report();
|
||||
ctx.setReport(report);
|
||||
ctx.setSourceCodeFilename(fileName);
|
||||
ctx.setSourceCodeFile(new File(fileName));
|
||||
return report;
|
||||
}
|
||||
|
||||
public static Report createReport(RuleContext ctx, String fileName) {
|
||||
Report report = new Report();
|
||||
|
||||
// overtake the listener
|
||||
report.addSynchronizedListeners(ctx.getReport().getSynchronizedListeners());
|
||||
|
||||
ctx.setReport(report);
|
||||
ctx.setSourceCodeFilename(fileName);
|
||||
ctx.setSourceCodeFile(new File(fileName));
|
||||
return report;
|
||||
}
|
||||
|
||||
public static class ReadableDuration {
|
||||
private final long duration;
|
||||
|
||||
@ -112,7 +115,7 @@ public class Report {
|
||||
// Note that this and the above data structure are both being maintained for a bit
|
||||
private final List<RuleViolation> violations = new ArrayList<RuleViolation>();
|
||||
private final Set<Metric> metrics = new HashSet<Metric>();
|
||||
private final List<ReportListener> listeners = new ArrayList<ReportListener>();
|
||||
private final List<SynchronizedReportListener> listeners = new ArrayList<SynchronizedReportListener>();
|
||||
private List<ProcessingError> errors;
|
||||
private List<RuleConfigurationError> configErrors;
|
||||
private Map<Integer, String> linesToSuppress = new HashMap<Integer, String>();
|
||||
@ -164,7 +167,7 @@ public class Report {
|
||||
}
|
||||
|
||||
public void addListener(ReportListener listener) {
|
||||
listeners.add(listener);
|
||||
listeners.add(new SynchronizedReportListener(listener));
|
||||
}
|
||||
|
||||
public List<SuppressedViolation> getSuppressedRuleViolations() {
|
||||
@ -266,13 +269,13 @@ public class Report {
|
||||
}
|
||||
|
||||
public Iterator<ProcessingError> errors() {
|
||||
return errors == null ? EmptyIterator.instance : errors.iterator();
|
||||
return errors == null ? EmptyIterator.<ProcessingError> instance() : errors.iterator();
|
||||
}
|
||||
|
||||
public Iterator<RuleConfigurationError> configErrors() {
|
||||
return configErrors == null ? EmptyIterator.instance : errors.iterator();
|
||||
return configErrors == null ? EmptyIterator.<RuleConfigurationError> instance() : configErrors.iterator();
|
||||
}
|
||||
|
||||
|
||||
public int treeSize() {
|
||||
return violationTree.size();
|
||||
}
|
||||
@ -292,4 +295,12 @@ public class Report {
|
||||
public long getElapsedTimeInMillis() {
|
||||
return end - start;
|
||||
}
|
||||
|
||||
public List<SynchronizedReportListener> getSynchronizedListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
public void addSynchronizedListeners(List<SynchronizedReportListener> synchronizedListeners) {
|
||||
listeners.addAll(synchronizedListeners);
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +42,11 @@ public class RuleContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which shares attributes with the given RuleContext.
|
||||
* Constructor which shares attributes and report listeners with the given RuleContext.
|
||||
*/
|
||||
public RuleContext(RuleContext ruleContext) {
|
||||
this.attributes = ruleContext.attributes;
|
||||
this.report.addSynchronizedListeners(ruleContext.getReport().getSynchronizedListeners());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd;
|
||||
|
||||
import net.sourceforge.pmd.stat.Metric;
|
||||
|
||||
/**
|
||||
* Wraps a report listener in order to synchronize calls to it.
|
||||
*/
|
||||
public final class SynchronizedReportListener implements ReportListener {
|
||||
|
||||
private final ReportListener wrapped;
|
||||
|
||||
public SynchronizedReportListener(ReportListener listener) {
|
||||
this.wrapped = listener;
|
||||
}
|
||||
|
||||
public synchronized void ruleViolationAdded(RuleViolation ruleViolation) {
|
||||
wrapped.ruleViolationAdded(ruleViolation);
|
||||
}
|
||||
|
||||
public synchronized void metricAdded(Metric metric) {
|
||||
wrapped.metricAdded(metric);
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
@ -9,10 +12,15 @@ import java.util.Iterator;
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class EmptyIterator<T extends Object> implements Iterator<T> {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final Iterator instance = new EmptyIterator();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final <T extends Object> Iterator<T> instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private EmptyIterator() {}
|
||||
|
||||
@ -23,4 +31,4 @@ public class EmptyIterator<T extends Object> implements Iterator<T> {
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user