15 December 2017
The PMD team is pleased to announce PMD 6.0.0.
This is a major release.
Thanks to Clément Fournier, we now have a new rule designer GUI, which is based on JavaFX. It replaces the old designer and can be started via
bin/run.sh designer
(on Unix-like platform such as Linux and Mac OS X)bin\designer.bat
(on Windows)Note: At least Java8 is required for the designer. The old designer is still available
as designerold
but will be removed with the next major release.
The Java grammar has been updated to support analyzing Java 9 projects:
module-info.java
can be parsedJava 9 support is enabled by default. You can switch back to an older java version
via the command line, e.g. -language java -version 1.8
.
We are now using the Apex Jorje Lexer to tokenize Apex code for CPD. This change means:
CPD will therefore have less false positives and false negatives.
As part of Google Summer of Code 2017, Bendegúz Nagy worked on type resolution for Java. For this release he has extended support for method calls for both instance and static methods.
Method shadowing and overloading are supported, as are varargs. However, the selection of the target method upon the presence of generics and type inference is still work in progress. Expect it in forecoming releases.
As for fields, the basic support was in place for release 5.8.0, but has now been expanded to support static fields.
As part of Google Summer of Code 2017, Clément Fournier is worked on the new metrics framework for object-oriented metrics.
There are already a couple of metrics (e.g. ATFD, WMC, Cyclo, LoC) implemented. More metrics are planned. Based on those metrics, rules like “GodClass” detection could be implemented more easily. The following rules benefit from the metrics framework: NcssCount (java), NPathComplexity (java), CyclomaticComplexity (both java and apex).
The Metrics framework has been abstracted and is available in pmd-core
for other languages. With this
PMD release, the metrics framework is supported for both Java and Apex.
A number of improvements on error reporting have taken place, meaning changes to some of the report formats.
Also of note, the xml report now provides a XML Schema definition, allowing easier parsing and validation.
Processing errors can now provide not only the message previously included on some reports, but also a full stacktrace. This will allow better error reports when providing feedback to the PMD team and help in debugging issues.
The report formats providing full stacktrace of errors are:
For a long time reports have been notified of configuration errors on rules, but they have remained hidden. On a push to make these more evident to users, and help them get the best results out of PMD, we have started to include them on the reports.
So far, only reports that include processing errors are showing configuration errors. In other words, the report formats providing configuration error reporting are:
As we move forward we will be able to detect and report more configuration errors (ie: incomplete auxclasspath
)
and include them to such reports.
Apex violations can now be suppressed very similarly to how it’s done in Java, by making use of a
@SuppressWarnings
annotation.
Supported syntax includes:
@SupressWarnings('PMD') // to supress all Apex rules
@SupressWarnings('all') // to supress all Apex rules
@SupressWarnings('PMD.ARuleName') // to supress only the rule named ARuleName
@SupressWarnings('PMD.ARuleName, PMD.AnotherRuleName') // to supress only the rule named ARuleName or AnotherRuleName
Notice this last scenario is slightly different to the Java syntax. This is due to differences in the Apex grammar for annotations.
All built-in rules have been sorted into one of eight categories:
These categories help you to find rules and figure out the relevance and impact for your project.
All rules have been moved accordingly, e.g. the rule “JumbledIncrementer”, which was previously defined in the
ruleset “java-basic” has now been moved to the “Error Prone” category. The new rule reference to be used is
<rule ref="category/java/errorprone.xml/JumbledIncrementer"/>
.
The old rulesets like “java-basic” are still kept for backwards-compatibility but will be removed eventually. The rule reference documentation has been updated to reflect these changes.
The new Java rule NcssCount
(category design
) replaces the three rules “NcssConstructorCount”, “NcssMethodCount”,
and “NcssTypeCount”. The new rule uses the metrics framework to achieve the same. It has two properties, to
define the report level for method and class sizes separately. Constructors and methods are considered the same.
The new Java rule DoNotExtendJavaLangThrowable
(category errorprone
) is a companion for the
java-strictexception.xml/DoNotExtendJavaLangError
, detecting direct extensions of java.lang.Throwable
.
The new Java rule ForLoopCanBeForeach
(category errorprone
) helps to identify those for-loops that can
be safely refactored into for-each-loops available since java 1.5.
The new Java rule AvoidFileStream
(category performance
) helps to identify code relying on FileInputStream
/ FileOutputStream
which, by using a finalizer, produces extra / unnecessary overhead to garbage collection, and should be replaced with
Files.newInputStream
/ Files.newOutputStream
available since java 1.7.
The new Java rule DataClass
(category design
) detects simple data-holders without behaviour. This might indicate
that the behaviour is scattered elsewhere and the data class exposes the internal data structure,
which breaks encapsulation.
The new Apex rule AvoidDirectAccessTriggerMap
(category errorprone
) helps to identify direct array access to triggers,
which can produce bugs by either accessing non-existing indexes, or leaving them out. You should use for-each-loops
instead.
The new Apex rule AvoidHardcodingId
(category errorprone
) detects hardcoded strings that look like identifiers
and flags them. Record IDs change between environments, meaning hardcoded ids are bound to fail under a different
setup.
The new Apex rule CyclomaticComplexity
(category design
) detects overly complex classes and methods. The
report threshold can be configured separately for classes and methods.
errorprone
.
The 5 rules are migrated for Apex from the equivalent Java rules and include:
EmptyCatchBlock
to detect catch blocks completely ignoring exceptions.EmptyIfStmt
for if blocks with no content, that can be safely removed.EmptyTryOrFinallyBlock
for empty try / finally blocks that can be safely removed.EmptyWhileStmt
for empty while loops that can be safely removed.EmptyStatementBlock
for empty code blocks that can be safely removed.AvoidSoslInLoops
(category performance
) is the companion of the old
AvoidSoqlInLoops
rule, flagging SOSL (Salesforce Object Search Language) queries when within
loops, to avoid governor issues, and hitting the database too often.The Java rule UnnecessaryFinalModifier
(category codestyle
, former ruleset java-unnecessarycode
)
has been merged into the rule UnnecessaryModifier
. As part of this, the rule has been revamped to detect more cases.
It will now flag anonymous class’ methods marked as final (can’t be overridden, so it’s pointless), along with
final methods overridden / defined within enum instances. It will also flag final
modifiers on try-with-resources.
The Java rule UnnecessaryParentheses
(category codestyle
, former ruleset java-controversial
)
has been merged into UselessParentheses
(category codestyle
, former ruleset java-unnecessary
).
The rule covers all scenarios previously covered by either rule.
The Java rule UncommentedEmptyConstructor
(category documentation
, former ruleset java-design
)
will now ignore empty constructors annotated with javax.inject.Inject
.
The Java rule AbstractClassWithoutAnyMethod
(category bestpractices
, former ruleset java-design
)
will now ignore classes annotated with com.google.auto.value.AutoValue
.
The Java rule GodClass
(category design', former ruleset
java-design`) has been revamped to use
the new metrics framework.
The Java rule LooseCoupling
(category bestpractices
, former ruleset java-coupling
) has been
replaced by the typeresolution-based implementation.
The Java rule CloneMethodMustImplementCloneable
(category errorprone
, former ruleset java-clone
)
has been replaced by the typeresolution-based
implementation and is now able to detect cases if a class implements or extends a Cloneable class/interface.
The Java rule UnusedImports
(category bestpractices
, former ruleset java-imports
) has been
replaced by the typeresolution-based
implementation and is now able to detect unused on-demand imports.
The Java rule SignatureDeclareThrowsException
(category design
, former ruleset ‘java-strictexception’)
has been replaced by the
typeresolution-based implementation. It has a new property IgnoreJUnitCompletely
, which allows all
methods in a JUnit testcase to throw exceptions.
The Java rule NPathComplexity
(category design
, former ruleset java-codesize
) has been revamped
to use the new metrics framework.
Its report threshold can be configured via the property reportLevel
, which replaces the now
deprecated property minimum
.
The Java rule CyclomaticComplexity
(category design
, former ruleset java-codesize
) has been
revamped to use the new metrics framework.
Its report threshold can be configured via the properties classReportLevel
and methodReportLevel
separately.
The old property reportLevel
, which configured the level for both total class and method complexity,
is deprecated.
CommentRequired
(category documentation
, former ruleset java-comments
)
has been revamped to include 2 new properties:
accessorCommentRequirement
to specify documentation requirements for getters and setters (default to ignored
)methodWithOverrideCommentRequirement
to specify documentation requirements for methods annotated with @Override
(default to ignored
)The Java rule EmptyCatchBlock
(category errorprone
, former ruleset java-empty
) has been changed to ignore
exceptions named ignore
or expected
by default. You can still override this behaviour by setting the allowExceptionNameRegex
property.
OptimizableToArrayCall
(category performance
, former ruleset design
) has been
modified to fit for the current JVM implementations: It basically detects now the opposite and suggests to
use Collection.toArray(new E[0])
with a zero-sized array.
See Arrays of Wisdom of the Ancients.The Java rules NcssConstructorCount
, NcssMethodCount
, and NcssTypeCount
(ruleset java-codesize
) have been
deprecated. They will be replaced by the new rule NcssCount
in the category design
.
The Java rule LooseCoupling
in ruleset java-typeresolution
is deprecated. Use the rule with the same name
from category bestpractices
instead.
The Java rule CloneMethodMustImplementCloneable
in ruleset java-typeresolution
is deprecated. Use the rule with
the same name from category errorprone
instead.
The Java rule UnusedImports
in ruleset java-typeresolution
is deprecated. Use the rule with
the same name from category bestpractices
instead.
The Java rule SignatureDeclareThrowsException
in ruleset java-typeresolution
is deprecated. Use the rule
with the same name from category design
instead.
The Java rule EmptyStaticInitializer
in ruleset java-empty
is deprecated. Use the rule EmptyInitializer
from the category errorprone
, which covers both static and non-static empty initializers.`
The Java rules GuardDebugLogging
(ruleset java-logging-jakarta-commons
) and GuardLogStatementJavaUtil
(ruleset java-logging-java
) have been deprecated. Use the rule GuardLogStatement
from the
category bestpractices
, which covers all cases regardless of the logging framework.
UseSingleton
has been removed from the ruleset java-design
. The rule has been renamed
long time ago to UseUtilityClass
(category design
).A bug in symbol table prevented
the symbol table analysis to properly match primitive arrays types. The issue affected the java-unsedcode/UnusedPrivateMethod
rule, but other rules may now produce improved results as consequence of this fix.
The Apex parser version was bumped, from 1.0-sfdc-187
to 210-SNAPSHOT
. This update let us take full advantage
of the latest improvements from Salesforce, but introduces some breaking changes:
BlockStatements
are now created for all control structures, even if no brace is used. We have therefore added
a hasCurlyBrace
method to differentiate between both scenarios.CastExpression
, ConstructorPreamble
, IllegalStoreExpression
,
MethodBlockStatement
, Modifier
, MultiStatement
, NestedExpression
, NestedStoreExpression
,
NewKeyValueObjectExpression
and StatementExecuted
TestNode
, DottedExpression
and NewNameValueObjectExpression
(replaced by NewKeyValueObjectExpression
)All existing rules have been updated to reflect these changes. If you have custom rules, be sure to update them.
For more info about the included Apex parser, see the new pmd module “pmd-apex-jorje”, which packages and provides the parser as a binary.
The incremental analysis feature first introduced in PMD 5.6.0 has been enhanced. A few minor issues have been fixed, and several improvements have been performed to make it more accurate.
The cache will now detect changes to the JARs referenced in the auxclasspath
instead of simply looking at their paths
and order. This means that if you are referencing a JAR you are overwriting in some way, the incremental analysis can
now detect it and invalidate it’s cache to avoid false reports.
Similarly, any changes to the execution classpath of PMD will invalidate the cache. This means that if you have custom rules packaged in a jar, any changes to it will invalidate the cache automatically.
We have also improved logging on the analysis code, allowing better insight into how the cache is performing, under debug / verbose builds you can even see individual hits / misses to the cache (and the reason for any miss!)
Finally, as this feature keeps maturing, we are gently pushing this forward. If not using incremental analysis, a warning will now be produced suggesting users to adopt it for better performance.
The implementation around the properties support for rule properties and report properties has been revamped
to be fully typesafe. Along with that change, the support classes have been moved into an own
package net.sourceforge.pmd.properties
. While there is no change necessary in the ruleset XML files,
when using/setting values for rules, there are adjustments necessary when declaring properties in Java-implemented
rules.
Rule properties can be declared both for Java based rules and XPath rules. This is now very well documented in Working with properties.
With PMD 6.0.0, multivalued properties are now also possible with XPath rules.
The class net.sourceforge.pmd.lang.dfa.NodeType
has been converted to an enum.
All node types are enum members now instead of int constants. The names for node types are retained.
The Properties API (rule and report properties) has been revamped to be fully typesafe. This is everything
around net.sourceforge.pmd.properties.PropertyDescriptor
.
Note: All classes related to properties have been moved into the package net.sourceforge.pmd.properties
.
The rule classes net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestClassShouldHaveAsserts
and net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestShouldNotUseSeeAllDataTrue
have been
renamed to ApexUnitTestClassShouldHaveAssertsRule
and ApexUnitTestShouldNotUseSeeAllDataTrueRule
,
respectively. This is to comply with the naming convention, that each rule class should be suffixed with “Rule”.
This change has no impact on custom rulesets, since the rule names themselves didn’t change.
The never implemented method PMD.processFiles(PMDConfiguration, RuleSetFactory, Collection<File>, RuleContext, ProgressMonitor)
along with the interface ProgressMonitor
has been removed.
The method PMD.setupReport(RuleSets, RuleContext, String)
is gone. It was used to report dysfunctional
rules. But PMD does this now automatically before processing the files, so there is no need for this
method anymore.
Renderer.getPropertyDefinitions
AbstractRenderer.defineProperty(String, String)
AbstractRenderer.propertyDefinitions
ReportListener
Report.addListener(ReportListener)
SynchronizedReportListener
CPDConfiguration.CPDConfiguration(int, Language, String)
CPDConfiguration.getRendererFromString(String)
StreamUtil
StringUtil.appendXmlEscaped(StringBuilder, String)
StringUtil.htmlEncode(String)
net.sourceforge.pmd.util.CollectionUtil
have been deprecated and will be removed in PMD 7.0.0. In particular:
CollectionUtil.addWithoutDuplicates(T[], T)
CollectionUtil.addWithoutDuplicates(T[], T[])
CollectionUtil.areSemanticEquals(T[], T[])
CollectionUtil.areEqual(Object, Object)
CollectionUtil.arraysAreEqual(Object, Object)
CollectionUtil.valuesAreTransitivelyEqual(Object[], Object[])
net.sourceforge.pmd.util.StringUtil
have been deprecated and will be removed in PMD 7.0.0. In particular:
StringUtil.startsWithAny(String, String[])
StringUtil.isNotEmpty(String)
StringUtil.isEmpty(String)
StringUtil.isMissing(String)
StringUtil.areSemanticEquals(String, String)
StringUtil.replaceString(String, String, String)
StringUtil.replaceString(String, char, String)
StringUtil.substringsOf(String, char)
StringUtil.substringsOf(String, String)
StringUtil.asStringOn(StringBuffer, Iterator, String)
StringUtil.asStringOn(StringBuilder, Object[], String)
StringUtil.lpad(String, int)
The class net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition
is now abstract, and has been enhanced
to provide several new methods.
The constructor of net.sourceforge.pmd.RuleSetFactory
, which took a ClassLoader
is deprecated.
Please use the alternative constructor with the net.sourceforge.pmd.util.ResourceLoader
instead.
bgastviewer.bat
or run.sh bgastviewer
is
deprecated, too, and will be removed in PMD 7.0.0.
Both the “old designer” and “bgastviewer” are replaced by the New Rule Designer.
net.sourceforge.pmd.util.designer.CodeEditorTextPane
net.sourceforge.pmd.util.designer.CreateXMLRulePanel
net.sourceforge.pmd.util.designer.Designer
net.sourceforge.pmd.util.designer.DFAPanel
net.sourceforge.pmd.util.designer.LineGetter
net.sourceforge.pmd.util.viewer.Viewer
net.sourceforge.pmd.util.viewer.gui.ActionCommands
net.sourceforge.pmd.util.viewer.gui.ASTPanel
net.sourceforge.pmd.util.viewer.gui.EvaluationResultsPanel
net.sourceforge.pmd.util.viewer.gui.MainFrame
net.sourceforge.pmd.util.viewer.gui.ParseExceptionHandler
net.sourceforge.pmd.util.viewer.gui.SourceCodePanel
net.sourceforge.pmd.util.viewer.gui.XPathPanel
net.sourceforge.pmd.util.viewer.gui.menu.ASTNodePopupMenu
net.sourceforge.pmd.util.viewer.gui.menu.AttributesSubMenu
net.sourceforge.pmd.util.viewer.gui.menu.SimpleNodeSubMenu
net.sourceforge.pmd.util.viewer.gui.menu.XPathFragmentAddingItem
net.sourceforge.pmd.util.viewer.model.ASTModel
net.sourceforge.pmd.util.viewer.model.AttributeToolkit
net.sourceforge.pmd.util.viewer.model.SimpleNodeTreeNodeAdapter
net.sourceforge.pmd.util.viewer.model.ViewerModel
net.sourceforge.pmd.util.viewer.model.ViewerModelEvent
net.sourceforge.pmd.util.viewer.model.ViewerModelListener
net.sourceforge.pmd.util.viewer.util.NLS
net.sourceforge.pmd.Rule
have been deprecated and will be removed in PMD 7.0.0.
All methods are replaced by their bean-like counterparts
void setUsesDFA()
. Use void setDfa(boolean)
instead.boolean usesDFA()
. Use boolean isDfa()
instead.void setUsesTypeResolution()
. Use void setTypeResolution(boolean)
instead.boolean usesTypeResolution()
. Use boolean isTypeResolution()
instead.void setUsesMultifile()
. Use void setMultifile(boolean)
instead.boolean usesMultifile()
. Use boolean isMultifile()
instead.boolean usesRuleChain()
. Use boolean isRuleChain()
instead.