diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 4cf6811725..69bf8669f2 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -76,6 +76,7 @@ Each `` element in the XML format now has 3 new attributes: * apex * [#2208](https://github.com/pmd/pmd/issues/2208): \[apex] ASTFormalComment should implement ApexNode<T> * core + * [#1984](https://github.com/pmd/pmd/issues/1984): \[java] Cyclomatic complexity is misreported (lack of clearing metrics cache) * [#2006](https://github.com/pmd/pmd/issues/2006): \[core] PMD should warn about multiple instances of the same rule in a ruleset * [#2161](https://github.com/pmd/pmd/issues/2161): \[core] ResourceLoader is deprecated and marked as internal but is exposed * [#2170](https://github.com/pmd/pmd/issues/2170): \[core] DocumentFile doesn't preserve newlines diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java index ed2a66c5e4..9862a8515b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd.lang.apex; import java.io.Writer; -import java.util.Arrays; -import java.util.List; import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler; import net.sourceforge.pmd.lang.Parser; @@ -17,14 +15,11 @@ import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.ast.DumpFacade; -import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsComputer; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsProvider; import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileVisitorFacade; import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory; import net.sourceforge.pmd.lang.ast.xpath.DefaultASTXPathHandler; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; @@ -70,26 +65,4 @@ public class ApexHandler extends AbstractLanguageVersionHandler { public LanguageMetricsProvider, ASTMethod> getLanguageMetricsProvider() { return myMetricsProvider; } - - - private static class ApexMetricsProvider extends AbstractLanguageMetricsProvider, ASTMethod> { - - @SuppressWarnings("unchecked") - ApexMetricsProvider() { - // a wild double cast - super((Class>) (Object) ASTUserClassOrInterface.class, ASTMethod.class, ApexMetricsComputer.getInstance()); - } - - - @Override - public List getAvailableTypeMetrics() { - return Arrays.asList(ApexClassMetricKey.values()); - } - - - @Override - public List getAvailableOperationMetrics() { - return Arrays.asList(ApexOperationMetricKey.values()); - } - } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java index 2e01e30668..30d1fae6a1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java @@ -37,7 +37,10 @@ public final class ApexMetrics { } - /** Resets the entire data structure. Used for tests. */ + /** + * Resets the entire data structure. + * This needs to be done in case PMD is executed multiple times within one JVM run. + */ static void reset() { FACADE.reset(); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java new file mode 100644 index 0000000000..c3a227b24c --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java @@ -0,0 +1,39 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.metrics; + +import java.util.Arrays; +import java.util.List; + +import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; +import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; + +public class ApexMetricsProvider extends AbstractLanguageMetricsProvider, ASTMethod> { + + @SuppressWarnings("unchecked") + public ApexMetricsProvider() { + // a wild double cast + super((Class>) (Object) ASTUserClassOrInterface.class, ASTMethod.class, ApexMetricsComputer.getInstance()); + } + + @Override + public void initialize() { + ApexMetrics.reset(); + } + + @Override + public List getAvailableTypeMetrics() { + return Arrays.asList(ApexClassMetricKey.values()); + } + + + @Override + public List getAvailableOperationMetrics() { + return Arrays.asList(ApexOperationMetricKey.values()); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java index ec57cceff9..a1b84240ce 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java @@ -31,6 +31,12 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; @Experimental public interface LanguageMetricsProvider { + /** + * Provides a hook to do any initializing before the first file is processed by PMD. + * This can be used by the metrics implementations to reset the cache. + */ + void initialize(); + /** * Returns a list of all supported type metric keys * for the language. 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 9b1af9682c..ee0bb7f382 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 @@ -24,6 +24,9 @@ import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.util.datasource.DataSource; @@ -114,6 +117,8 @@ public abstract class AbstractPMDProcessor { configuration.getAnalysisCache().checkValidity(rs, configuration.getClassLoader()); final SourceCodeProcessor processor = new SourceCodeProcessor(configuration); + resetMetrics(); + for (final DataSource dataSource : files) { // this is the real, canonical and absolute filename (not shortened) String realFileName = dataSource.getNiceFileName(false, null); @@ -134,6 +139,15 @@ public abstract class AbstractPMDProcessor { } } + private void resetMetrics() { + for (Language language : LanguageRegistry.getLanguages()) { + LanguageMetricsProvider languageMetricsProvider = language.getDefaultVersion().getLanguageVersionHandler().getLanguageMetricsProvider(); + if (languageMetricsProvider != null) { + languageMetricsProvider.initialize(); + } + } + } + protected abstract void runAnalysis(PmdRunnable runnable); protected abstract void collectReports(List renderers); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java index 03ca3ba425..59ab1ca3b7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd.lang.java; import java.io.Writer; -import java.util.Arrays; -import java.util.List; import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler; import net.sourceforge.pmd.lang.DataFlowHandler; @@ -23,9 +21,7 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.java.dfa.DataFlowFacade; import net.sourceforge.pmd.lang.java.dfa.JavaDFAGraphRule; -import net.sourceforge.pmd.lang.java.metrics.JavaMetricsComputer; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.JavaMetricsProvider; import net.sourceforge.pmd.lang.java.multifile.MultifileVisitorFacade; import net.sourceforge.pmd.lang.java.qname.QualifiedNameResolver; import net.sourceforge.pmd.lang.java.rule.JavaRuleViolationFactory; @@ -38,8 +34,6 @@ import net.sourceforge.pmd.lang.java.xpath.TypeIsExactlyFunction; import net.sourceforge.pmd.lang.java.xpath.TypeIsFunction; import net.sourceforge.pmd.lang.java.xpath.TypeOfFunction; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.MetricKey; -import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; import net.sf.saxon.sxpath.IndependentContext; @@ -169,25 +163,4 @@ public abstract class AbstractJavaHandler extends AbstractLanguageVersionHandler public LanguageMetricsProvider getLanguageMetricsProvider() { return myMetricsProvider; } - - - private static class JavaMetricsProvider extends AbstractLanguageMetricsProvider { - - - JavaMetricsProvider() { - super(ASTAnyTypeDeclaration.class, MethodLikeNode.class, JavaMetricsComputer.getInstance()); - } - - - @Override - public List> getAvailableTypeMetrics() { - return Arrays.asList(JavaClassMetricKey.values()); - } - - - @Override - public List> getAvailableOperationMetrics() { - return Arrays.asList(JavaOperationMetricKey.values()); - } - } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java index 5e889e0439..de4282675d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java @@ -38,7 +38,10 @@ public final class JavaMetrics { } - /** Resets the entire data structure. Used for tests. */ + /** + * Resets the entire data structure. + * This needs to be done in case PMD is executed multiple times within one JVM run. + */ static void reset() { FACADE.reset(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java new file mode 100644 index 0000000000..8070454c64 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java @@ -0,0 +1,38 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics; + +import java.util.Arrays; +import java.util.List; + +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; +import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.metrics.MetricKey; +import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; + +public class JavaMetricsProvider extends AbstractLanguageMetricsProvider { + + public JavaMetricsProvider() { + super(ASTAnyTypeDeclaration.class, MethodLikeNode.class, JavaMetricsComputer.getInstance()); + } + + @Override + public void initialize() { + JavaMetrics.reset(); + } + + @Override + public List> getAvailableTypeMetrics() { + return Arrays.asList(JavaClassMetricKey.values()); + } + + + @Override + public List> getAvailableOperationMetrics() { + return Arrays.asList(JavaOperationMetricKey.values()); + } +}