From cc5ce5cdf909c87cce5dc6fa36f9533e95f9fc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Fri, 20 Jan 2017 09:53:08 -0300 Subject: [PATCH 1/3] Update changelog --- src/site/markdown/overview/changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 1f9cddfc37..7681c9b6c0 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -45,6 +45,8 @@ This is a bug fixing release, no major changes were introduced. * [#1518](https://sourceforge.net/p/pmd/bugs/1518/): \[xml] Error while processing xml file with ".webapp" in the file or directory name * psql * [#1549](https://sourceforge.net/p/pmd/bugs/1549/): \[plsql] Parse error for IS [NOT] NULL construct +* javascript + * [#201](https://github.com/pmd/pmd/issues/201): \[javascript] template strings are not correctly parsed ### External Contributions @@ -53,4 +55,5 @@ This is a bug fixing release, no major changes were introduced. * [#152](https://github.com/pmd/pmd/pull/152): \[java] fixes #1552 continue does not require break * [#154](https://github.com/pmd/pmd/pull/154): \[java] Fix #1547: UnusedImports: Adjust regex to support underscores * [#170](https://github.com/pmd/pmd/pull/170): \[core] Ant Task Formatter encoding issue with XMLRenderer +* [#200](https://github.com/pmd/pmd/pull/200): \[javascript] Templatestring grammar fix From 3caa71b94b016902ee1a41f0390d04dc3153a1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Fri, 13 Jan 2017 20:24:20 -0300 Subject: [PATCH 2/3] Resolve #180 - refactor pmd processors - SourceCodeProcessor now consistently calls rule sets start / end if cache is not up to date - Both Mono and MultiThread Processors rely on PmdRunnable, just using different execution strategies - This also fixes https://sourceforge.net/p/pmd/bugs/1511/ --- .../sourceforge/pmd/SourceCodeProcessor.java | 43 +++-- .../pmd/processor/AbstractPMDProcessor.java | 34 +++- .../pmd/processor/MonoThreadProcessor.java | 86 ++------- .../pmd/processor/MultiThreadProcessor.java | 107 +++++------ .../pmd/processor/PmdRunnable.java | 169 ++++++++---------- .../pmd/processor/PmdThreadFactory.java | 30 +--- .../pmd/testframework/RuleTst.java | 2 - .../markdown/customizing/howtowritearule.md | 8 +- 8 files changed, 194 insertions(+), 285 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java index a4c30e2f0d..915f7954e7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java @@ -10,15 +10,19 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; +import org.apache.commons.io.IOUtils; + import net.sourceforge.pmd.benchmark.Benchmark; import net.sourceforge.pmd.benchmark.Benchmarker; -import net.sourceforge.pmd.lang.*; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.lang.LanguageVersionHandler; +import net.sourceforge.pmd.lang.Parser; +import net.sourceforge.pmd.lang.VisitorStarter; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.xpath.Initializer; -import org.apache.commons.io.IOUtils; - public class SourceCodeProcessor { private final PMDConfiguration configuration; @@ -64,25 +68,26 @@ public class SourceCodeProcessor { * not be parsed, or other error is encountered. */ public void processSourceCode(Reader sourceCode, RuleSets ruleSets, RuleContext ctx) throws PMDException { - determineLanguage(ctx); + determineLanguage(ctx); - // make sure custom XPath functions are initialized - Initializer.initialize(); + // make sure custom XPath functions are initialized + Initializer.initialize(); - // Coarse check to see if any RuleSet applies to file, will need to do a finer RuleSet specific check later - if (ruleSets.applies(ctx.getSourceCodeFile())) { + // Coarse check to see if any RuleSet applies to file, will need to do a finer RuleSet specific check later + if (ruleSets.applies(ctx.getSourceCodeFile())) { - try { - processSource(sourceCode, ruleSets,ctx); - - } catch (ParseException pe) { - throw new PMDException("Error while parsing " + ctx.getSourceCodeFilename(), pe); - } catch (Exception e) { - throw new PMDException("Error while processing " + ctx.getSourceCodeFilename(), e); - } finally { - IOUtils.closeQuietly(sourceCode); - } - } + try { + ruleSets.start(ctx); + processSource(sourceCode, ruleSets, ctx); + } catch (ParseException pe) { + throw new PMDException("Error while parsing " + ctx.getSourceCodeFilename(), pe); + } catch (Exception e) { + throw new PMDException("Error while processing " + ctx.getSourceCodeFilename(), e); + } finally { + IOUtils.closeQuietly(sourceCode); + ruleSets.end(ctx); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index d5fbdbfe6e..57e86d39c3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -8,9 +8,11 @@ import java.util.List; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RulesetsFactoryUtils; +import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.benchmark.Benchmark; import net.sourceforge.pmd.benchmark.Benchmarker; import net.sourceforge.pmd.renderers.Renderer; @@ -22,15 +24,14 @@ import net.sourceforge.pmd.util.datasource.DataSource; */ public abstract class AbstractPMDProcessor { - protected final PMDConfiguration configuration; + protected final PMDConfiguration configuration; - public AbstractPMDProcessor(PMDConfiguration configuration) { - this.configuration = configuration; - } + public AbstractPMDProcessor(PMDConfiguration configuration) { + this.configuration = configuration; + } - public void renderReports(final List renderers, final Report report) { - - long start = System.nanoTime(); + public void renderReports(final List renderers, final Report report) { + long start = System.nanoTime(); try { for (Renderer r : renderers) { @@ -62,5 +63,22 @@ public abstract class AbstractPMDProcessor { protected RuleSets createRuleSets(RuleSetFactory factory) { return RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), factory); } - + + public void processFiles(RuleSetFactory ruleSetFactory, List files, RuleContext ctx, + List renderers) { + SourceCodeProcessor processor = new SourceCodeProcessor(configuration); + + for (DataSource dataSource : files) { + String niceFileName = filenameFrom(dataSource); + + runAnalysis(new PmdRunnable(configuration, dataSource, niceFileName, renderers, + ctx, ruleSetFactory, processor)); + } + + collectReports(renderers); + } + + protected abstract void runAnalysis(PmdRunnable runnable); + + protected abstract void collectReports(List renderers); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java index c71fc8e620..b7c147490b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java @@ -3,23 +3,12 @@ */ package net.sourceforge.pmd.processor; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import net.sourceforge.pmd.PMDConfiguration; -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.PMDException; import net.sourceforge.pmd.Report; -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSets; -import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.renderers.Renderer; -import net.sourceforge.pmd.util.datasource.DataSource; /** * @author Romain Pelisse @@ -27,62 +16,25 @@ import net.sourceforge.pmd.util.datasource.DataSource; */ public final class MonoThreadProcessor extends AbstractPMDProcessor { - public MonoThreadProcessor(PMDConfiguration configuration) { - super(configuration); - } + private final List reports = new ArrayList<>(); + + public MonoThreadProcessor(PMDConfiguration configuration) { + super(configuration); + } - private static final Logger LOG = Logger.getLogger(MonoThreadProcessor.class.getName()); + @Override + protected void runAnalysis(PmdRunnable runnable) { + // single thread execution, run analysis on same thread + reports.add(runnable.call()); + } - public void processFiles(RuleSetFactory ruleSetFactory, List files, - RuleContext ctx, List renderers) { + @Override + protected void collectReports(List renderers) { + for (Report r : reports) { + super.renderReports(renderers, r); + } - // single threaded execution - - RuleSets rs = createRuleSets(ruleSetFactory); - SourceCodeProcessor processor = new SourceCodeProcessor(configuration); - - for (DataSource dataSource : files) { - String niceFileName = filenameFrom(dataSource); - - Report report = PMD.setupReport(rs, ctx, niceFileName); - - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Processing " + ctx.getSourceCodeFilename()); - } - rs.start(ctx); - - for (Renderer r : renderers) { - r.startFileAnalysis(dataSource); - } - - try { - InputStream stream = new BufferedInputStream(dataSource.getInputStream()); - ctx.setLanguageVersion(null); - processor.processSourceCode(stream, rs, ctx); - } catch (PMDException pmde) { - if (LOG.isLoggable(Level.FINE)) { - LOG.log(Level.FINE, "Error while processing file: "+niceFileName, pmde.getCause()); - } - - report.addError(new Report.ProcessingError(pmde.getMessage(), niceFileName)); - } catch (IOException ioe) { - // unexpected exception: log and stop executor service - addError(report, "Unable to read source file", ioe, niceFileName); - } catch (RuntimeException re) { - // unexpected exception: log and stop executor service - addError(report, "RuntimeException while processing file", re, niceFileName); - } - - rs.end(ctx); - super.renderReports(renderers, ctx.getReport()); - } - } - - private void addError(Report report, String msg, Exception ex, String fileName) { - LOG.log(Level.FINE, msg, ex); - report.addError( - new Report.ProcessingError(ex.getMessage(), - fileName) - ); - } + // Since this thread may run PMD again, clean up the runnable + PmdRunnable.reset(); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java index 43b9083e23..98350efff6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java @@ -3,20 +3,19 @@ */ package net.sourceforge.pmd.processor; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.renderers.Renderer; -import net.sourceforge.pmd.util.datasource.DataSource; /** * @author Romain Pelisse @@ -24,66 +23,46 @@ import net.sourceforge.pmd.util.datasource.DataSource; */ public class MultiThreadProcessor extends AbstractPMDProcessor { + private ThreadFactory factory; + private ExecutorService executor; + private CompletionService completionService; + private List> tasks = new ArrayList<>(); + + public MultiThreadProcessor(final PMDConfiguration configuration) { + super(configuration); - public MultiThreadProcessor(final PMDConfiguration configuration) { - super(configuration); - } + factory = new PmdThreadFactory(); + executor = Executors.newFixedThreadPool(configuration.getThreads(), factory); + completionService = new ExecutorCompletionService<>(executor); + } - /** - * Run PMD on a list of files using multiple threads. - */ - public void processFiles(final RuleSetFactory ruleSetFactory, final List files, - final RuleContext ctx, final List renderers) { - - RuleSets rs = createRuleSets(ruleSetFactory); - rs.start(ctx); - - PmdThreadFactory factory = new PmdThreadFactory(ruleSetFactory, ctx); - ExecutorService executor = Executors.newFixedThreadPool( - configuration.getThreads(), factory); - List> tasks = new LinkedList<>(); - - for (DataSource dataSource : files) { - String niceFileName = filenameFrom(dataSource); - - PmdRunnable r = new PmdRunnable(executor, configuration, - dataSource, niceFileName, renderers); - Future future = executor.submit(r); - tasks.add(future); - } - executor.shutdown(); - - processReports(renderers, tasks); - - rs.end(ctx); - super.renderReports(renderers, ctx.getReport()); - - } - - private void processReports(final List renderers, List> tasks) throws Error { - - while (!tasks.isEmpty()) { - Future future = tasks.remove(0); - Report report = null; - try { - report = future.get(); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - future.cancel(true); - } catch (ExecutionException ee) { - Throwable t = ee.getCause(); - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } else if (t instanceof Error) { - throw (Error) t; - } else { - throw new IllegalStateException( - "PmdRunnable exception", t); - } - } - - super.renderReports(renderers, report); - } - } + @Override + protected void runAnalysis(PmdRunnable runnable) { + // multi-threaded execution, dispatch analysis to worker threads + tasks.add(completionService.submit(runnable)); + } + @Override + protected void collectReports(List renderers) { + // Collect result analysis, waiting for termination if needed + try { + for (int i = 0; i < tasks.size(); i++) { + final Report report = completionService.take().get(); + super.renderReports(renderers, report); + } + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } catch (ExecutionException ee) { + Throwable t = ee.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t instanceof Error) { + throw (Error) t; + } else { + throw new IllegalStateException("PmdRunnable exception", t); + } + } finally { + executor.shutdownNow(); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java index 6e898d6495..281a8ea9f4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java @@ -8,126 +8,101 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; import java.util.logging.Level; import java.util.logging.Logger; -import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.PMD; +import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.PMDException; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSets; +import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.util.datasource.DataSource; -public class PmdRunnable extends PMD implements Callable { +public class PmdRunnable implements Callable { - private static final Logger LOG = Logger.getLogger(PmdRunnable.class.getName()); + private static final Logger LOG = Logger.getLogger(PmdRunnable.class.getName()); - private final ExecutorService executor; - private final DataSource dataSource; - private final String fileName; - private final List renderers; + private static final ThreadLocal LOCAL_THREAD_CONTEXT = new ThreadLocal<>(); - public PmdRunnable(ExecutorService executor, - PMDConfiguration configuration, DataSource dataSource, - String fileName, List renderers) { - super(configuration); - this.executor = executor; - this.dataSource = dataSource; - this.fileName = fileName; - this.renderers = renderers; - } + private final PMDConfiguration configuration; + private final DataSource dataSource; + private final String fileName; + private final List renderers; + private final RuleContext ruleContext; + private final RuleSetFactory ruleSetFactory; + private final SourceCodeProcessor sourceCodeProcessor; - // If we ever end up having a ReportUtil class, this method should be moved there... - private static void addError(Report report, Exception ex, String fileName) { - report.addError( - new Report.ProcessingError(ex.getMessage(), - fileName) - ); - } + public PmdRunnable(PMDConfiguration configuration, DataSource dataSource, String fileName, + List renderers, RuleContext ruleContext, RuleSetFactory ruleSetFactory, + SourceCodeProcessor sourceCodeProcessor) { + this.configuration = configuration; + this.dataSource = dataSource; + this.fileName = fileName; + this.renderers = renderers; + this.ruleContext = ruleContext; + this.ruleSetFactory = ruleSetFactory; + this.sourceCodeProcessor = sourceCodeProcessor; + } - private void addErrorAndShutdown(Report report, Exception e, String errorMessage) { - // unexpected exception: log and stop executor service - LOG.log(Level.FINE, errorMessage, e); - addError(report, e, fileName); - executor.shutdownNow(); - } - - public Report call() { - PmdThread thread = (PmdThread) Thread.currentThread(); + public static void reset() { + LOCAL_THREAD_CONTEXT.remove(); + } - RuleContext ctx = thread.getRuleContext(); - RuleSets rs = thread.getRuleSets(configuration.getRuleSets()); + private void addError(Report report, Exception e, String errorMessage) { + // unexpected exception: log and stop executor service + LOG.log(Level.FINE, errorMessage, e); + report.addError(new Report.ProcessingError(e.getMessage(), fileName)); + } - Report report = setupReport(rs, ctx, fileName); - - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Processing " + ctx.getSourceCodeFilename()); - } - for (Renderer r : renderers) { - r.startFileAnalysis(dataSource); - } + @Override + public Report call() { + ThreadContext tc = LOCAL_THREAD_CONTEXT.get(); + if (tc == null) { + try { + tc = new ThreadContext(ruleSetFactory.createRuleSets(configuration.getRuleSets()), + new RuleContext(ruleContext)); + } catch (RuleSetNotFoundException e) { + throw new RuntimeException(e); + } + LOCAL_THREAD_CONTEXT.set(tc); + } - try { - InputStream stream = new BufferedInputStream( - dataSource.getInputStream()); - ctx.setLanguageVersion(null); - this.getSourceCodeProcessor().processSourceCode(stream, rs, ctx); - } catch (PMDException pmde) { - if (LOG.isLoggable(Level.FINE)) { - LOG.log(Level.FINE, "Error while processing file: "+fileName, pmde.getCause()); - } - addError(report, pmde, fileName); - } catch (IOException ioe) { - addErrorAndShutdown(report, ioe, "IOException during processing of "+ fileName ); + Report report = PMD.setupReport(tc.ruleSets, tc.ruleContext, fileName); - } catch (RuntimeException re) { - addErrorAndShutdown(report, re,"RuntimeException during processing of " + fileName); - } - return report; - } - - private static class PmdThread extends Thread { + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("Processing " + tc.ruleContext.getSourceCodeFilename()); + } + for (Renderer r : renderers) { + r.startFileAnalysis(dataSource); + } - public PmdThread(int id, Runnable r, RuleSetFactory ruleSetFactory, - RuleContext ctx) { - super(r, "PmdThread " + id); - this.id = id; - context = new RuleContext(ctx); - this.ruleSetFactory = ruleSetFactory; - } + try { + InputStream stream = new BufferedInputStream(dataSource.getInputStream()); + tc.ruleContext.setLanguageVersion(null); + sourceCodeProcessor.processSourceCode(stream, tc.ruleSets, tc.ruleContext); + } catch (PMDException pmde) { + addError(report, pmde, "Error while processing file: " + fileName); + } catch (IOException ioe) { + addError(report, ioe, "IOException during processing of " + fileName); + } catch (RuntimeException re) { + addError(report, re, "RuntimeException during processing of " + fileName); + } - private final int id; - private RuleContext context; - private RuleSets rulesets; - private final RuleSetFactory ruleSetFactory; + return report; + } - public RuleContext getRuleContext() { - return context; - } + private static class ThreadContext { + /* default */ final RuleSets ruleSets; + /* default */ final RuleContext ruleContext; - public RuleSets getRuleSets(String rsList) { - if (rulesets == null) { - try { - rulesets = ruleSetFactory.createRuleSets(rsList); - } catch (Exception e) { - e.printStackTrace(); - } - } - return rulesets; - } - - @Override - public String toString() { - return "PmdThread " + id; - } - } - - public static Thread createThread(int id, Runnable r, - RuleSetFactory ruleSetFactory, RuleContext ctx) { - return new PmdThread(id, r,ruleSetFactory, ctx); - } + ThreadContext(RuleSets ruleSets, RuleContext ruleContext) { + this.ruleSets = ruleSets; + this.ruleContext = ruleContext; + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java index 1c11d72e0d..8c0bd34feb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java @@ -2,34 +2,16 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.processor; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.RuleSetFactory; - public class PmdThreadFactory implements ThreadFactory { - - private final RuleSetFactory ruleSetFactory; - private final RuleContext ctx; - private final AtomicInteger counter = new AtomicInteger(); - public PmdThreadFactory(RuleSetFactory ruleSetFactory, RuleContext ctx) { - this.ruleSetFactory = ruleSetFactory; - this.ctx = ctx; - } + private final AtomicInteger counter = new AtomicInteger(); - public Thread newThread(Runnable r) { - Thread t = PmdRunnable.createThread(counter.incrementAndGet(), r, - ruleSetFactory, ctx); - threadList.add(t); - return t; - } + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "PmdThread " + counter.incrementAndGet()); + } - public List threadList = Collections - .synchronizedList(new LinkedList()); - -} \ No newline at end of file +} diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java index b3a066cfb2..5a83052746 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java @@ -216,9 +216,7 @@ public abstract class RuleTst { ctx.setIgnoreExceptions(false); RuleSet rules = new RuleSet(); rules.addRule(rule); - rules.start(ctx); p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx); - rules.end(ctx); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/site/markdown/customizing/howtowritearule.md b/src/site/markdown/customizing/howtowritearule.md index 9731d8a9ad..ce5f6f906b 100644 --- a/src/site/markdown/customizing/howtowritearule.md +++ b/src/site/markdown/customizing/howtowritearule.md @@ -271,7 +271,7 @@ rule that checks stuff across the all source code? Let's take a dummy example. L rule that count how many Expression Node you have in your source code (told you, it was a dummy example :) ). You realize quite simply. You just have to add static field to the RulesContext, as an attribute, and uses -Rule.start() and Rule.end() hook to initialized and finalize your rule's implementation: +`Rule.start()` and `Rule.end()` hooks to initialize and finalize your rule's implementation: package net.sourceforge.pmd.rules; @@ -309,9 +309,9 @@ Rule.start() and Rule.end() hook to initialized and finalize your rule's impleme } } -As you can see in this example, the method start will be call the first time the rule is going to be used, -so you can initialize properly your rule here. Once the rule will have finished to parses the source code, -the method end() will be invoke you can assert there if, or not, your rule has been violated. +As you can see in this example, the method `start()` will be called once per file, right before it's analysis starts, +so you can initialize properly your rule here. Once the rule have finished analyzing the file's source code, +the method `end()` will be invoked you can assert there if your rule has been violated or not. Note that the example logs a violation **without** a proper classname. This is not really a good idea. From 8201ba0a064d5d54716fc9f5e9cdcf2813d95501 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Jan 2017 19:24:26 +0100 Subject: [PATCH 3/3] Update changelog --- src/site/markdown/overview/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 5fdf6597ca..f05e300fb7 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -55,6 +55,8 @@ See also [bugfix #1556](https://sourceforge.net/p/pmd/bugs/1556/). * [#1549](https://sourceforge.net/p/pmd/bugs/1549/): \[plsql] Parse error for IS [NOT] NULL construct * javascript * [#201](https://github.com/pmd/pmd/issues/201): \[javascript] template strings are not correctly parsed +* General + * [#1511](https://sourceforge.net/p/pmd/bugs/1511/): \[core] Inconsistent behavior of Rule.start/Rule.end ### External Contributions