Table of Contents
Previous versions of PMD can be downloaded here: Releases - pmd/pmd (GitHub)
29-May-2026 - 7.25.0
The PMD team is pleased to announce PMD 7.25.0.
This is a minor release.
Table Of Contents
- 🚀️ New and noteworthy
- 🌟️ New and Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🚀️ New and noteworthy
Updated ANTLR library to 4.13.2
We have updated the ANTLR library (parser generator) from 4.9.3 to the latest version 4.13.2, in order to be able to use the latest version of Apex parser library.
This is an incompatible update: In case you use custom language modules based on ANTLR, you need to make sure to regenerate all of your lexers and parsers with the new ANTLR version.
For the ANTLR based language modules, that PMD ships (kotlin and swift and various CPD modules), this is already done.
🌟️ New and Changed Rules
New Rules
- The new Java rule
JUnitJupiterTestNoPrivateModifierfind JUnit test classes and methods that are private. Test classes, test methods, and lifecycle methods are not required to be public, but they must not be private. Otherwise, they won’t be found by the test framework. - The new Java rule
UnnecessaryBlockreports blocks that are unnecessary as they don’t introduce a new scope. This rule helps simplify code structure by identifying and flagging redundant blocks that can make code harder to read and may be misleading. - The new Java rule
VariableDeclarationUsageDistanceflags local variables that are declared far from their usage, which can make code harder to read. The rule has a propertymaxDistancethat allows to configure the maximum allowed distance between declaration and usage. - The new Java rule
AssertStatementInTestdetects usages ofassertstatement in tests. These should be replaced by framework assertion methods such asassertEquals. Such methods provide better error messages and make test behave correctly when running without-ea.
Changed Rules
- The rule
OnlyOneReturnhas a new propertyallowGuardIfs. When this property is true, then guard ifs at the beginning of a method are allowed their return statements don’t count. - The rules
UseUtilityClassandClassNamingConventionsnow use the same definition of what a utility class is. The most significant change is, that classes withmain()methods are no longer considered utility classes byUseUtilityClass. - We are continuously working to improve the precision of violation reporting for various rules.
The goal is to ensure that rules report issues on the correct line and highlight only the relevant lines.
For example, instead of flagging an entire class declaration (including its body), we now generally report only
the class name. For more details, see [java] Single Line Warnings #730
and [java] Review reported locations of rules #3769. While this effort
is still ongoing, the following Java rules have been updated in this release:
AbstractClassWithoutAbstractMethodAbstractClassWithoutAnyMethodAtLeastOneConstructorAvoidDollarSignsAvoidCatchingGenericExceptionAvoidSynchronizedStatement(now reports only on synchronized keyword and not the whole synchronized block)ClassNamingConventionsClassWithOnlyPrivateConstructorsShouldBeFinalCommentDefaultAccessModifierCommentRequiredCouplingBetweenObjects(now reports only on class identifier and not whole compilation unit anymore)CyclomaticComplexityDataClassExcessiveImports(now reports only on imports and not the whole compilation unit anymore)ExcessiveParameterListExcessivePublicCountExhaustiveSwitchHasDefault(now reports only on switch keyword and not the whole switch block)GodClassImplicitFunctionalInterfaceJUnit5TestShouldBePackagePrivateLocalHomeNamingConventionLocalInterfaceSessionNamingConventionMissingSerialVersionUIDMissingStaticMethodInNonInstantiatableClassNcssCountNonExhaustiveSwitch(now reports only on switch keyword and not the whole switch block)NoPackagePublicMemberInNonPublicTypeShortClassNameSingleMethodSingletonSwitchDensity(now reports only on switch keyword and not the whole switch block)TestClassWithoutTestCasesTooFewBranchesForSwitch(now reports only on switch keyword and not the whole switch block)TooManyFields(now reports only on class identifier and not the whole class body anymore)TooManyMethods(now reports only on class identifier and not the whole class body anymore)TooManyStaticImports(now reports only on the first static import and not the whole compilation unit anymore)UnnecessaryModifierUseUtilityClass
Renamed rules and properties
- One rule and one property have been renamed to reflect the fact that they work for both JUnit 5 and 6:
- The rule
JUnitJupiterTestShouldBePackagePrivate(Java Best Practices) was renamed fromJUnit5TestShouldBePackagePrivate. - The property
junitJupiterTestPatternof ruleMethodNamingConventions(Java Code Style) was renamed fromjunit5TestPattern.
- The rule
The old names still work but are deprecated.
🐛️ Fixed Issues
- core
- doc
- #6708: [doc] Update minimal Java version for building PMD in documentation
- java
- #1102: [java] Improve consistency of utility class detection across rules
- #5721: [java] StackOverflowError in 7.17.0 with nested wildcard generics
- #5746: [java] Separate test sources and resources
- #6688: [java] LocalVariableCouldBeFinalRule API changed
- #6704: [java] Rename rules and properties with JUnit5 in the name
- java-bestpractices
- #3212: [java] Enhance UseStandardCharsets to flag some constructors of IO-related classes
- #3777: [java] New rule: AssertStatementInTest
- #5477: [java] JUnit5TestShouldBePackagePrivate is not applied when @Test method is only present in parent class
- #6606: [java] UnusedPrivateField: False positive on JUnit Jupiter @FieldSource
- #6681: [java] UnitTestShouldIncludeAssert: False positive with JUnitSoftAssertions Rule (JUnit 4)
- #6710: [java] UseStandardCharsets: False negative when using lowercase standard charset names
- #6719: [java] UseStandardCharsets: False negative with Java 22+ and UTF-32 charsets
- java-codestyle
- #2801: [java] OnlyOneReturn should have a property to allow early exits (guard clauses)
- #4350: [java] ClassNamingConventions: testClassPattern not applied to class that inherits all its @Test methods
- #6427: [java] UnnecessaryCast: False positive for long cast before bit-shift operations on int/byte
- #6602: [java] LocalVariableCouldBeFinal: False negative when multiple variables are declared at once
- #6622: [java] New rule: UnnecessaryBlock
- #6640: [java] New rule: VariableDeclarationUsageDistance
- java-design
- #559: [java] UseUtilityClass: False negative for constant only classes
- java-errorprone
- #3288: [java] New Rule: JUnit5TestNoPrivateModifier
- #4288: [java] Document that CallSuperFirst/CallSuperLast are Android specific
- #6163: [java] ConstructorCallsOverridableMethod: False positive when method is from enclosing class
- #6517: [java] UselessPureMethodCall: False negative for methods on IntStream/LongStream/DoubleStream
- #6652: [java] AvoidInstanceofChecksInCatchClause: false negative when pattern-matching instanceof
- #6712: [java] UnnecessaryBooleanAssertion: Use InvocationMatcher to find assertions
- java-multithreading
- kotlin
🚨️ API Changes
Deprecations
- java
FieldDeclarationsShouldBeAtStartOfClassRule#visitis an implementation detail ofFieldDeclarationsShouldBeAtStartOfClassRule. It will be removed in a later release.CyclomaticComplexityRule#visitTypeDeclis an implementation detail ofCyclomaticComplexityRule. It will be removed in a later release.SwitchDensityRule#visitSwitchLikeis an implementation detail ofSwitchDensityRule. It will be removed in a later release.
- kotlin
- The constructor
PmdKotlinParser#PmdKotlinParserhas been deprecated. UseKotlinLanguageModule#getInstance,createProcessor,servicesandgetParserinstead to retrieve a correctly configured parser instance. - The constructor
KotlinHandler#KotlinHandlerhas been deprecated. UsegetInstance,createProcessorandservicesinstead to access the LanguageVersionHandler for Kotlin. - The methods
KotlinInnerNode#getImageandKotlinInnerNode#hasImageEqualTohave been deprecated. They have not been used yet in Kotlin and the long-term plan is to remove these methods on each node. Concrete nodes (subclasses of KotlinInnerNode) should provide a more specific attribute like “getName” or “getIdentifier” instead and not rely on “getImage”.
The same deprecation has been done forKotlinTerminalNode.
See #4787 for more information.
- The constructor
Experimental API
- kotlin
KotlinLanguageProperties#PARSE_TIMEOUT_SECONDSKotlinLanguageProperties#getParseTimeoutSeconds- Multiple classes have been added that provide an experimental way to add custom attributes to nodes:
- Attributes can be accessed on each node in Java-based rules via
KotlinInnerNode#attributes.
The attributes are also automatically exposed for XPath rules.
✨️ Merged pull requests
- #6084: [java] Shrink reported locations for some rules - Sören Glimm (@UncleOwen)
- #6522: [java] Fix #6520: DoNotUseThreads: fix false positive on Thread.onSpinWait() - leemeii (@leemeii)
- #6524: [java] Fix #6517: UselessPureMethodCall: fix false negative for primitive streams - leemeii (@leemeii)
- #6553: [java] Fix StackOverflowError in TypeOps projection of cyclic captured type vars - Sebastian Lövdahl (@slovdahl)
- #6557: [java] New rule: AssertStatementInTest - Zbynek Konecny (@zbynek)
- #6561: [java] Fix #6163: ConstructorCallsOverridableMethod: False positive with call to enclosing class - Lukas Gräf (@lukasgraef)
- #6573: [java] Fix #6427: Add bitwise and/or/xor to BINARY_PROMOTED_OPS - Sören Glimm (@UncleOwen)
- #6587: [java] Fix #2801: Add a property to OnlyOneReturnRule to allow guard ifs - Sören Glimm (@UncleOwen)
- #6597: [java] Fix #3212: Enhance UseStandardCharsets - Sören Glimm (@UncleOwen)
- #6601: [java] Fix #4288: Document that CallSuperFirst and CallSuperLast are android only - Sören Glimm (@UncleOwen)
- #6603: [java] Fix #6602: Fix false negative in LocalVariableCouldBeFinalRule - Sören Glimm (@UncleOwen)
- #6604: [java] Fix #3288: New rule JUnit5TestNoPrivateModifierRule - Sören Glimm (@UncleOwen)
- #6605: [java] Fix #6308: Add syntax highlighting to MarkdownRenderer - Sören Glimm (@UncleOwen)
- #6619: [java] Fix #5746: Separate test sources and resources - Sören Glimm (@UncleOwen)
- #6623: [java] Cleanup: Remove TODO from ModifierOwner.getVisibility() - Sören Glimm (@UncleOwen)
- #6636: [java] OverridingThreadRun: Fix false negatives with other methods and anonymous classes - Zbynek Konecny (@zbynek)
- #6638: [java] Fix #559: Improve UseUtilityClassRule to trigger also on static members - Sören Glimm (@UncleOwen)
- #6639: [java] New rule: UnnecessaryBlock - Sören Glimm (@UncleOwen)
- #6640: [java] New rule: VariableDeclarationUsageDistance - Zbynek Konecny (@zbynek)
- #6646: [test] Split up AbstractRuleSetFactoryTest.testAllPMDBuiltInRulesMeetConventions() - Sören Glimm (@UncleOwen)
- #6650: [kotlin] Fix #6608: Improve kotlin parser error handling - Peter Paul Bakker (@stokpop)
- #6653: [kotlin] Fix #6648: Multi-dollar interpolation for regular strings - Peter Paul Bakker (@stokpop)
- #6654: [swift] Fix invalid swift token OSXApplicationExtension - Andreas Dangel (@adangel)
- #6657: [java] AvoidSynchronizedStatement: Improve rule doc - Andreas Dangel (@adangel)
- #6658: [doc] Fix capitalization of ANTLR in release notes - Zbynek Konecny (@zbynek)
- #6660: [kotlin] Fix #6659: Prevent parser hang via InterruptibleParserATNSimulator and parse timeout - Peter Paul Bakker (@stokpop)
- #6661: [java] Fix #6652: Support new-style instanceof (with pattern matching) in AvoidInstanceofChecksInCatchClause - Sören Glimm (@UncleOwen)
- #6670: [kotlin] Add AST improvements, KotlinAstUtil - Peter Paul Bakker (@stokpop)
- #6671: [java] Part of #4841: Deprecate unnecessary public methods in FieldDeclarationsShouldBeAtStartOfClassRule/CyclomaticComplexityRule/SwitchDensityRule - Sören Glimm (@UncleOwen)
- #6679: [chore] Fix typos in comments and documentation - Zbynek Konecny (@zbynek)
- #6680: [java] Fix #5477: JUnit5TestShouldBePackagePrivate is not applied when @Test method is only present in parent class - Sören Glimm (@UncleOwen)
- #6683: Fix duplicated “the” in Java and Visualforce comments - vip892766gma (@vip892766gma)
- #6686: [java] False positive for UnusedPrivateField referenced by @FieldSource - Zbynek Konecny (@zbynek)
- #6687: LocalVariableCouldBeFinalRule: Revert API change - Sören Glimm (@UncleOwen)
- #6689: [java] Fix #4350: Fix ClassNamingConventions by teaching TestFrameworkUtil about type resolution - Sören Glimm (@UncleOwen)
- #6691: [java] Fix #1102: improve consistency of utility class detection across rules - Sören Glimm (@UncleOwen)
- #6705: [java] Fix #6681: UnitTestShouldIncludeAssert: False positive with JUnitSoftAssertions Rule (JUnit 4) - Lukas Gräf (@lukasgraef)
- #6707: [java] Fix #6704: rename rules and properties with JUnit5 in the name - Sören Glimm (@UncleOwen)
- #6708: [doc] Update minimal Java version for building PMD in documentation - Zbynek Konecny (@zbynek)
- #6712: [java] UnnecessaryBooleanAssertion: Use InvocationMatcher to find assertions - Zbynek Konecny (@zbynek)
- #6716: [java] Fix #6710: Case insensitive comparison in UseStandardCharsets - Sören Glimm (@UncleOwen)
- #6726: [java] Fix #6719: UseStandardCharsets UTF-32 on Java >= 22 - Sören Glimm (@UncleOwen)
📦️ Dependency updates
- #6612: chore(deps): bump io.github.apex-dev-tools:apex-parser from 4.4.1 to 5.0.0
- #6620: Bump PMD from 7.23.0 to 7.24.0
- #6621: [core] Fix #4972: Update ANTLR from 4.9.3 to 4.13.2
- #6631: chore(deps): bump ruby/setup-ruby from 1.305.0 to 1.306.0
- #6635: chore(deps): bump com.google.code.gson:gson from 2.13.2 to 2.14.0
- #6642: chore(deps): bump crate-ci/typos from 1.45.1 to 1.46.0
- #6643: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.4.0 to 13.4.2
- #6644: chore(deps): bump org.checkerframework:checker-qual from 4.0.0 to 4.1.0
- #6656: chore(deps): bump nokogiri from 1.19.2 to 1.19.3 in /.ci/files
- #6662: chore(deps): bump actions/create-github-app-token from 3.1.1 to 3.2.0
- #6663: chore(deps): bump scalameta.version from 4.16.1 to 4.17.0
- #6664: chore(deps): bump ruby/setup-ruby from 1.306.0 to 1.307.0
- #6666: chore(deps): bump crate-ci/typos from 1.46.0 to 1.46.1
- #6665: chore(deps-dev): bump log4j.version from 2.25.4 to 2.26.0
- #6667: chore(deps): bump org.apache.groovy:groovy from 5.0.5 to 5.0.6
- #6668: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.6 to 0.25.7
- #6697: chore(deps): bump ruby/setup-ruby from 1.307.0 to 1.308.0
- #6698: chore(deps): bump junit.version from 6.0.3 to 6.1.0
- #6699: chore(deps): bump crate-ci/typos from 1.46.1 to 1.46.2
- #6700: chore(deps): bump org.apache.maven.plugins:maven-enforcer-plugin from 3.6.2 to 3.6.3
- #6701: chore(deps): bump org.ow2.asm:asm from 9.9.1 to 9.10
- #6702: chore(deps): bump com.google.protobuf:protobuf-java from 4.34.1 to 4.35.0
- #6720: chore(deps): bump crate-ci/typos from 1.46.2 to 1.46.3
- #6721: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.7 to 0.26.0
- #6722: chore(deps): bump ruby/setup-ruby from 1.308.0 to 1.310.0
- #6723: chore(deps): bump org.ow2.asm:asm from 9.10 to 9.10.1
- #6724: chore(deps-dev): bump com.github.hazendaz.maven:coveralls-maven-plugin from 5.0.0 to 5.1.0
- #6725: chore(deps-dev): Update tmp from 0.2.5 to 0.2.6
- #6729: chore(deps-dev): bump build-tools from 37 to 38
📈️ Stats
- 308 commits
- 72 closed tickets & PRs
- Days since last release: 34
24-April-2026 - 7.24.0
The PMD team is pleased to announce PMD 7.24.0.
This is a minor release.
Table Of Contents
🌟️ New Rules
- The new Apex rule
AvoidInterfaceAsMapKeyreportsMapdeclarations (fields, variables, parameters) whose key type is an interface that has at least one abstract implementing class definingequalsorhashCode. Using such maps results in potentially duplicated map entries or not being able to get entries by key. - The new Java rule
OverridingThreadRunfinds overriddenThread::runmethods. This is not recommended. Instead, implementRunnableand pass an instance to the thread constructor.
🐛️ Fixed Issues
- apex
- #5386: [apex] Apex files ending in “Test” are skipped with a number of rules
- apex-errorprone
- #6492: [apex] New rule: Prevent use of interface -> abstract class with equals/hashCode as key in Map
- apex-security
- #5385: [apex] ApexCRUDViolation not reported even if SOQL doesn’t have permissions check on it
- java-bestpractices
- #4272: [java] JUnitTestsShouldIncludeAssert: False positive with assert in lambda
- java-multithreading
- #595: [java] New rule: Implement Runnable instead of extending Thread
- kotlin
- #6003: [kotlin] Support multidollar interpolation (Kotlin 2.2)
✨️ Merged pull requests
- #6493: [apex] New Rule: AvoidInterfaceAsMapKeyRule - Jonny Alexander Power (@JonnyPower)
- #6497: [kotlin] Fix kotlin grammar for parsing multidollar interpolation - Peter Paul Bakker (@stokpop)
- #6555: [java] New rule: OverridingThreadRun to prefer using Runnable - Zbynek Konecny (@zbynek)
- #6556: [java] Fix #4272: False positive in UnitTestShouldIncludeAssert when using assertion in lambda - Lukas Gräf (@lukasgraef)
- #6563: [apex] Remove class name suffix “Test” as indicator of test classes - David Schach (@dschach)
- #6576: [test] chore: Throw a TestAbortedException on disabled tests - UncleOwen (@UncleOwen)
- #6577: [dist] chore: Improve error message for missing JAVA_HOME in AntIT.java - UncleOwen (@UncleOwen)
- #6607: [doc] basic.xml has been gone for a long time - UncleOwen (@UncleOwen)
📦️ Dependency updates
- #6515: chore: bump pmd-regression-tester from 1.6.2 to 1.7.0
- #6552: Bump PMD from 7.22.0 to 7.23.0
- #6564: chore(deps): bump ruby/setup-ruby from 1.295.0 to 1.299.0
- #6565: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.7 to 1.18.8
- #6566: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.3.0 to 13.4.0
- #6567: chore(deps-dev): bump log4j.version from 2.25.3 to 2.25.4
- #6569: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.7 to 1.18.8
- #6570: chore(deps): bump org.apache.groovy:groovy from 5.0.4 to 5.0.5
- #6571: chore(deps-dev): bump io.github.git-commit-id:git-commit-id-maven-plugin from 9.0.2 to 9.1.0
- #6572: chore(deps): bump bigdecimal from 4.0.1 to 4.1.0 in /docs
- #6578: chore(deps): bump marocchino/sticky-pull-request-comment from 3.0.2 to 3.0.3
- #6579: chore(deps): bump crate-ci/typos from 1.44.0 to 1.45.0
- #6580: chore(deps): bump ruby/setup-ruby from 1.299.0 to 1.300.0
- #6581: chore(deps-dev): bump io.github.git-commit-id:git-commit-id-maven-plugin from 9.1.0 to 10.0.0
- #6582: chore(deps): bump org.checkerframework:checker-qual from 3.54.0 to 4.0.0
- #6583: chore(deps-dev): bump ant.version from 1.10.15 to 1.10.16
- #6584: chore(deps): bump bigdecimal from 4.1.0 to 4.1.1 in /docs
- #6588: chore(deps): bump actions/cache from 5.0.4 to 5.0.5
- #6589: chore(deps): bump marocchino/sticky-pull-request-comment from 3.0.3 to 3.0.4
- #6590: chore(deps): bump crate-ci/typos from 1.45.0 to 1.45.1
- #6591: chore(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1
- #6592: chore(deps): bump actions/create-github-app-token from 3.0.0 to 3.1.1
- #6593: chore(deps): bump scalameta.version from 4.15.2 to 4.16.0
- #6594: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.4 to 0.25.5
- #6595: chore(deps-dev): bump com.google.guava:guava from 33.5.0-jre to 33.6.0-jre
- #6596: chore(deps-dev): bump ant.version from 1.10.16 to 1.10.17
- #6599: chore(deps-dev): Bump lodash from 4.17.23 to 4.18.1
- #6600: chore(deps-dev): Bump addressable from 2.8.9 to 2.9.0
- #6613: chore(deps): bump ruby/setup-ruby from 1.300.0 to 1.305.0
- #6614: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.5 to 0.25.6
- #6615: chore(deps): bump scalameta.version from 4.16.0 to 4.16.1
- #6616: chore(deps-dev): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.5.0.6356 to 5.6.0.6792
- #6617: chore(deps): bump org.jsoup:jsoup from 1.22.1 to 1.22.2
- #6618: chore(deps): bump bigdecimal from 4.1.1 to 4.1.2 in /docs
📈️ Stats
- 82 commits
- 14 closed tickets & PRs
- Days since last release: 27
27-March-2026 - 7.23.0
The PMD team is pleased to announce PMD 7.23.0.
This is a minor release.
Table Of Contents
🐛️ Fixed Issues
- core
- #6503: [core] Links in HTML report are broken
- java-errorprone
- #6502: [java] CloseResource: False positive for allowedResourceMethodPatterns entries when using unqualified method calls
- java-security
- #6531: [java] InsecureCryptoIv: False negative with fixed IVs from array initializers
✨️ Merged pull requests
- #6467: [ci] Use typos gh-action - Andreas Dangel (@adangel)
- #6488: [doc] Update security.md for CVE-2026-28338 - Andreas Dangel (@adangel)
- #6489: [doc] CPD: document –report-file parameter - Andreas Dangel (@adangel)
- #6504: [core] Fix #6503: Don’t escape externalInfoUrl in reports - Andreas Dangel (@adangel)
- #6505: [java] Fix #6502: CloseResource should consider unqualified method calls - Andreas Dangel (@adangel)
- #6545: [java] Fix #6531: False negative in InsecureCryptoIv with array initializers - Zbynek Konecny (@zbynek)
📦️ Dependency updates
- #6476: Bump PMD from 7.21.0 to 7.22.0
- #6479: chore(deps): bump actions/download-artifact from 7.0.0 to 8.0.0
- #6480: chore(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0
- #6481: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.2.0 to 13.3.0
- #6482: chore(deps): bump org.mockito:mockito-core from 5.21.0 to 5.22.0
- #6483: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.5 to 1.18.7
- #6484: chore(deps): bump org.yaml:snakeyaml from 2.5 to 2.6
- #6485: chore(deps): bump org.checkerframework:checker-qual from 3.53.1 to 3.54.0
- #6486: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.5 to 1.18.7
- #6487: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.5 to 4.34.0
- #6490: chore: Update gems, remove github-pages
- #6498: chore(deps): bump ruby/setup-ruby from 1.288.0 to 1.290.0
- #6499: chore(deps-dev): bump commons-logging:commons-logging from 1.3.5 to 1.3.6
- #6500: chore(deps-dev): bump org.apache.maven.plugins:maven-shade-plugin from 3.6.1 to 3.6.2
- #6501: chore(deps): bump org.apache.maven.plugins:maven-resources-plugin from 3.4.0 to 3.5.0
- #6506: chore(deps): bump actions/create-github-app-token from 2.2.1 to 3.0.0
- #6507: chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1
- #6508: chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.4 to 3.0.2
- #6509: chore(deps): bump ruby/setup-ruby from 1.290.0 to 1.295.0
- #6511: chore(deps): bump org.mockito:mockito-core from 5.22.0 to 5.23.0
- #6514: chore: bump maven from 3.9.12 to 3.9.14
- #6516: chore: bump json from 2.19.0 to 2.19.2
- #6548: chore(deps): bump actions/cache from 5.0.3 to 5.0.4
- #6549: chore(deps): bump com.google.protobuf:protobuf-java from 4.34.0 to 4.34.1
- #6551: chore: use ruby4
📈️ Stats
- 38 commits
- 9 closed tickets & PRs
- Days since last release: 27
27-February-2026 - 7.22.0
The PMD team is pleased to announce PMD 7.22.0.
This is a minor release.
Table Of Contents
- 🚀️ New and noteworthy
- 🌟️ New and Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🚀️ New and noteworthy
Security fixes
- This release fixes a stored XSS vulnerability in VBHTMLRenderer and YAHTMLRenderer via unescaped violation messages.
Affects CI/CD pipelines that run PMD with--format vbhtmlor--format yahtmlon untrusted source code (e.g. pull requests from external contributors) and expose the HTML report as a build artifact. JavaScript executes in the browser context of anyone who opens the report.
Note: The defaulthtmlformat is not affected by unescaped violation messages, but a similar problem existed with suppressed violation markers.
If you use these reports, it is recommended to upgrade PMD.
Reported by Smaran Chand (@smaranchand).
🌟️ New and Changed Rules
New Rules
- The new Java rule
UnnecessaryInterfaceDeclarationdetects classes that implement interfaces that are already implemented by its superclass, and interfaces that extend other interfaces already declared by their superinterfaces.
These declarations are redundant and can be removed to simplify the code.
Changed Rules
- The rule
CloseResourceintroduces a new property,allowedResourceMethodPatterns, which lets you specify method invocation patterns whose return values are resources managed externally. This is useful for ignoring managed resources - for example,Reader/Writerinstances obtained fromHttpServletRequest/HttpServletResponse- because the servlet container, not application code, is responsible for closing them. By default, the rule ignoresInputStream/OutputStream/Reader/Writerresources returned by methods on(Http)ServletRequestand(Http)ServletResponse(bothjavax.servletandjakarta.servlet).
🐛️ Fixed Issues
- core
- doc
- #6396: [doc] Mention test-pmd-tool as alternative for testing
- java-bestpractices
- #6431: [java] UnitTestShouldIncludeAssert: False positive with SoftAssertionsExtension on parent/grandparent classes
- java-codestyle
- #6458: [java] New Rule: UnnecessaryInterfaceDeclaration
- java-errorprone
🚨️ API Changes
Deprecations
- core
CodeClimateIssue: This class is an implementation detail ofCodeClimateRenderer. It will be internalized in a future release.
- visualforce
DataType. The enum constants have been renamed to follow Java naming conventions. The old enum constants are deprecated and should no longer be used.
The methodDataType#fromStringwill return the new enum constants.
UseDataType#fieldTypeNameOfto get the original field type name.
✨️ Merged pull requests
- #6396: [doc] Mention test-pmd-tool as alternative for testing - Beech Horn (@metalshark)
- #6397: [java] Add support for Lombok-generated getters in symbol resolution - Anurag Agarwal (@altaiezior)
- #6420: [ci] build: Add typos as spell checker - Andreas Dangel (@adangel)
- #6432: [java] UnitTestShouldIncludeAssert: False positive with SoftAssertionsExtension on parent/grandparent classes - Artur Kalimullin (@kaliy)
- #6434: [java] chore(style): Fix lambda argument indentation for checkstyle compliance - Kai (@aclfe)
- #6437: [java] CloseResource: Allow to ignore managed resources - Gildas Cuisinier (@gcuisinier)
- #6445: chore: Fix FieldNamingConventions - Andreas Dangel (@adangel)
- #6446: [doc] Add new IntelliJ Plugin “PMD X” - Andreas Dangel (@adangel)
- #6447: chore: Small release process fixes - Andreas Dangel (@adangel)
- #6458: [java] New Rule: UnnecessaryInterfaceDeclaration - Zbynek Konecny (@zbynek)
- #6472: [core] Fix BaseAntlrTerminalNode getTokenKind to return type instead of index - Peter Paul Bakker (@stokpop)
- #6475: [core] Fix stored XSS in VBHTMLRenderer and YAHTMLRenderer - Andreas Dangel (@adangel)
📦️ Dependency updates
- #6433: Bump PMD from 7.20.0 to 7.21.0
- #6438: chore(deps): bump actions/cache from 5.0.2 to 5.0.3
- #6439: chore(deps): bump ruby/setup-ruby from 1.286.0 to 1.288.0
- #6440: chore(deps): bump scalameta.version from 4.14.6 to 4.14.7
- #6441: chore(deps): bump org.apache.maven.plugins:maven-compiler-plugin from 3.14.1 to 3.15.0
- #6442: chore(deps): bump org.checkerframework:checker-qual from 3.53.0 to 3.53.1
- #6443: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.0.0 to 13.1.0
- #6444: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.4 to 4.33.5
- #6452: chore(deps): bump actions/checkout from 6.0.1 to 6.0.2
- #6455: chore(deps): bump org.apache.maven.plugins:maven-dependency-plugin from 3.9.0 to 3.10.0
- #6456: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.1.0 to 13.2.0
- #6462: chore(deps): bump junit.version from 6.0.2 to 6.0.3
- #6463: chore(deps): bump scalameta.version from 4.14.7 to 4.15.2
- #6465: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.4 to 1.18.5
- #6468: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.4 to 1.18.5
- #6469: chore(deps): bump surefire.version from 3.5.4 to 3.5.5
- #6470: chore(deps): bump org.jetbrains:annotations from 26.0.2-1 to 26.1.0
- #6473: chore(deps): bump nokogiri to 1.19.1
- #6474: chore(deps): bump faraday from 2.13.3 to 2.14.1
📈️ Stats
- 66 commits
- 16 closed tickets & PRs
- Days since last release: 28
30-January-2026 - 7.21.0
The PMD team is pleased to announce PMD 7.21.0.
This is a minor release.
Table Of Contents
- 🚀️ New and noteworthy
- 🌟️ New and Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🚀️ New and noteworthy
🚀️ New: Java 26 Support
This release of PMD brings support for Java 26.
There are no new standard language features.
There is one preview language feature:
In order to analyze a project with PMD that uses these preview language features,
you’ll need to select the new language version 26-preview:
pmd check --use-version java-26-preview ...
Note: Support for Java 24 preview language features have been removed. The version “24-preview” is no longer available.
Build Requirement is Java 21
From now on, Java 21 or newer is required to build PMD. PMD itself still remains compatible with Java 8, so that it still can be used in a pure Java 8 environment. This allows us to use the latest checkstyle version during the build.
CPD
- The Apex module now supports suppression through
CPD-ON/CPD-OFFcomment pairs. See #6417
🌟️ New and Changed Rules
New Rules
- The new Java rule
PublicMemberInNonPublicTypedetects public members (such as methods or fields) within non-public types. Non-public types should not declare public members, as their effective visibility is limited, and using thepublicmodifier can create confusion. - The new Java rule
UnsupportedJdkApiUsageflags the use of unsupported and non-portable JDK APIs, includingsun.*packages,sun.misc.Unsafe, andjdk.internal.misc.Unsafe. These APIs are unstable, intended for internal use, and may change or be removed. The rule complements Java compiler warnings by highlighting such usage during code reviews and encouraging migration to official APIs like VarHandle and the Foreign Function & Memory API.
Changed Rules
The following rules have been changed to use a consistent implementation of enum based rule properties:
- The property
checkAddressTypesof ruleAvoidUsingHardCodedIPhas changed:- Instead of
IPv4useipv4 - Instead of
IPv6useipv6 - Instead of
IPv4 mapped IPv6useipv4MappedIpv6 - The old values still work, but you’ll see a deprecation warning.
- Instead of
- The property
nullCheckBranchof ruleConfusingTernaryhas changed:- Instead of
Anyuseany - Instead of
Thenusethen - Instead of
Elseuseelse - The old values still work, but you’ll see a deprecation warning.
- Instead of
- The property
typeAnnotationsof ruleModifierOrderhas changed:- Instead of
ontypeuseonType - Instead of
ondecluseonDecl - The old values still work, but you’ll see a deprecation warning.
- Instead of
- The values of the properties of rule
CommentRequiredhave changed:- Instead of
Requireduserequired - Instead of
Ignoreduseignored - Instead of
Unwanteduseunwanted - The old values still work, but you’ll see a deprecation warning.
- Instead of
Deprecated Rules
- The Java rule
DontImportSunhas been deprecated. It is replaced byUnsupportedJdkApiUsage.
🐛️ Fixed Issues
- core
- #6184: [core] Consistent implementation of enum properties
- apex
- #6417: [apex] Support CPD suppression with “CPD-OFF” & “CPD-ON”
- apex-codestyle
- #6349: [apex] FieldDeclarationsShouldBeAtStart: False positive with properties
- cli
- #6290: [cli] Improve Designer start script
- java
- java-design
- #6231: [java] New Rule: PublicMemberInNonPublicType
- java-errorprone
- java-performance
- #3857: [java] InsufficientStringBufferDeclaration: False negatives with String constants
🚨️ API Changes
Deprecations
- core
MetricOption#valueName: When metrics are used for (rule) properties, then the conventional enum mapping (from SCREAMING_SNAKE_CASE to camelCase) will be used for the enum values. SeeconventionalEnumListProperty.- In
PropertyFactory:enumProperty(String, Map). UseconventionalEnumPropertyinstead.enumProperty(String, Class). UseconventionalEnumPropertyinstead.enumProperty(String, Class, Function). UseconventionalEnumPropertyinstead.enumListProperty(String, Map). UseconventionalEnumListPropertyinstead.enumListProperty(String, Class, Function). UseconventionalEnumListPropertyinstead.
- java
AvoidBranchingStatementAsLastInLoopRule#CHECK_FOR. This constant should have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_DO. This constant should have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_WHILE. This constant should have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_BREAK_LOOP_TYPES. This property descriptor should have been private. It won’t be used anymore. UsegetPropertyDescriptoron the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#CHECK_CONTINUE_LOOP_TYPES. This property descriptor should have been private. It won’t be used anymore. UsegetPropertyDescriptoron the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#CHECK_RETURN_LOOP_TYPES. This property descriptor should have been private. It won’t be used anymore. UsegetPropertyDescriptoron the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#check. This method should have been private and will be internalized.AvoidBranchingStatementAsLastInLoopRule#hasPropertyValue. This method should have been private and will be internalized.AvoidBranchingStatementAsLastInLoopRule#checksNothing. This method should have been private and will be internalized.ClassFanOutOption#valueName,CycloOption#valueName,NcssOption#valueName
- lang-test
AbstractMetricTestRule#optionMappings. No extra mapping is required anymore. TheMetricOptionenum values are used. SeeAbstractMetricTestRule(Metric, Class)to provide the enum at construction time.
✨️ Merged pull requests
- #6231: [java] New Rule: PublicMemberInNonPublicType - Andreas Dangel (@adangel)
- #6232: [java] New Rule: UnsupportedJdkApiUsage - Thomas Leplus (@thomasleplus)
- #6233: [core] Fix #6184: More consistent enum properties - Andreas Dangel (@adangel)
- #6290: [cli] Improve Designer start script - Andreas Dangel (@adangel)
- #6315: [java] Fix #5882: UnconditionalIfStatement false-negative if true/false is not literal - Marcel (@mrclmh)
- #6362: chore: Fix typos - Zbynek Konecny (@zbynek)
- #6366: [java] Fix #3857: InsufficientStringBufferDeclaration should consider constant Strings - Lukas Gräf (@lukasgraef)
- #6373: [java] Support Java 26 - Andreas Dangel (@adangel)
- #6377: [doc] chore: update last_updated - Andreas Dangel (@adangel)
- #6384: chore: helper script check-all-contributors.sh - Andreas Dangel (@adangel)
- #6386: [core] chore: Bump minimum Java version required for building to 21 - Andreas Dangel (@adangel)
- #6387: [ci] publish-pull-requests: download latest build result - Andreas Dangel (@adangel)
- #6389: chore: update javadoc deprecated tags - Andreas Dangel (@adangel)
- #6390: chore: update javadoc experimental tags - Andreas Dangel (@adangel)
- #6391: chore: update javadoc internal API tags - Andreas Dangel (@adangel)
- #6392: [doc] ADR 3: Clarify javadoc tags - Andreas Dangel (@adangel)
- #6394: [apex] Fix #6349: FieldDeclarationsShouldBeAtStart false positive with properties - Mohamed Hamed (@mdhamed238)
- #6407: [java] Fix #3601: InvalidLogMessageFormat: False positive when final parameter is Supplier
- [Lukas Gräf](https://github.com/lukasgraef) (@lukasgraef) - #6417: [apex] Support CPD suppression with “CPD-OFF” & “CPD-ON” - Jade (@goto-dev-null)
- #6428: [ci] chore: run extensive integration tests under linux only - Andreas Dangel (@adangel)
- #6429: [doc] chore: add keywords for auxclasspath in Java documentation - Andreas Dangel (@adangel)
- #6430: [java] Fix #6364: Parse error with yield lambda - Andreas Dangel (@adangel)
📦️ Dependency updates
- #6367: Bump PMD from 7.19.0 to 7.20.0
- #6369: chore(deps): bump ruby/setup-ruby from 1.275.0 to 1.277.0
- #6370: chore(deps): bump org.apache.groovy:groovy from 5.0.2 to 5.0.3
- #6371: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.2 to 1.18.3
- #6372: chore(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.6.2 to 3.6.3
- #6375: chore: Bump maven from 3.9.11 to 3.9.12
- #6378: chore(deps): bump ruby/setup-ruby from 1.277.0 to 1.279.0
- #6379: chore(deps): bump scalameta.version from 4.14.2 to 4.14.4
- #6380: chore(deps): bump junit.version from 6.0.1 to 6.0.2
- #6381: chore(deps): bump org.jsoup:jsoup from 1.21.2 to 1.22.1
- #6382: chore(deps): bump org.checkerframework:checker-qual from 3.52.1 to 3.53.0
- #6383: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.3.0 to 13.0.0
- #6385: chore(deps): bump uri from 1.0.3 to 1.0.4 in /docs
- #6399: chore(deps): bump ruby/setup-ruby from 1.279.0 to 1.282.0
- #6400: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.1 to 0.25.4
- #6401: chore(deps): bump org.sonatype.central:central-publishing-maven-plugin from 0.9.0 to 0.10.0
- #6403: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.2 to 4.33.4
- #6410: chore(deps): bump ruby/setup-ruby from 1.282.0 to 1.285.0
- #6411: chore(deps): bump actions/cache from 5.0.1 to 5.0.2
- #6412: chore(deps): bump scalameta.version from 4.14.4 to 4.14.5
- #6413: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.3 to 1.18.4
- #6414: chore(deps-dev): bump org.codehaus.mojo:versions-maven-plugin from 2.20.1 to 2.21.0
- #6415: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.3 to 1.18.4
- #6419: chore(deps-dev): bump lodash from 4.17.21 to 4.17.23
- #6421: chore(deps): bump actions/setup-java from 5.1.0 to 5.2.0
- #6422: chore(deps): bump actions/checkout from 6.0.1 to 6.0.2
- #6423: chore(deps): bump scalameta.version from 4.14.5 to 4.14.6
- #6424: chore(deps-dev): bump org.assertj:assertj-core from 3.27.6 to 3.27.7
- #6425: chore(deps): bump org.apache.groovy:groovy from 5.0.3 to 5.0.4
📈️ Stats
- 146 commits
- 30 closed tickets & PRs
- Days since last release: 30
30-December-2025 - 7.20.0
The PMD team is pleased to announce PMD 7.20.0.
This is a minor release.
Table Of Contents
- 🌟️ Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🌟️ Changed Rules
- The Java rule
OnlyOneReturnhas a new propertyignoredMethodNames. This property by default is set tocompareToandequals, thus this rule now by default allows multiple return statements for these methods. To restore the old behavior, simply set this property to an empty value.
🐛️ Fixed Issues
- core
- #6330: [core] “Unable to create ValueRepresentation” when using @LiteralText (XPath)
- java
- java-bestpractices
- #4282: [java] GuardLogStatement: False positive when guard is not a direct parent
- #6028: [java] UnusedPrivateMethod: False positive with raw type for generic method
- #6257: [java] UnusedLocalVariable: False positive with instanceof pattern guard
- #6291: [java] EnumComparison: False positive for any object when object.equals(null)
- #6328: [java] UnusedLocalVariable: False positive for pattern variable in for-each without braces
- java-codestyle
- #4257: [java] OnlyOneReturn: False positive with equals method
- #5043: [java] LambdaCanBeMethodReference: False positive on overloaded methods
- #6237: [java] UnnecessaryCast: ContextedRuntimeException when parsing switch expression with lambdas
- #6279: [java] EmptyMethodInAbstractClassShouldBeAbstract: False positive for final empty methods
- #6284: [java] UnnecessaryConstructor: False positive for JavaDoc-bearing constructor
- java-errorprone
- java-performance
- maintenance
- #6230: [core] Single module snapshot build fails
🚨️ API Changes
Experimental API
✨️ Merged pull requests
- #6262: [java] UnusedLocalVariable: fix false positive with guard in switch - Zbynek Konecny (@zbynek)
- #6285: [java] Fix #5043: FP in LambdaCanBeMethodReference when method ref would be ambiguous - Clément Fournier (@oowekyala)
- #6287: [doc] Explain how to build or pull snapshot dependencies for single module builds - Marcel (@mrclmh)
- #6288: [java] Fix #6279: EmptyMethodInAbstractClassShouldBeAbstract should ignore final methods - Marcel (@mrclmh)
- #6292: [java] Fix #6291: EnumComparison FP when comparing with null - Clément Fournier (@oowekyala)
- #6293: [java] Fix #6276: NullAssignment should not report assigning null to a final field in a constructor - Lukas Gräf (@lukasgraef)
- #6294: [java] Fix #6028: UnusedPrivateMethod FP - Clément Fournier (@oowekyala)
- #6295: [java] Fix #6237: UnnecessaryCast error with switch expr returning lambdas - Clément Fournier (@oowekyala)
- #6296: [java] Fix #4282: GuardLogStatement only detects guard methods immediately around it - Marcel (@mrclmh)
- #6299: [java] Fix grammar of switch label - Clément Fournier (@oowekyala)
- #6309: [java] Fix #4257: Allow ignoring methods in OnlyOneReturn - Marcel (@mrclmh)
- #6311: [java] Fix #6284: UnnecessaryConstructor reporting false-positive on JavaDoc-bearing constructor - Marcel (@mrclmh)
- #6313: [java] Fix #4910: if-statement triggers ConsecutiveAppendsShouldReuse - Marcel (@mrclmh)
- #6316: [java] Fix #5877: AvoidArrayLoops false-negative when break inside switch statement - Marcel (@mrclmh)
- #6342: [core] Fix #6330: Cannot access Chars attribute from XPath - Clément Fournier (@oowekyala)
- #6344: [java] Fix #6328: UnusedLocalVariable should consider pattern variable in for-each without curly braces - Mohamed Hamed (@mdhamed238)
- #6348: [jsp] Fix malformed Javadoc HTML in JspDocStyleTest - Gianmarco (@gianmarcoschifone)
- #6359: [java] Fix #6234: Parser fails to parse switch expressions in super() constructor calls - Mohamed Hamed (@mdhamed238)
- #6360: [java] Fix #4158: BigIntegerInstantiation false-negative with compile-time constant - Lukas Gräf (@lukasgraef)
- #6361: [vf] Fix invalid Javadoc syntax in VfDocStyleTest - Gianmarco (@gianmarcoschifone)
- #6363: [apex] Add sca-extra ruleset for Salesforce Apex testing - Beech Horn (@metalshark)
📦️ Dependency updates
- #6286: Bump PMD from 7.18.0 to 7.19.0
- #6300: chore(deps): bump actions/checkout from 6.0.0 to 6.0.1
- #6301: chore(deps): bump org.checkerframework:checker-qual from 3.52.0 to 3.52.1
- #6302: chore(deps): bump org.apache.maven.plugins:maven-resources-plugin from 3.3.1 to 3.4.0
- #6303: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.1 to 1.18.2
- #6304: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.1.2 to 12.2.0
- #6305: chore(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.3.0.6276 to 5.4.0.6343
- #6306: chore(deps): bump webrick from 1.9.1 to 1.9.2 in /docs
- #6318: chore(deps): bump actions/create-github-app-token from 2.2.0 to 2.2.1
- #6319: chore(deps): bump actions/setup-java from 5.0.0 to 5.1.0
- #6320: chore(deps): bump ruby/setup-ruby from 1.268.0 to 1.269.0
- #6321: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.1 to 1.18.2
- #6323: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.1 to 4.33.2
- #6324: chore(deps): bump io.github.apex-dev-tools:apex-ls_2.13 from 6.0.1 to 6.0.2
- #6325: chore(deps): bump org.apache.maven.plugins:maven-assembly-plugin from 3.7.1 to 3.8.0
- #6329: chore(deps): bump org.mozilla:rhino from 1.7.15 to 1.7.15.1
- #6331: chore(deps): bump actions/upload-artifact from 5.0.0 to 6.0.0
- #6332: chore(deps): bump org.mockito:mockito-core from 5.20.0 to 5.21.0
- #6333: chore(deps): bump actions/download-artifact from 6.0.0 to 7.0.0
- #6334: chore(deps): bump ruby/setup-ruby from 1.269.0 to 1.270.0
- #6335: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.2.0 to 12.3.0
- #6336: chore(deps): bump actions/cache from 4.3.0 to 5.0.1
- #6337: chore(deps): bump bigdecimal from 3.3.1 to 4.0.0 in /docs
- #6339: chore(deps): bump org.apache.maven.plugins:maven-release-plugin from 3.2.0 to 3.3.1
- #6341: chore(deps): bump org.apache.maven.plugins:maven-source-plugin from 3.3.1 to 3.4.0
- #6347: chore(deps-dev): bump org.apache.logging.log4j:log4j-core from 2.25.2 to 2.25.3 in /pmd-java
- #6350: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.24.2 to 0.25.1
- #6352: chore(deps): bump ruby/setup-ruby from 1.270.0 to 1.275.0
- #6353: chore(deps): bump org.ow2.asm:asm from 9.9 to 9.9.1
- #6354: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.2 to 1.18.3
- #6356: chore(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.4.0.6343 to 5.5.0.6356
- #6357: chore(deps): bump org.apache.commons:commons-text from 1.14.0 to 1.15.0
- #6358: chore(deps): bump bigdecimal from 4.0.0 to 4.0.1 in /docs
📈️ Stats
- 102 commits
- 39 closed tickets & PRs
- Days since last release: 32
28-November-2025 - 7.19.0
The PMD team is pleased to announce PMD 7.19.0.
This is a minor release.
Table Of Contents
- 🚀️ New and noteworthy
- 🌟️ New and Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🚀️ New and noteworthy
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog (7.19.0) and PMD Designer Changelog (7.19.1).
🌟️ New and Changed Rules
New Rules
- The new Apex rule
AvoidFutureAnnotationfinds usages of the@Futureannotation. It is a legacy way to execute asynchronous Apex code. New code should implement theQueueableinterface instead. - The new Java rule
EnumComparisonfinds usages ofequals()on enum constants or values. Enums should be compared directly with==instead ofequals()which has some advantages (e.g. static type checking at compile time). - The new Apex rule
NcssCountreplaces the four rules “ExcessiveClassLength”, “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 rule has been added to the quickstart ruleset.
Note: The new metric is implemented more correct than in the old rules. E.g. it considers now also switch statements and correctly counts if-statements only once and ignores method calls that are part of an expression and not a statement on their own. This leads to different numbers. Keep in mind, that NCSS counts statements and not lines of code. Statements that are split on multiple lines are still counted as one. - The new PL/SQL rule
NcssCountreplaces the rules “ExcessiveMethodLength”, “ExcessiveObjectLength”, “ExcessivePackageBodyLength”, “ExcessivePackageSpecificationLength”, “ExcessiveTypeLength”, “NcssMethodCount” and “NcssObjectCount”. The new rule uses the metrics framework to achieve the same. It has two properties, to define the report level for method and object sizes separately.
Note: the new metric is implemented more correct than in the old rules, so that the actual numbers of the NCSS metric from the old rules might be different from the new rule “NcssCount”. Statements that are split on multiple lines are still counted as one.
Deprecated Rules
- The Apex rule
ExcessiveClassLengthhas been deprecated. UseNcssCountto find big classes or create a custom XPath based rule using//ApexFile[UserClass][@EndLine - @BeginLine > 1000]. - The Apex rules
NcssConstructorCount,NcssMethodCount, andNcssTypeCounthave been deprecated in favor or the new ruleNcssCount. - The PL/SQL rule
ExcessiveMethodLengthhas been deprecated. UseNcssCountinstead or create a custom XPath based rule using//(MethodDeclaration|ProgramUnit|TriggerTimingPointSection|TriggerUnit|TypeMethod)[@EndLine - @BeginLine > 100]. - The PL/SQL rule
ExcessiveObjectLengthhas been deprecated. UseNcssCountinstead or create a custom XPath based rule using//(PackageBody|PackageSpecification|ProgramUnit|TriggerUnit|TypeSpecification)[@EndLine - @BeginLine > 1000]. - The PL/SQL rule
ExcessivePackageBodyLengthhas been deprecated. UseNcssCountinstead or create a custom XPath based rule using//PackageBody[@EndLine - @BeginLine > 1000]. - The PL/SQL rule
ExcessivePackageSpecificationLengthhas been deprecated. UseNcssCountinstead or create a custom XPath based rule using//PackageSpecification[@EndLine - @BeginLine > 1000]. - The PL/SQL rule
ExcessiveTypeLengthhas been deprecated. UseNcssCountinstead or create a custom XPath based rule using//TypeSpecification[@EndLine - @BeginLine > 1000]. - The PL/SQL rules
NcssMethodCountandNcssObjectCounthave been deprecated in favor of the new ruleNcssCount.
🐛️ Fixed Issues
- core
- #4767: [core] Deprecate old symboltable API
- apex-bestpractices
- #6203: [apex] New Rule: Avoid Future Annotation
- apex-design
- #2128: [apex] Merge NCSS count rules for Apex
- java
- java-bestpractices
- java-codestyle
- #6053: [java] ModifierOrder false-positives with type annotations and type parameters (typeAnnotations = anywhere)
- java-errorprone
- #4742: [java] EmptyFinalizer should not trigger if finalize method is final and class is not
- #6072: [java] OverrideBothEqualsAndHashCodeOnComparable should not be required for record classes
- #6092: [java] AssignmentInOperand false positive in 7.17.0 for case blocks in switch statements
- #6096: [java] OverrideBothEqualsAndHashCodeOnComparable on class with lombok.EqualsAndHashCode annotation
- #6199: [java] AssignmentInOperand: description of property allowIncrementDecrement is unclear
- #6273: [java] TestClassWithoutTestCases documentation does not mention test prefixes
- java-performance
- plsql-design
- #4326: [plsql] Merge NCSS count rules for PL/SQL
- maintenance
- #5701: [core] net.sourceforge.pmd.cpd.SourceManager has public methods
🚨️ API Changes
Deprecations
- core
net.sourceforge.pmd.lang.symboltable: All classes in this package are deprecated. The symbol table and type resolution implementation for Java has been rewritten from scratch for PMD 7.0.0. This package is the remains of the old symbol table API, that is only used by PL/SQL. For PMD 8.0.0 all these classes will be removed from pmd-core.
- apex
ExcessiveClassLengthRuleNcssConstructorCountRuleNcssMethodCountRuleNcssTypeCountRuleASTStatement: This AST node is not used and doesn’t appear in the tree.ApexVisitor#visit(ASTStatement, P)
- plsql
✨️ Merged pull requests
- #6081: [java] Fix #6072: OverrideBothEqualsAndHashCodeOnComparable should not be required for record classes - UncleOwen (@UncleOwen)
- #6192: [java] Fix #6053: ModifierOrder - consider type params - Andreas Dangel (@adangel)
- #6194: chore: always place type annotations on the type - Andreas Dangel (@adangel)
- #6195: chore: always compare enums with == - Andreas Dangel (@adangel)
- #6196: [java] New Rule: EnumComparison - Andreas Dangel (@adangel)
- #6198: [apex] New rule NcssCount to replace old Ncss*Count rules - Andreas Dangel (@adangel)
- #6201: [java] Fix #6199: AssignmentInOperandRule: Update description of allowIncrementDecrement property - Lukas Gräf (@lukasgraef)
- #6202: [java] Fix #6188: UnitTestsShouldIncludeAssert - FP when TestNG @Test.expectedException is present - Lukas Gräf (@lukasgraef)
- #6204: [apex] Add rule to limit usage of @Future annotation - Mitch Spano (@mitchspano)
- #6214: [plsql] New rule NcssCount to replace old Ncss*Count rules - Andreas Dangel (@adangel)
- #6217: [doc] Add Blue Cave to known tools using PMD - Jude Pereira (@judepereira)
- #6227: [java] UseArraysAsList: check increment - Andreas Dangel (@adangel)
- #6228: [java] UseArraysAsList: skip when if-statements - Andreas Dangel (@adangel)
- #6229: chore: remove public methods from SourceManager - Andreas Dangel (@adangel)
- #6238: [java] Fix #6096: Detect Lombok generated equals/hashCode in Comparable - Marcel (@mrclmh)
- #6249: [core] Deprecate old symboltable API - Andreas Dangel (@adangel)
- #6250: chore: fail build for compiler warnings - Andreas Dangel (@adangel)
- #6251: [java] Fix #6092: AssignmentInOperand false positive in 7.17.0 for case statements - Marcel (@mrclmh)
- #6255: [java] Fix #4742: EmptyFinalizer should not trigger if finalize method is final and class is not - Marcel (@mrclmh)
- #6258: [java] Fix #5820: GuardLogStatement recognizes that a string is a compile-time constant expression only if at first position - Marcel (@mrclmh)
- #6259: [java] Fix #5689: Issue with scoping of record members - Clément Fournier (@oowekyala)
- #6277: [doc] Add button to copy configuration snippet - Zbynek Konecny (@zbynek)
- #6278: [doc] TestClassWithoutTestCases: Mention test prefixes - Marcel (@mrclmh)
- #6280: [ci] Exclude build resources from spring-framework for regression tester - Clément Fournier (@oowekyala)
- #6282: [java] Fix #6256: ignore invalid annotation type - Andreas Dangel (@adangel)
📦️ Dependency updates
- #6197: Bump PMD from 7.17.0 to 7.18.0
- #6205: chore(deps): bump junit.version from 6.0.0 to 6.0.1
- #6206: chore(deps): bump org.checkerframework:checker-qual from 3.51.1 to 3.52.0
- #6207: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.17.7 to 1.17.8
- #6208: chore(deps): bump com.google.protobuf:protobuf-java from 4.32.1 to 4.33.0
- #6209: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.0.1 to 12.1.1
- #6210: chore(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.13 to 0.8.14
- #6219: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.17.8 to 1.18.0
- #6220: chore(deps): bump org.apache.maven.plugins:maven-release-plugin from 3.1.1 to 3.2.0
- #6221: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.17.8 to 1.18.0
- #6222: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.1.1 to 12.1.2
- #6223: chore(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.2.0.4988 to 5.3.0.6276
- #6240: chore(deps): bump ruby/setup-ruby from 1.267.0 to 1.268.0
- #6241: chore(deps): bump actions/checkout from 5.0.0 to 5.0.1
- #6242: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.0 to 1.18.1
- #6243: chore(deps): bump org.scala-lang:scala-library from 2.13.17 to 2.13.18
- #6244: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.0 to 1.18.1
- #6245: chore(deps): bump org.apache.maven.plugins:maven-jar-plugin from 3.4.2 to 3.5.0
- #6246: chore(deps): bump org.scala-lang:scala-reflect from 2.13.17 to 2.13.18
- #6247: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.0 to 4.33.1
- #6263: chore(deps): bump actions/checkout from 5.0.1 to 6.0.0
- #6264: chore(deps): bump org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0
- #6265: chore(deps): bump actions/create-github-app-token from 2.1.4 to 2.2.0
- #6266: chore(deps): bump scalameta.version from 4.14.1 to 4.14.2
- #6267: chore(deps): bump org.codehaus.mojo:versions-maven-plugin from 2.19.1 to 2.20.1
- #6281: Bump build-tools from 35 to 36
- #6283: Bump PMD Designer from 7.10.0 to 7.19.1
📈️ Stats
- 122 commits
- 44 closed tickets & PRs
- Days since last release: 28
31-October-2025 - 7.18.0
The PMD team is pleased to announce PMD 7.18.0.
This is a minor release.
Table Of Contents
- 🚀️ New and noteworthy
- 🌟️ New and Changed Rules
- 🐛️ Fixed Issues
- 🚨️ API Changes
- ✨️ Merged pull requests
- 📦️ Dependency updates
- 📈️ Stats
🚀️ New and noteworthy
Build Requirement is Java 17
From now on, Java 17 or newer is required to build PMD. PMD itself still remains compatible with Java 8, so that it still can be used in a pure Java 8 environment. This allows us to use the latest checkstyle version during the build.
🌟️ New and Changed Rules
New Rules
- The new Java rule
IdenticalConditionalBranchesfinds conditional statements that do the same thing when the condition is true and false. This is either incorrect or redundant. - The new Java rule
LabeledStatementfinds labeled statements in code. Labels make control flow difficult to understand and should be avoided. By default, the rule allows labeled loops (do, while, for). But it has a property to flag also those labeled loops. - The new Java rule
UnusedLabelfinds unused labels which are unnecessary and only make the code hard to read. This new rule will be part of the quickstart ruleset.
Changed Rules
ConfusingTernaryhas a new propertynullCheckBranchto control, whether null-checks should be allowed (the default case) or should lead to a violation.AvoidCatchingGenericExceptionis now configurable with the new propertytypesThatShouldNotBeCaught.
⚠️ The rule has also been moved from category “Design” to category “Error Prone”. If you are currently bulk-adding all the rules from the “Design” category into your custom ruleset, then you need to add the rule explicitly again (otherwise it won’t be included anymore):<rule ref="category/java/errorprone.xml/AvoidCatchingGenericException" />
Deprecated Rules
- The Java rule
AvoidCatchingNPEhas been deprecated in favor of the updated ruleAvoidCatchingGenericException, which is now configurable. - The Java rule
AvoidCatchingThrowablehas been deprecated in favor of the updated ruleAvoidCatchingGenericException, which is now configurable.
🐛️ Fixed Issues
- general
- #4714: [core] Allow trailing commas in multivalued properties
- #5873: [ci] Run integration test with Java 25
- #6012: [pmd-rulesets] Rulesets should be in alphabetical order
- #6073: [doc] Search improvements
- #6097: [doc] Add PMD versions dropdown
- #6098: [doc] Add a copy URL button
- #6101: [doc] Highlight current header in TOC
- #6149: [doc] Reproducible Build Documentation is outdated - PMD is now built using Java 17
- #6150: [core] Reduce memory usage of CPD’s MatchCollector
- apex
- #5935: [apex] @SuppressWarnings - allow whitespace around comma when suppressing multiple rules
- apex-design
- #6022: [apex] ExcessiveClassLength/ExcessiveParameterList include the metric in the message
- apex-documentation
- #6189: [apex] ApexDoc rule doesn’t match published Salesforce ApexDoc specification
- java
- java-bestpractices
- #2928: [java] New rules about labeled statements
- #4122: [java] CheckResultSet false-positive with local variable
- #6124: [java] UnusedLocalVariable: fix false negatives in pattern matching
- #6169: [java] AvoidUsingHardCodedIP: violation message should mention the hard coded address
- #6171: [java] AvoidUsingHardCodedIP: fix false positive for IPv6
- java-codestyle
- #5919: [java] ClassNamingConventions: Include integration tests in testClassPattern by default
- #6004: [java] Make ConfusingTernary != null configurable
- #6029: [java] Fix UnnecessaryCast false-negative in method calls
- #6057: [java] ModifierOrder false positive on “abstract sealed class”
- #6079: [java] IdenticalCatchBranches: False negative for overriden method calls
- #6123: [java] UselessParentheses FP around switch expression
- #6131: [java] ModifierOrder: wrong enum values documented, indirectly causing xml parse errors
- java-design
- java-documentation
- java-errorprone
- #5042: [java] CloseResource false-positive on Pattern Matching with instanceof
- #5878: [java] DontUseFloatTypeForLoopIndices false-negative if variable is declared before loop
- #6038: [java] Merge AvoidCatchingNPE and AvoidCatchingThrowable into AvoidCatchingGenericException
- #6055: [java] UselessPureMethodCall false positive with AtomicInteger::getAndIncrement
- #6060: [java] UselessPureMethodCall false positive on ZipInputStream::getNextEntry
- #6075: [java] AssignmentInOperand false positive with lambda expressions
- #6083: [java] New rule IdenticalConditionalBranches
- java-multithreading
- #5880: [java] DoubleCheckedLocking is not detected if more than 1 assignment or more than 2 if statements
- java-performance
- #6172: [java] InefficientEmptyStringCheck should include String#strip
- java-security
- #6191: [java] HardCodedCryptoKey: NPE when constants from parent class are used
- plsql-design
- #6077: [plsql] Excessive*/Ncss*Count/NPathComplexity include the metric
🚨️ API Changes
Deprecations
- java
- The following methods have been deprecated. Due to refactoring of the internal base class, these methods are not used anymore and are not required to be implemented anymore:
✨️ Merged pull requests
- #6021: [java] Fix #5569: ExcessiveImports/ExcessiveParameterList/ExcessivePublicCount include the metric in the message - UncleOwen (@UncleOwen)
- #6022: [apex] ExcessiveClassLength/ExcessiveParameterList include the metric in the message - UncleOwen (@UncleOwen)
- #6023: [test] Fix #6012: Alphabetically sort all default rules - Zbynek Konecny (@zbynek)
- #6024: [java] Fix #5878: DontUseFloatTypeForLoopIndices now checks the UpdateStatement as well - UncleOwen (@UncleOwen)
- #6029: [java] Fix UnnecessaryCast false-negative in method calls - Zbynek Konecny (@zbynek)
- #6031: [java] Fix #5880: False Negatives in DoubleCheckedLocking - Lukas Gräf (@lukasgraef)
- #6039: [core] Fix #4714: trim token before feeding it to the extractor - UncleOwen (@UncleOwen)
- #6040: [java,apex,plsql,velocity] Change description of “minimum” parameter - UncleOwen (@UncleOwen)
- #6042: [java] Fix #2928: New Rules UnusedLabel and LabeledStatement - UncleOwen (@UncleOwen)
- #6043: [java] Reactivate deactivated test in LocalVariableCouldBeFinal - UncleOwen (@UncleOwen)
- #6051: [java] Fix #6038: Make AvoidCatchingGenericException configurable - UncleOwen (@UncleOwen)
- #6056: chore: fix dogfood issues from new rules - Andreas Dangel (@adangel)
- #6059: [java] Fix #6058: DanglingJavadoc FP in module-info files - Lukas Gräf (@lukasgraef)
- #6061: [core] chore: Bump minimum Java version required for building to 17 - Andreas Dangel (@adangel)
- #6071: [java] Fix #5919: Add integration tests to ClassNamingConventions testClassRegex - Anton Bobov (@abobov)
- #6073: [doc] Search improvements - Andreas Dangel (@adangel)
- #6074: [apex] Fix @SuppressWarnings with whitespace around comma - Juan Martín Sotuyo Dodero (@jsotuyod)
- #6077: [plsql] Excessive/NcssCount/NPathComplexity include the metric - Andreas Dangel (@adangel)
- #6078: [java] Fix #6075: Fix FP in AssignmentInOperandRule - UncleOwen (@UncleOwen)
- #6080: [java] Fix #6079: IdenticalCatchBranches for overriden method calls - Zbynek Konecny (@zbynek)
- #6082: [java] Fix false positives in UselessPureMethodCall for streams and atomics - Zbynek Konecny (@zbynek)
- #6083: [java] New rule IdenticalConditionalBranches - Zbynek Konecny (@zbynek)
- #6085: [java] Fix false positive for ModifierOrder - Zbynek Konecny (@zbynek)
- #6093: [ci] Fix #5873: Run integration tests with Java 25 additionally - Andreas Dangel (@adangel)
- #6097: [doc] Add PMD versions dropdown - Andreas Dangel (@adangel)
- #6098: [doc] Add a copy URL button - Andreas Dangel (@adangel)
- #6100: [java] AvoidDeeplyNestedIfStmts: fix false negative with if-else - Zbynek Konecny (@zbynek)
- #6101: [doc] Highlight current header in TOC - Andreas Dangel (@adangel)
- #6112: [java] DanglingJavadoc: fix false positive for compact constructors - Zbynek Konecny (@zbynek)
- #6114: [java] Fix #4122: CheckResultSet false-positive with local variable - Lukas Gräf (@lukasgraef)
- #6116: [java] ConfusingTernary: add configuration property for null checks - Zbynek Konecny (@zbynek)
- #6124: [java] UnusedLocalVariable: fix false negatives in pattern matching - Zbynek Konecny (@zbynek)
- #6128: [java] Fix #4904: Correct class name in violation decorator - Andreas Dangel (@adangel)
- #6129: [java] Fix #6127: Correct var name in violation decorator - Andreas Dangel (@adangel)
- #6130: [java] UselessParentheses: fix false positives for switch expressions - Zbynek Konecny (@zbynek)
- #6132: [java] Implement main method launch protocol priorities - Zbynek Konecny (@zbynek)
- #6133: [java] Fix #5042: CloseResource: fix false positive with pattern matching - Zbynek Konecny (@zbynek)
- #6150: [core] Reduce memory usage of CPD’s MatchCollector - Lukas Gräf (@lukasgraef)
- #6152: chore(deps): Update Saxon-HE from 12.5 to 12.9 - Zbynek Konecny (@zbynek)
- #6156: [java] Fix #6146: ClassCastException in TypeTestUtil - Clément Fournier (@oowekyala)
- #6164: [doc] Update reproducible build info with Java 17 - Andreas Dangel (@adangel)
- #6166: [doc] Use emoji variants - Andreas Dangel (@adangel)
- #6170: [java] Fix #6169: AvoidUsingHardCodedIP - mention address in message - Andreas Dangel (@adangel)
- #6171: [java] AvoidUsingHardCodedIP: fix false positive for IPv6 - Andreas Dangel (@adangel)
- #6172: [java] InefficientEmptyStringCheck should include String#strip - Zbynek Konecny (@zbynek)
- #6185: [java] Fix #6131: Correct enum values for ModifierOrder - Andreas Dangel (@adangel)
- #6190: [apex] Update ApexDoc rule to match the published specification - Mitch Spano (@mitchspano)
- #6191: [java] HardCodedCryptoKey: NPE when constants from parent class are used - Zbynek Konecny (@zbynek)
📦️ Dependency updates
- #6034: chore(deps): bump com.puppycrawl.tools:checkstyle from 10.26.1 to 11.0.1
- #6054: Bump PMD from 7.16.0 to 7.17.0
- #6062: chore(deps): bump surefire.version from 3.5.3 to 3.5.4
- #6063: chore(deps): bump ruby/setup-ruby from 1.257.0 to 1.258.0
- #6064: chore(deps): bump com.google.code.gson:gson from 2.13.1 to 2.13.2
- #6065: chore(deps): bump actions/create-github-app-token from 2.1.1 to 2.1.4
- #6066: chore(deps): bump org.apache.groovy:groovy from 5.0.0 to 5.0.1
- #6067: chore(deps): bump org.apache.maven.plugins:maven-shade-plugin from 3.6.0 to 3.6.1
- #6068: chore(deps): bump scalameta.version from 4.13.9 to 4.13.10
- #6076: Bump pmdtester from 1.6.0 to 1.6.1
- #6086: chore(deps): bump ruby/setup-ruby from 1.258.0 to 1.263.0
- #6087: chore(deps-dev): bump log4j.version from 2.25.1 to 2.25.2
- #6088: chore(deps): bump org.mockito:mockito-core from 5.19.0 to 5.20.0
- #6089: chore(deps): bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.3 to 3.12.0
- #6090: chore(deps): bump org.codehaus.mojo:versions-maven-plugin from 2.19.0 to 2.19.1
- #6091: chore(deps): bump org.apache.maven.plugins:maven-compiler-plugin from 3.14.0 to 3.14.1
- #6094: chore(deps): Bump rexml from 3.4.1 to 3.4.4
- #6104: chore(deps): bump actions/cache from 4.2.4 to 4.3.0
- #6105: chore(deps): bump org.scala-lang:scala-library from 2.13.16 to 2.13.17
- #6106: chore(deps): bump junit.version from 5.13.4 to 6.0.0
- #6107: chore(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.5.1 to 3.6.0
- #6108: chore(deps): bump com.puppycrawl.tools:checkstyle from 10.26.1 to 11.1.0
- #6109: chore(deps-dev): bump org.assertj:assertj-core from 3.27.4 to 3.27.6
- #6110: chore(deps): bump org.sonatype.central:central-publishing-maven-plugin from 0.8.0 to 0.9.0
- #6118: chore(deps): bump com.google.protobuf:protobuf-java from 4.32.0 to 4.32.1
- #6119: chore(deps): bump com.github.hazendaz.maven:coveralls-maven-plugin from 4.7.0 to 5.0.0
- #6120: chore(deps): bump org.scala-lang:scala-reflect from 2.13.16 to 2.13.17
- #6121: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.23.1 to 0.24.1
- #6122: chore(deps): bump bigdecimal from 3.2.3 to 3.3.0 in /docs
- #6136: chore(deps): bump ruby/setup-ruby from 1.263.0 to 1.265.0
- #6137: chore(deps): bump org.apache.maven.plugins:maven-enforcer-plugin from 3.6.1 to 3.6.2
- #6138: chore(deps): bump scalameta.version from 4.13.10 to 4.14.0
- #6139: chore(deps): bump com.puppycrawl.tools:checkstyle from 11.1.0 to 12.0.1
- #6140: chore(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.6.0 to 3.6.1
- #6141: chore(deps): bump org.ow2.asm:asm from 9.8 to 9.9
- #6142: chore(deps): bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0
- #6143: chore(deps): bump bigdecimal from 3.3.0 to 3.3.1 in /docs
- #6152: chore(deps): Update Saxon-HE from 12.5 to 12.9
- #6157: chore(deps-dev): bump com.google.guava:guava from 33.4.8-jre to 33.5.0-jre
- #6158: chore(deps): bump scalameta.version from 4.14.0 to 4.14.1
- #6159: chore(deps): bump org.apache.maven.plugins:maven-dependency-plugin from 3.8.1 to 3.9.0
- #6160: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.24.1 to 0.24.2
- #6161: chore(deps): bump org.apache.maven.plugins:maven-pmd-plugin from 3.27.0 to 3.28.0
- #6162: chore(deps): bump org.apache.maven.plugins:maven-antrun-plugin from 3.1.0 to 3.2.0
- #6165: Bump pmdtester from 1.6.1 to 1.6.2
- #6173: chore(deps): bump actions/upload-artifact from 4.6.2 to 5.0.0
- #6174: chore(deps): bump ruby/setup-ruby from 1.265.0 to 1.267.0
- #6175: chore(deps): bump actions/download-artifact from 5.0.0 to 6.0.0
- #6178: chore(deps): bump org.checkerframework:checker-qual from 3.49.5 to 3.51.1
- #6179: chore(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.6.1 to 3.6.2
- #6180: chore(deps): bump io.github.apex-dev-tools:apex-ls_2.13 from 5.10.0 to 6.0.1
- #6181: chore(deps): bump org.apache.groovy:groovy from 5.0.1 to 5.0.2
- #6182: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.17.7 to 1.17.8
📈️ Stats
- 233 commits
- 76 closed tickets & PRs
- Days since last release: 49
12-September-2025 - 7.17.0
The PMD team is pleased to announce PMD 7.17.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
✨ New Rules
This release brings several new rules for both Java and Apex. Please try them out and submit feedback on our issue tracker!
- The new apex rule
AnnotationsNamingConventionsenforces that annotations are used consistently in PascalCase.
The rule is referenced in the quickstart.xml ruleset for Apex. - The new java rule
TypeParameterNamingConventionsreplaces the now deprecated rule GenericsNaming. The new rule is configurable and checks for naming conventions of type parameters in generic types and methods. It can be configured via a regular expression.
By default, this rule uses the standard Java naming convention (single uppercase letter).
The rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
OverrideBothEqualsAndHashCodeOnComparablefinds missinghashCode()and/orequals()methods on types that implementComparable. This is important if instances of these classes are used in collections. Failing to do so can lead to unexpected behavior in sets which then do not conform to theSetinterface. While theSetinterface relies onequals()to determine object equality, sorted sets likeTreeSetusecompareTo()instead. The same issue can arise when such objects are used as keys in sorted maps.
This rule is very similar toOverrideBothEqualsAndHashcodewhich has always been skippingComparableand only reports if one of the two methods is missing. The new rule will also report, if both methods (hashCode and equals) are missing.
The rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
UselessPureMethodCallfinds method calls of pure methods whose result is not used. Ignoring the result of such method calls is likely as mistake as pure methods are side effect free.
The rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
RelianceOnDefaultCharsetfinds method calls that depend on the JVM’s default charset. Using these method without specifying the charset explicitly can lead to unexpected behavior on different platforms. - Thew new java rule
VariableCanBeInlinedfinds local variables that are immediately returned or thrown. This rule replaces the old ruleUnnecessaryLocalBeforeReturnwhich only considered return statements. The new rule also finds unnecessary local variables before throw statements.
The rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
CollectionTypeMismatchdetects calls to collection methods where we suspect the types are incompatible. This happens for instance when you try to remove aStringfrom aCollection<Integer>: although it is allowed to write this becauseremovetakes anObjectparameter, it is most likely a mistake.
This rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
DanglingJavadocfinds Javadoc comments that do not belong to a class, method or field. These comments are ignored by the Javadoc tool and should either be corrected or removed.
The rule is referenced in the quickstart.xml ruleset for Java. - The new java rule
ModifierOrder(codestyle) finds incorrectly ordered modifiers (e.g.,static publicinstead ofpublic static). It ensures modifiers appear in the correct order as recommended by the Java Language Specification.
Deprecated Rules
- The java rule
GenericsNaminghas been deprecated for removal in favor of the new ruleTypeParameterNamingConventions. - The java rule
AvoidLosingExceptionInformationhas been deprecated for removal in favor of the new ruleUselessPureMethodCall. - The java rule
UselessOperationOnImmutablehas been deprecated for removal in favor of the new ruleUselessPureMethodCall. - The java rule
UnnecessaryLocalBeforeReturnhas been deprecated for removal in favor of the new ruleVariableCanBeInlined.
CPD: New Markdown Report Format
This PMD version ships with a simple Markdown based output format for CPD. It outputs all duplications
one after another including the code snippets as code blocks.
See Report formats for CPD.
🐛 Fixed Issues
- apex-codestyle
- #5650: [apex] New Rule: AnnotationsNamingConventions
- core
- java
- java-bestpractices
- #2186: [java] New Rule: RelianceOnDefaultCharset
- #4500: [java] AvoidReassigningLoopVariables - false negatives within for-loops and skip allowed
- #4770: [java] UnusedFormalParameter should ignore public constructor as same as method
- #5198: [java] CheckResultSet false-positive with local variable checked in a while loop
- java-codestyle
- #972: [java] Improve naming conventions rules
- #4916: [java] UseExplicitTypes: cases where ‘var’ should be unobjectionable
- #5601: [java] New Rule: ModifierOrder
- #5770: [java] New Rule: VariableCanBeInlined: Local variables should not be declared and then immediately returned or thrown
- #5922: [java] New Rule: TypeParameterNamingConventions
- #5948: [java] UnnecessaryBoxing false positive when calling
List.remove(int) - #5982: [java] More detailed message for the UselessParentheses rule
- java-design
- java-documentation
- #5916: [java] New Rule: DanglingJavadoc
- java-errorprone
- #3401: [java] Improve AvoidUsingOctalValues documentation
- #3434: [java] False negatives in AssignmentInOperand Rule
- #5837: [java] New Rule: OverrideBothEqualsAndHashCodeOnComparable
- #5881: [java] AvoidLosingExceptionInformation does not trigger when inside if-else
- #5907: [java] New Rule: UselessPureMethodCall
- #5915: [java] AssignmentInOperand not raised when inside do-while loop
- #5949: [java] New Rule: CollectionTypeMismatch: for Collections methods that take Object as a parameter
- #5974: [java] CloseResourceRule: NullPointerException while analyzing
- test
- #5973: [test] Enable XML validation for rule tests
🚨 API Changes
Deprecations
- pmd-java:
JClassSymbol#annotationAppliesTo: UseJClassSymbol#annotationAppliesToContextinstead.Experimental API
- pmd-core:
RuleContext#addViolationWithPosition
PMD Report Format CSV
The CSV report format for PMD as three new columns:
- End Line
- Begin Column
- End Column
These columns are not enabled by default, but can be activated via their respective renderer properties. See Report formats for PMD.
Rule Test Schema
When executing rule tests, the rule test XML file will be validated against the schema and the tests will fail if the XML file is invalid.
There was a small bug in the schema around verifying suppressed violations: If a test wanted to verify, that there
are no suppressed violations, then this was not possible. Now the <expected-suppression> element may be
empty. This is available in version 1.1.1 of the schema.
See Testing your rules for more information.
Deprecations
- test
- The method
AbstractRuleSetFactoryTest#hasCorrectEncodingwill be removed. PMD has the ruleMissingEncodingfor XML files that should be used instead.
- The method
✨ Merged pull requests
- #5601: [java] New Rule: ModifierOrder - Clément Fournier (@oowekyala)
- #5822: [apex] Fix #5650: New Rule: AnnotationsNamingConventions - Mitch Spano (@mitchspano)
- #5847: [java] Fix #5770: New Rule: VariableCanBeInlined - Vincent Potucek (@Pankraz76)
- #5856: [java] Fix #5837: New Rule: OverrideBothEqualsAndHashCodeOnComparable - Vincent Potucek (@Pankraz76)
- #5907: [java] New Rule: UselessPureMethodCall - Zbynek Konecny (@zbynek)
- #5916: [java] New Rule: DanglingJavadoc - Zbynek Konecny (@zbynek)
- #5922: [java] Fix #972: Add a new rule TypeParameterNamingConventions - UncleOwen (@UncleOwen)
- #5924: [java] Fix #5915: Fix AssignmentInOperandRule to also work an do-while loops and switch statements - UncleOwen (@UncleOwen)
- #5930: [java] Fix #4500: Fix AvoidReassigningLoopVariablesRule to allow only simple assignments in the forReassign=skip case - UncleOwen (@UncleOwen)
- #5931: [java] Fix #5023: Fix UseUtilityClassRule to use the message provided in design.xml - UncleOwen (@UncleOwen)
- #5932: [ci] Reuse GitHub Pre-Releases - Andreas Dangel (@adangel)
- #5933: [test] Fix QuickstartRulesetTests to detect deprecated rules again - Andreas Dangel (@adangel)
- #5934: [java] Fix #2186: New Rule: RelianceOnDefaultCharset - UncleOwen (@UncleOwen)
- #5938: [doc] Update suppression docs to reflect PMD 7 changes - Zbynek Konecny (@zbynek)
- #5939: [java] Fix #5198: CheckResultSet FP when local variable is checked - Lukas Gräf (@lukasgraef)
- #5954: [core] Fix #4721: Enable XML rule MissingEncoding in dogfood ruleset - Andreas Dangel (@adangel)
- #5955: chore: Fix LiteralsFirstInComparison violations in test code - Andreas Dangel (@adangel)
- #5957: [java] Fix #3401: Improve message/description/examples for AvoidUsingOctalValues - UncleOwen (@UncleOwen)
- #5958: [core] CSVRenderer: Add begin and end for line and columns (default off) - Jude Pereira (@judepereira)
- #5959: [java] Fix #5960: AddEmptyString: Improve report location - Zbynek Konecny (@zbynek)
- #5961: [java] Fix #5960: Add details to the error message for some rules - Zbynek Konecny (@zbynek)
- #5965: [java] Fix #5881: AvoidLosingException - Consider nested method calls - Andreas Dangel (@adangel)
- #5967: [doc][java] ReplaceJavaUtilDate - improve doc to mention java.sql.Date - Andreas Dangel (@adangel)
- #5968: [doc] Add logging page to sidebar under dev docs - Andreas Dangel (@adangel)
- #5969: [doc] Add CSS in PMD’s description - Andreas Dangel (@adangel)
- #5970: chore: CI improvements - Andreas Dangel (@adangel)
- #5971: [java] Fix #5948: UnnecessaryBoxingRule: Check if unboxing is required for overload resolution - UncleOwen (@UncleOwen)
- #5972: [java] Fix #3434: False negatives in AssignmentInOperand rule - UncleOwen (@UncleOwen)
- #5975: [test] Fix #5973: Enable XML Validation for rule tests - Andreas Dangel (@adangel)
- #5979: [java] Fix #5974: NPE in CloseResourceRule - Lukas Gräf (@lukasgraef)
- #5980: chore: Fix typos - Zbynek Konecny (@zbynek)
- #5981: [java] Fix #4911: AvoidRethrowingException consider supertypes in following catches - UncleOwen (@UncleOwen)
- #5982: [java] More detailed message for the UselessParentheses rule - Zbynek Konecny (@zbynek)
- #5989: [java] Improve performance of RelianceOnDefaultCharset - UncleOwen (@UncleOwen)
- #5994: [java] Fix #4770: UnusedFormalParameter should ignore public constructor as same as method - UncleOwen (@UncleOwen)
- #5995: [html] Add test case that tests the end of a reported violation (test for #3951) - UncleOwen (@UncleOwen)
- #5996: [java] Fix #4916: UseExplicitTypes cases where ‘var’ should be unobjectionable - UncleOwen (@UncleOwen)
- #6006: [java] Fix #5949: New Rule: CollectionTypeMismatch - UncleOwen (@UncleOwen)
- #6008: [core] Fix #5849: Support Markdown Output for CPD Reports - Lukas Gräf (@lukasgraef)
- #6009: [java] More detailed message for AvoidInstanceofChecksInCatchClause - Zbynek Konecny (@zbynek)
- #6016: [java] Fix #6014: Crash when encountering a java comment at the end of a file - UncleOwen (@UncleOwen)
📦 Dependency updates
- #5936: Bump PMD from 7.15.0 to 7.16.0
- #5937: Bump pmdtester from 1.5.5 to 1.6.0
- #5941: chore(deps): bump org.apache.commons:commons-text from 1.13.1 to 1.14.0
- #5944: chore(deps): bump io.github.apex-dev-tools:apex-ls_2.13 from 5.9.0 to 5.10.0
- #5945: chore(deps): bump org.junit:junit-bom from 5.13.3 to 5.13.4
- #5946: chore(deps): bump org.apache.groovy:groovy from 4.0.27 to 4.0.28
- #5962: chore(deps): bump scalameta.version from 4.13.8 to 4.13.9
- #5963: chore(deps-dev): bump org.apache.commons:commons-compress from 1.27.1 to 1.28.0
- #5976: chore(deps-dev): bump all-contributors-cli from 6.20.0 to 6.26.1
- #5978: chore(deps-dev): bump org.assertj:assertj-core from 3.27.3 to 3.27.4
- #5984: chore(deps): bump actions/checkout from 4.2.2 to 5.0.0
- #5985: chore(deps): bump ruby/setup-ruby from 1.254.0 to 1.255.0
- #5986: chore(deps): bump actions/create-github-app-token from 2.0.6 to 2.1.1
- #5988: chore(deps): Bump build-tools from 33 to 34
- #5990: chore(deps): Update @babel/runtime from 7.16.7 to 7.28.7
- #5991: chore(deps): Update tmp from 0.0.33 to 0.2.5
- #5997: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.17.6 to 1.17.7
- #5998: chore(deps): bump kotlin.version from 2.2.0 to 2.2.10
- #5999: chore(deps): bump org.mockito:mockito-core from 5.18.0 to 5.19.0
- #6000: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.17.6 to 1.17.7
- #6001: chore(deps): bump com.google.protobuf:protobuf-java from 4.31.1 to 4.32.0
- #6002: chore(deps): bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.2 to 3.11.3
- #6013: chore(deps): bump actions/setup-java from 4.7.1 to 5.0.0
- #6033: chore(deps): bump ruby/setup-ruby from 1.255.0 to 1.257.0
- #6044: chore(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.1.0.4751 to 5.2.0.4988
- #6045: chore(deps): bump org.jetbrains:annotations from 26.0.2 to 26.0.2-1
- #6046: chore(deps): bump org.apache.groovy:groovy from 4.0.28 to 5.0.0
- #6047: chore(deps): bump org.yaml:snakeyaml from 2.4 to 2.5
- #6048: chore(deps): bump org.codehaus.mojo:versions-maven-plugin from 2.18.0 to 2.19.0
- #6049: chore(deps): bump org.jsoup:jsoup from 1.21.1 to 1.21.2
- #6050: chore(deps): bump bigdecimal from 3.2.2 to 3.2.3 in /docs
📈 Stats
- 188 commits
- 65 closed tickets & PRs
- Days since last release: 49
25-July-2025 - 7.16.0
The PMD team is pleased to announce PMD 7.16.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
🚀 New: Java 25 Support
This release of PMD brings support for Java 25.
There are the following new standard language features:
- JEP 511: Module Import Declarations
- JEP 512: Compact Source Files and Instance Main Methods
- JEP 513: Flexible Constructor Bodies
And one preview language feature:
In order to analyze a project with PMD that uses these preview language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 25-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-25-preview ...
Note: Support for Java 23 preview language features have been removed. The version “23-preview” is no longer available.
New: CPD support for CSS
CPD now supports CSS (Cascading Style Sheets), a language for describing the rendering of structured
documents (such as HTML) on screen, on paper etc.
It is shipped with the new module pmd-css.
✨ New Rules
- Two new rules have been added to Java’s Error Prone category:
ReplaceJavaUtilCalendarandReplaceJavaUtilDate. These rules help to migrate away from old Java APIs aroundjava.util.Calendarandjava.util.Date. It is recommended to use the modernjava.timeAPI instead, which is available since Java 8.
🐛 Fixed Issues
- core
- java
- java-codestyle
- #5892: [java] ShortVariable false positive for java 22 unnamed variable
_
- #5892: [java] ShortVariable false positive for java 22 unnamed variable
- java-design
- #5858: [java] FinalFieldCouldBeStatic false positive for array initializers
- java-errorprone
- #2862: [java] New Rules: Avoid java.util.Date and Calendar classes
🚨 API Changes
Experimental APIs that are now considered stable
- pmd-java
ASTImportDeclaration#isModuleImportis now stable API.ASTCompilationUnit#isCompactis now stable API. Note, it was previously calledisSimpleCompilationUnit.ASTImplicitClassDeclarationis now stable API.JavaVisitorBase#visit(ASTImplicitClassDeclaration, P)is now stable API.
✨ Merged pull requests
- #5733: [css] Add new CPD language - Thomas Prouvot (@tprouvot)
- #5859: Fix #5858: [java] Fix false positive in FinalFieldCouldBeStatic for array initializers - Zbynek Konecny (@zbynek)
- #5872: [java] Add Support for Java 25 - Andreas Dangel (@adangel)
- #5876: chore: license header cleanup - Andreas Dangel (@adangel)
- #5883: Fix #2862: [java] Add rules discouraging the use of java.util.Calendar and java.util.Date - UncleOwen (@UncleOwen)
- #5893: chore: Fix Mockito javaagent warning for Java 21+ - Andreas Dangel (@adangel)
- #5894: chore: Fix JUnit warning about invalid test factory - Andreas Dangel (@adangel)
- #5895: Fix #5597: Move dogfood profile to separate settings.xml - Andreas Dangel (@adangel)
- #5899: Fix #5344: [java] Just log invalid annotation target type - Andreas Dangel (@adangel)
- #5909: [ci] Create a pre-release for snapshot builds - Andreas Dangel (@adangel)
- #5911: [doc] Reference CPD Capable Languages in CPD CLI docu - Andreas Dangel (@adangel)
- #5914: Fix #5892: [java] ShortVariable FP for java 22 Unnamed Variable - Lukas Gräf (@lukasgraef)
- #5918: chore: [cli] Improve symbolic link tests for Windows - Andreas Dangel (@adangel)
- #5920: chore: [scala] Fix javadoc config - Andreas Dangel (@adangel)
📦 Dependency updates
- #5857: Bump PMD from 7.14.0 to 7.15.0
- #5861: Bump scalameta.version from 4.13.7 to 4.13.8
- #5862: Bump com.puppycrawl.tools:checkstyle from 10.25.1 to 10.26.1
- #5863: Bump org.apache.maven.plugins:maven-pmd-plugin from 3.26.0 to 3.27.0
- #5864: Bump kotlin.version from 1.9.24 to 2.2.0
- #5865: Bump org.junit:junit-bom from 5.13.1 to 5.13.2
- #5866: Bump org.jsoup:jsoup from 1.20.1 to 1.21.1
- #5884: Bump org.junit:junit-bom from 5.13.2 to 5.13.3
- #5885: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.7 to 3.2.8
- #5886: Bump org.checkerframework:checker-qual from 3.49.4 to 3.49.5
- #5889: Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.5.0 to 3.6.0
- #5900: Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0
- #5901: Bump io.github.apex-dev-tools:apex-parser from 4.4.0 to 4.4.1
- #5902: Bump log4j.version from 2.25.0 to 2.25.1
- #5910: Bump maven from 3.9.10 to 3.9.11
- #5921: Bump build-tools from 32 to 33
- #5926: chore(deps): bump org.apache.maven.plugins:maven-enforcer-plugin from 3.6.0 to 3.6.1
- #5927: chore(deps): bump ostruct from 0.6.2 to 0.6.3 in /.ci/files in the all-gems group across 1 directory
- #5928: chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.3 to 2.9.4 in the all-actions group
- #5929: chore(deps): Update gems
📈 Stats
- 100 commits
- 21 closed tickets & PRs
- Days since last release: 27
27-June-2025 - 7.15.0
The PMD team is pleased to announce PMD 7.15.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- 💵 Financial Contributions
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
✨ New Rules
- The new Apex rule
AvoidBooleanMethodParametersfinds methods that take a boolean parameter. This can make method calls difficult to understand and maintain as the method is clearly doing two things.
🐛 Fixed Issues
- apex-design
- #5427: [apex] New Rule: Avoid Boolean Method Parameters
- apex-security
- #5788: [apex] ApexCRUDViolation unable to detect insecure SOQL if it is a direct input argument
- doc
- #5790: [doc] Website rule reference pages are returning 404
- java-bestpractices
- java-codestyle
- java-design
- #5804: [java] UselessOverridingMethod doesn’t play well with UnnecessarySuppressWarning
🚨 API Changes
Rule Test Schema
The rule test schema has been extended to support verifying suppressed violations. See Testing your rules for more information.
Also note, the schema rule-tests.xsd is now only in the module “pmd-test-schema”. It has been removed from the old location from module “pmd-test”.
💵 Financial Contributions
Many thanks to our sponsors:
- Cybozu (@cybozu)
✨ Merged pull requests
- #5738: chore: Remove unused private methods in test classes - Pankraz76 (@Pankraz76)
- #5745: [ci] New “Publish Release” workflow - Andreas Dangel (@adangel)
- #5791: [doc] Add a simple check whether generate rule doc pages exist - Andreas Dangel (@adangel)
- #5797: [doc] Update sponsors - Andreas Dangel (@adangel)
- #5800: Fix #5793: [java] NonExhaustiveSwitch should ignore “case null” - Andreas Dangel (@adangel)
- #5803: chore: Remove unnecessary suppress warnings - Andreas Dangel (@adangel)
- #5805: Fix #5804: [java] UselessOverridingMethod needs to ignore SuppressWarnings - Andreas Dangel (@adangel)
- #5806: [test] Verify suppressed violations in rule tests - Andreas Dangel (@adangel)
- #5814: Fix #5788: [apex] ApexCRUDViolation - consider deeper nested Soql - Andreas Dangel (@adangel)
- #5815: Fix #5785: [java] UnusedPrivateField should ignore SuppressWarnings - Andreas Dangel (@adangel)
- #5818: Fix #2304: [java] UnnecessaryImport FP for on-demand imports in JavaDoc - Lukas Gräf (@lukasgraef)
- #5821: [apex] New Rule: Avoid boolean method parameters - Mitch Spano (@mitchspano)
- #5823: [doc] Fix javadoc plugin configuration - Andreas Dangel (@adangel)
- #5833: Fix #1639 #5832: Use filtered comment text for UnnecessaryImport - Andreas Dangel (@adangel)
- #5851: chore: [java] ReplaceHashtableWithMap: Fix name of test - UncleOwen (@UncleOwen)
📦 Dependency updates
- #5775: Bump PMD from 7.13.0 to 7.14.0
- #5778: Bump the all-gems group across 2 directories with 3 updates
- #5779: Bump org.codehaus.mojo:exec-maven-plugin from 3.5.0 to 3.5.1
- #5780: Bump org.apache.maven.plugins:maven-clean-plugin from 3.4.1 to 3.5.0
- #5781: Bump com.google.protobuf:protobuf-java from 4.31.0 to 4.31.1
- #5782: Bump org.apache.groovy:groovy from 4.0.26 to 4.0.27
- #5783: Bump com.puppycrawl.tools:checkstyle from 10.24.0 to 10.25.0
- #5784: Bump org.junit:junit-bom from 5.12.2 to 5.13.0
- #5807: Bump maven from 3.9.8 to 3.9.10
- #5809: Bump org.codehaus.mojo:build-helper-maven-plugin from 3.6.0 to 3.6.1
- #5810: Bump org.junit:junit-bom from 5.13.0 to 5.13.1
- #5811: Bump junit5.platform.version from 1.13.0 to 1.13.1
- #5812: Bump org.checkerframework:checker-qual from 3.49.3 to 3.49.4
- #5813: Bump the all-gems group across 2 directories with 1 update
- #5828: Bump scalameta.version from 4.13.6 to 4.13.7
- #5829: Bump liquid from 5.8.6 to 5.8.7 in /.ci/files in the all-gems group across 1 directory
- #5838: Bump marocchino/sticky-pull-request-comment from 2.9.2 to 2.9.3 in the all-actions group
- #5839: Bump log4j.version from 2.24.3 to 2.25.0
- #5840: Bump com.puppycrawl.tools:checkstyle from 10.25.0 to 10.25.1
- #5841: Bump net.bytebuddy:byte-buddy-agent from 1.17.5 to 1.17.6
- #5842: Bump net.bytebuddy:byte-buddy from 1.17.5 to 1.17.6
- #5843: Bump org.sonatype.central:central-publishing-maven-plugin from 0.7.0 to 0.8.0
- #5844: Bump ostruct from 0.6.1 to 0.6.2 in /.ci/files in the all-gems group across 1 directory
- #5853: Bump build-tools from 30 to 32
📈 Stats
- 91 commits
- 24 closed tickets & PRs
- Days since last release: 27
30-May-2025 - 7.14.0
The PMD team is pleased to announce PMD 7.14.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
PMD CLI now uses threaded execution by default
In the PMD CLI, the --threads (-t) option can now accept a thread
count given relative to the number of cores of the machine. For instance,
it is now possible to write -t 1C to spawn one thread per core, or -t 0.5C
to spawn one thread for every other core.
The thread count option now defaults to 1C, meaning parallel execution
is used by default. You can disable this by using -t 1.
New Rule UnnecessaryWarningSuppression (experimental)
This new Java rule UnnecessaryWarningSuppression reports unused suppression
annotations and comments. Violations of this rule cannot be suppressed.
How to use it? Just include it in your ruleset:
<rule ref="category/java/bestpractices.xml/UnnecessaryWarningSuppression" />
Note: This rule is currently experimental. It is available for now only for Java.
The rule for now only reports annotations specific to PMD, like @SuppressWarnings("PMD").
In the future we might be able to check for other common ones like @SuppressWarnings("unchecked") or "fallthrough".
Since violations of this rule cannot be suppressed, we opted here on the side of false-negatives and
don’t report every unused case yet.
However, suppressing specific PMD rules is working as expected.
Migrating to Central Publisher Portal
We’ve now migrated to Central Publisher Portal. Snapshots of PMD are still available, however the repository URL changed. To consume these with maven, you can use the following snippet:
<repositories>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
Releases of PMD are available on Maven Central as before without change.
More CLI parameters shared between PMD and CPD
When executing PMD or CPD, the same parameters are now understood for selecting which files should be analyzed. See File collection options for a list of common, shared parameters that are valid for both commands.
🐛 Fixed Issues
- core
- java-bestpractices
- java-codestyle
- java-design
- java-errorprone
- #5702: [java] InvalidLogMessageFormat: Lombok @Slf4j annotation is not interpreted by PMD
- java-performance
- #5711: [java] UseArraysAsList false positive with Sets
- visualforce
- #5476: [visualforce] NPE when analyzing standard field references in visualforce page
🚨 API Changes
CLI
- CPD now supports
--report-file(-r) and--exclude-file-list. - PMD now supports
--excludeand--non-recursive. - The option
--ignore-listin PMD is renamed to--exclude-file-list.
Deprecations
- CLI
- The option
--ignore-listhas been deprecated. Use--exclude-file-listinstead.
- The option
- core
AstInfo#getSuppressionComments: UsegetAllSuppressionCommentsorgetSuppressionComment.AstInfo#withSuppressMap: UsewithSuppressionCommentsAbstractTokenManager#suppressMap: Don’t use this map directly anymore. Instead, usegetSuppressionComments.AbstractTokenManager#getSuppressMap: UsegetSuppressionCommentsinstead.
- pmd-java
ASTCompactConstructorDeclaration#getDeclarationNode: This method just returnsthisand isn’t useful.JavaMetrics#NPATH: UseNPATH_COMP, which is available on more nodes, and uses Long instead of BigInteger.
Experimental
- core
- pmd-java
✨ Merged pull requests
- #5584: [ci] New workflow “Publish Snapshot” - Andreas Dangel (@adangel)
- #5599: [java] Rewrite NPath complexity metric - Clément Fournier (@oowekyala)
- #5609: [core] Add rule to report unnecessary suppression comments/annotations - Clément Fournier (@oowekyala)
- #5699: Fix #5702: [java] First-class support for lombok @Slf4j - Clément Fournier (@oowekyala)
- #5700: [core] Don’t accidentally catch unexpected runtime exceptions in CpdAnalysis - Elliotte Rusty Harold (@elharo)
- #5712: Fix #5711: [java] UseArrayAsList - only consider List.add - Andreas Dangel (@adangel)
- #5715: Fix #5476: [visualforce] Resolve data types of standard object fields - Andreas Dangel (@adangel)
- #5716: Fix #5634: [java] CommentDefaultAccessModifier: Comment between annotation and constructor not recognized - Lukas Gräf (@lukasgraef)
- #5726: Fix #5724: [java] Implicit functional interface FP with sealed interface - Clément Fournier (@oowekyala)
- #5727: Fix #5621: [java] Fix FPs with UnusedPrivateMethod - Clément Fournier (@oowekyala)
- #5728: [ci] Improvements for “Publish Pull Requests” - Andreas Dangel (@adangel)
- #5730: [ci] Refactor git-repo-sync - Andreas Dangel (@adangel)
- #5731: [cli] Share more CLI options between CPD and PMD - Clément Fournier (@oowekyala)
- #5736: Fix #5061: [java] UnusedLocalVariable FP when using compound assignment - Lukas Gräf (@lukasgraef)
- #5741: [cli] Make CLI default to multithreaded - Clément Fournier (@oowekyala)
- #5742: [ci] publish-snapshot/old build: migrate to central portal - Andreas Dangel (@adangel)
- #5743: [ci] Make build a reusable workflow - Andreas Dangel (@adangel)
- #5744: Fix #5705: [cli] Always determine PMD_HOME based on script location - Andreas Dangel (@adangel)
- #5748: [core] Reformat SarifLog to comply to coding standards - Andreas Dangel (@adangel)
- #5763: [java] Support annotated constructor return type in symbol API - Clément Fournier (@oowekyala)
- #5764: Fix #2462: [java] LinguisticNaming should ignore setters for Builders - Lukas Gräf (@lukasgraef)
📦 Dependency updates
- #5706: Bump PMD from 7.12.0 to 7.13.0
- #5709: Bump com.google.code.gson:gson from 2.13.0 to 2.13.1
- #5710: Bump com.puppycrawl.tools:checkstyle from 10.23.0 to 10.23.1
- #5717: Bump scalameta.version from 4.13.4 to 4.13.5
- #5718: Bump org.checkerframework:checker-qual from 3.49.2 to 3.49.3
- #5719: Bump org.jsoup:jsoup from 1.19.1 to 1.20.1
- #5751: Bump scalameta.version from 4.13.5 to 4.13.6
- #5754: Bump com.google.protobuf:protobuf-java from 4.30.2 to 4.31.0
- #5766: Bump io.github.git-commit-id:git-commit-id-maven-plugin from 9.0.1 to 9.0.2
- #5767: Bump org.mockito:mockito-core from 5.17.0 to 5.18.0
- #5768: Bump com.puppycrawl.tools:checkstyle from 10.23.1 to 10.24.0
📈 Stats
- 165 commits
- 33 closed tickets & PRs
- Days since last release: 35
25-April-2025 - 7.13.0
The PMD team is pleased to announce PMD 7.13.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
Docker images
PMD is now providing official docker images at https://hub.docker.com/r/pmdcode/pmd and https://github.com/pmd/docker/pkgs/container/pmd.
You can now analyze your code with PMD by using docker like so:
docker run --rm --tty -v $PWD:/src pmdcode/pmd:latest check -d . -R rulesets/java/quickstart.xml`
More information is available at https://github.com/pmd/docker.
Experimental support for language dialects
A dialect is a particular form of another supported language. For example, an XSLT is a particular form of an XML. Even though the dialect has its own semantics and uses, the contents are still readable by any tool capable of understanding the base language.
In PMD, a dialect allows to set up completely custom rules, XPath functions, properties and metrics for these files; while retaining the full support of the underlying base language including already existing rules and XPath functions.
See [core] Support language dialects #5438 and Adding a new dialect for more information.
✨ New Rules
- The new Apex rule
TypeShadowsBuiltInNamespacefinds Apex classes, enums, and interfaces that have the same name as a class, enum, or interface in theSystemorSchemanamespace. Shadowing these namespaces in this way can lead to confusion and unexpected behavior.
🐛 Fixed Issues
- core
- apex-bestpractices
- #5667: [apex] ApexUnitTestShouldNotUseSeeAllDataTrue false negative when seeAllData parameter is a string
- apex-errorprone
- #3184: [apex] Prevent classes from shadowing System Namespace
- java
- #5645: [java] Parse error on switch with yield
- java-bestpractices
- #5687: [java] UnusedPrivateMethodRule: exclude serialization method readObjectNoData()
- plsql
- #5675: [plsql] Parse error with TREAT function
🚨 API Changes
Deprecations
net.sourceforge.pmd.lang.xml.pom.PomLanguageModuleis deprecated. POM is now a dialect of XML. UsePomDialectModuleinstead.net.sourceforge.pmd.lang.xml.wsdl.WsdlLanguageModuleis deprecated. WSDL is now a dialect of XML. UseWsdlDialectModuleinstead.net.sourceforge.pmd.lang.xml.xsl.XslLanguageModuleis deprecated. XSL is now a dialect of XML. UseXslDialectModuleinstead.
Experimental API
- The core API around support for language dialects:
✨ Merged pull requests
- #5438: [core] Support language dialects - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5450: Fix #3184: [apex] New Rule: TypeShadowsBuiltInNamespace - Mitch Spano (@mitchspano)
- #5573: Fix #5525: [core] Add Sarif Level Property - julees7 (@julees7)
- #5623: [dist] Make pmd launch script compatible with /bin/sh - Clément Fournier (@oowekyala)
- #5648: Fix #5645: [java] Parse error with yield statement - Clément Fournier (@oowekyala)
- #5652: [java] Cleanup
AccessorClassGenerationRuleimplementation - Pankraz76 (@Pankraz76) - #5672: [doc] Fix its/it’s and doable/double typos - John Jetmore (@jetmore)
- #5674: Fix #5448: [ci] Maintain public Docker image - Andreas Dangel (@adangel)
- #5684: Fix #5667: [apex] ApexUnitTestShouldNotUseSeeAllDataTrue false negative when seeAllDate parameter is a string - Thomas Prouvot (@tprouvot)
- #5685: [doc] typo fix in PMD Designer reference - Douglas Griffith (@dwgrth)
- #5686: Fix #5675: [plsql] Support TREAT function with specified datatype - Andreas Dangel (@adangel)
- #5687: [java] UnusedPrivateMethodRule: exclude serialization method readObjectNoData() - Gili Tzabari (@cowwoc)
- #5688: [java] Fix Double Literal for Java19+ compatibility - Andreas Dangel (@adangel)
📦 Dependency updates
- #5607: Bump org.junit:junit-bom from 5.11.4 to 5.12.1
- #5641: Bump PMD from 7.11.0 to 7.12.0
- #5653: Bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.0.0.4389 to 5.1.0.4751
- #5654: Bump surefire.version from 3.5.2 to 3.5.3
- #5655: Bump com.google.guava:guava from 33.4.5-jre to 33.4.6-jre
- #5656: Bump org.ow2.asm:asm from 9.7.1 to 9.8
- #5657: Bump com.google.protobuf:protobuf-java from 4.30.1 to 4.30.2
- #5658: Bump logger from 1.6.6 to 1.7.0 in /.ci/files in the all-gems group across 1 directory
- #5671: Bump checkstyle from 10.21.4 to 10.23.0
- #5676: Bump org.checkerframework:checker-qual from 3.49.1 to 3.49.2
- #5677: Bump junit5.platform.version from 1.12.1 to 1.12.2
- #5678: Bump org.apache.commons:commons-text from 1.13.0 to 1.13.1
- #5679: Bump com.google.guava:guava from 33.4.6-jre to 33.4.7-jre
- #5680: Bump org.mockito:mockito-core from 5.16.1 to 5.17.0
- #5681: Bump org.jacoco:jacoco-maven-plugin from 0.8.12 to 0.8.13
- #5682: Bump net.bytebuddy:byte-buddy-agent from 1.17.4 to 1.17.5
- #5683: Bump the all-gems group across 2 directories with 2 updates
- #5691: Bump com.google.code.gson:gson from 2.12.1 to 2.13.0
- #5692: Bump com.google.guava:guava from 33.4.7-jre to 33.4.8-jre
- #5693: Bump net.bytebuddy:byte-buddy from 1.17.4 to 1.17.5
- #5694: Bump org.junit:junit-bom from 5.12.1 to 5.12.2
- #5696: Bump info.picocli:picocli from 4.7.6 to 4.7.7
- #5697: Bump com.github.hazendaz.maven:coveralls-maven-plugin from 4.5.0-M6 to 4.7.0
- #5704: Bump nokogiri from 1.18.5 to 1.18.8
📈 Stats
- 117 commits
- 19 closed tickets & PRs
- Days since last release: 27
28-March-2025 - 7.12.0
The PMD team is pleased to announce PMD 7.12.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
✨ New Rules
- The new Java rule
ImplicitFunctionalInterfacereports functional interfaces that were not explicitly declared as such with the annotation@FunctionalInterface. If an interface is accidentally a functional interface, then it should bear a@SuppressWarnings("PMD.ImplicitFunctionalInterface")annotation to make this clear.
🐛 Fixed Issues
- core
- #5593: [core] Make renderers output files in deterministic order even when multithreaded
- apex
- #5567: [apex] Provide type information for CastExpression
- apex-design
- #5616: [apex] ExcessiveParameterList reports entire method instead of signature only
- java
- #5587: [java] Thread deadlock during PMD analysis in ParseLock.getFinalStatus
- java-bestpractices
- java-codestyle
- plsql
🚨 API Changes
Deprecations
- java
- The method
buildConstValueis deprecated for removal. It should have been package-private from the start. In order to get the (compile time) const value of an expression, usegetConstValueorgetConstFoldingResultinstead. - For the same reason, the following methods are also deprecated for removal:
buildConstValueandbuildConstValue.
- The method
JTypeVar#withUpperboundis deprecated. It was previously meant to be used internally and not needed anymore.
✨ Merged pull requests
- #5550: Fix #5521: [plsql] Improve parser performance by reducing lookaheads - Andreas Dangel (@adangel)
- #5554: Fix #5369: [java] Consider that lombok.val and var are inferred - Clément Fournier (@oowekyala)
- #5555: Fix #2849: [java] Add rule ImplicitFunctionalInterface - Clément Fournier (@oowekyala)
- #5556: [ci] New workflow “Publish Results from Pull Requests” - Andreas Dangel (@adangel)
- #5574: Fix #5567: [apex] Provide type info for CastExpression - Andreas Dangel (@adangel)
- #5583: [java] Fix race condition in ClassStub for inner classes - Andreas Dangel (@adangel)
- #5586: [java/core] Micro optimizations - Clément Fournier (@oowekyala)
- #5588: [java] Fix crash when parsing class for anonymous class - Clément Fournier (@oowekyala)
- #5591: Fix #5587: [java] Fix deadlock while loading ClassStub - Clément Fournier (@oowekyala)
- #5593: [core] Make renderers output files in deterministic order even when multithreaded - Clément Fournier (@oowekyala)
- #5595: Fix #5590: [java] LiteralsFirstInComparisons with constant field - Clément Fournier (@oowekyala)
- #5596: Fix #4441: [plsql] XMLQuery - Support identifier as XQuery_string parameter - Andreas Dangel (@adangel)
- #5598: Fix #5592: [java] Fix UnusedAssignment FP with compact record ctor - Clément Fournier (@oowekyala)
- #5600: Fix #5079: [java] LocalVariableCouldBeFinal false-positive with lombok.val - Clément Fournier (@oowekyala)
- #5611: Fix #5452: [java] PackageCase reported on wrong line - Clément Fournier (@oowekyala)
- #5617: Fix #5616: [apex] ExcessiveParameterList: Report only method signature - Andreas Dangel (@adangel)
- #5618: [doc] Fix search index - Andreas Dangel (@adangel)
📦 Dependency updates
- #5558: Bump PMD from 7.10.0 to 7.11.0
- #5561: Bump org.apache.groovy:groovy from 4.0.25 to 4.0.26
- #5562: Bump org.junit.platform:junit-platform-suite from 1.11.4 to 1.12.0
- #5564: Bump org.apache.maven.plugins:maven-clean-plugin from 3.4.0 to 3.4.1
- #5565: Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.3 to 3.1.4
- #5566: Bump io.github.apex-dev-tools:apex-ls_2.13 from 5.7.0 to 5.8.0
- #5571: Bump nokogiri from 1.16.7 to 1.18.3
- #5572: Bump uri from 0.13.1 to 1.0.3
- #5575: Bump org.jsoup:jsoup from 1.18.3 to 1.19.1
- #5576: Bump scalameta.version from 4.13.2 to 4.13.3
- #5577: Bump org.yaml:snakeyaml from 2.3 to 2.4
- #5578: Bump com.google.protobuf:protobuf-java from 4.29.3 to 4.30.0
- #5580: Bump net.bytebuddy:byte-buddy from 1.17.1 to 1.17.2
- #5581: Bump com.puppycrawl.tools:checkstyle from 10.21.3 to 10.21.4
- #5582: Bump the gems liquid to 5.8.1 and logger to 1.6.6
- #5602: Bump org.apache.maven.plugins:maven-install-plugin from 3.1.3 to 3.1.4
- #5603: Bump net.bytebuddy:byte-buddy-agent from 1.17.1 to 1.17.2
- #5604: Bump org.mockito:mockito-core from 5.15.2 to 5.16.1
- #5605: Bump org.junit.platform:junit-platform-suite from 1.12.0 to 1.12.1
- #5606: Bump org.checkerframework:checker-qual from 3.49.0 to 3.49.1
- #5608: Bump com.google.protobuf:protobuf-java from 4.30.0 to 4.30.1
- #5619: Bump nokogiri from 1.18.3 to 1.18.5
- #5624: Bump scalameta.version from 4.13.3 to 4.13.4
- #5627: Bump net.bytebuddy:byte-buddy-agent from 1.17.2 to 1.17.4
- #5628: Bump io.github.apex-dev-tools:apex-ls_2.13 from 5.8.0 to 5.9.0
- #5629: Bump com.google.guava:guava from 33.4.0-jre to 33.4.5-jre
- #5630: Bump net.bytebuddy:byte-buddy from 1.17.2 to 1.17.4
📈 Stats
- 114 commits
- 28 closed tickets & PRs
- Days since last release: 27
28-February-2025 - 7.11.0
The PMD team is pleased to announce PMD 7.11.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
✨ New Rules
- The new Apex rule
AvoidStatefulDatabaseResultdetectsDatabase.Statefulimplementations that store database results in instance variables. This can cause serialization issues between successive batch iterations.
Signed Releases
We now not only sign the maven artifacts, but also our binary distribution files that you can download from GitHub Releases. See the page Signed Releases in our documentation for how to verify the files.
🐛 Fixed Issues
- apex-errorprone
- #5305: [apex] New Rule: Avoid Stateful Database Results
- java
- java-bestpractices
- java-codestyle
- #4822: [java] UnnecessaryCast false-positive for raw types
- #5073: [java] UnnecessaryCast false-positive for cast in return position of lambda
- #5440: [java] UnnecessaryCast reported in stream chain map() call that casts to more generic interface
- #5523: [java] UnnecessaryCast false-positive for integer operations in floating-point context
- #5541: [java] Fix IdenticalCatchBranch reporting branches that call different overloads
- java-design
- #5018: [java] FinalFieldCouldBeStatic false-positive for access of super class field
- plsql
- #5522: [plsql] Parse error for operator in TRIM function call
🚨 API Changes
Deprecations
- java
- The method
TypeOps#isContextDependent(JMethodSig)is deprecated for removal. UseisContextDependent(JExecutableSymbol)instead which is more flexible.
- The method
✨ Merged pull requests
- #5425: [apex] New Rule: Avoid Stateful Database Results - Mitch Spano (@mitchspano)
- #5491: [docs] Call render_release_notes.rb within docs - Andreas Dangel (@adangel)
- #5492: [docs] Add security page with known vulnerabilities - Andreas Dangel (@adangel)
- #5503: [java] AvoidSynchronizedAtMethodLevel: Fixed error in code example - Balazs Glatz (@gbq6)
- #5507: Fix #5486: [java] Fix UnusedPrivateMethod - always search decls in current AST - Andreas Dangel (@adangel)
- #5508: Fix #3359: [java] UnusedPrivateMethod: Ignore lombok.EqualsAndHashCode.Include - Andreas Dangel (@adangel)
- #5510: [ci] Add signed releases - Andreas Dangel (@adangel)
- #5524: [ci] New optimized workflow for pull requests - Andreas Dangel (@adangel)
- #5526: Fix #5523: [java] UnnecessaryCast FP with integer division - Clément Fournier (@oowekyala)
- #5527: Fix #5522: [plsql] Allow arbitrary expressions for TRIM - Andreas Dangel (@adangel)
- #5528: Fix #5442: [java] Fix stackoverflow with recursive generic types - Clément Fournier (@oowekyala)
- #5529: Fix #5493: [java] IllegalArgumentException with wildcard bound - Clément Fournier (@oowekyala)
- #5530: Fix #5073: [java] UnnecessaryCast FP with lambdas - Clément Fournier (@oowekyala)
- #5537: Fix #5504: [java] UnusedAssignment FP with continue in foreach loop - Clément Fournier (@oowekyala)
- #5538: Add project icon for IntelliJ IDEA - Vincent Potucek (@pankratz227)
- #5539: [plsql] Add OracleDBUtils as regression testing project - Andreas Dangel (@adangel)
- #5541: [java] Fix IdenticalCatchBranch reporting branches that call different overloads - Clément Fournier (@oowekyala)
- #5542: Add GitHub issue links in IDEA git log - Andreas Dangel (@adangel)
- #5544: [javacc] Move grammar files into src/main/javacc - Andreas Dangel (@adangel)
- #5551: [doc] Update contributors for 7.11.0 - Andreas Dangel (@adangel)
- #5552: Fix #4822: [java] UnnecessaryCast FP with unchecked cast - Clément Fournier (@oowekyala)
- #5553: Fix #5018: [java] FinalFieldCouldBeStatic FP with super field access - Clément Fournier (@oowekyala)
📦 Dependency updates
- #5490: Bump PMD from 7.9.0 to 7.10.0
- #5494: Bump liquid from 5.7.1 to 5.7.2 in the all-gems group across 1 directory
- #5497: Bump net.bytebuddy:byte-buddy-agent from 1.16.1 to 1.17.0
- #5498: Bump org.assertj:assertj-core from 3.25.3 to 3.27.3
- #5499: Bump org.mockito:mockito-core from 5.14.2 to 5.15.2
- #5500: Bump org.junit:junit-bom from 5.11.2 to 5.11.4
- #5501: Bump org.scala-lang:scala-reflect from 2.13.15 to 2.13.16
- #5516: Bump org.jetbrains:annotations from 26.0.1 to 26.0.2
- #5517: Bump net.bytebuddy:byte-buddy from 1.15.11 to 1.17.0
- #5518: Bump org.junit.platform:junit-platform-suite from 1.11.3 to 1.11.4
- #5519: Bump org.checkerframework:checker-qual from 3.48.3 to 3.49.0
- #5520: Bump com.google.guava:guava from 33.0.0-jre to 33.4.0-jre
- #5532: Bump net.bytebuddy:byte-buddy-agent from 1.17.0 to 1.17.1
- #5533: Bump log4j.version from 2.24.2 to 2.24.3
- #5534: Bump com.google.code.gson:gson from 2.11.0 to 2.12.1
- #5535: Bump scalameta.version from 4.12.7 to 4.13.1.1
- #5536: Bump org.apache.groovy:groovy from 4.0.24 to 4.0.25
- #5545: Bump commons-logging:commons-logging from 1.3.4 to 1.3.5
- #5546: Bump scalameta.version from 4.13.1.1 to 4.13.2
- #5547: Bump net.bytebuddy:byte-buddy from 1.17.0 to 1.17.1
- #5548: Bump com.puppycrawl.tools:checkstyle from 10.21.2 to 10.21.3
- #5549: Bump org.apache.maven.plugins:maven-compiler-plugin from 3.13.0 to 3.14.0
📈 Stats
- 97 commits
- 35 closed tickets & PRs
- Days since last release: 28
31-January-2025 - 7.10.0
The PMD team is pleased to announce PMD 7.10.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🌟 New and changed rules
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
🚀 New: Java 24 Support
This release of PMD brings support for Java 24. There are no new standard language features, but a couple of preview language features:
- JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)
- JEP 492: Flexible Constructor Bodies (Third Preview)
- JEP 494: Module Import Declarations (Second Preview)
- JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview)
In order to analyze a project with PMD that uses these preview language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 24-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-24-preview ...
Note: Support for Java 22 preview language features have been removed. The version “22-preview” is no longer available.
New GPG Release Signing Key
Since January 2025, we switched the GPG Key we use for signing releases in Maven Central to be
A0B5CA1A4E086838.
The full fingerprint is 2EFA 55D0 785C 31F9 56F2 F87E A0B5 CA1A 4E08 6838.
This step was necessary, as the passphrase of the old key has been compromised and therefore the key is not safe to use anymore. While the key itself is not compromised as far as we know, we still decided to generate a new key, just to be safe. As until now (January 2025) we are not aware, that the key actually has been misused. The previous releases of PMD in Maven Central can still be considered untampered, as Maven Central is read-only.
This unexpected issue was discovered while checking Reproducible Builds by a third party.
The security advisory about the compromised passphrase is tracked as GHSA-88m4-h43f-wx84 and CVE-2025-23215.
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog (7.10.0).
🌟 New and changed rules
New Rules
- The new Java rule
ExhaustiveSwitchHasDefaultfinds switch statements and expressions, that cover already all cases but still have a default case. This default case is unnecessary and prevents getting compiler errors when e.g. new enum constants are added without extending the switch.
🐛 Fixed Issues
- apex
- apex-security
- #3158: [apex] ApexSuggestUsingNamedCred false positive with Named Credential merge fields
- documentation
- #2492: [doc] Promote wiki pages to standard doc pages
- java
- #5154: [java] Support Java 24
- java-performance
- #5311: [java] TooFewBranchesForSwitch false positive for exhaustive switches over enums without default case
🚨 API Changes
Removed Experimental API
- pmd-java
net.sourceforge.pmd.lang.java.ast.ASTTemplate,net.sourceforge.pmd.lang.java.ast.ASTTemplateExpression,net.sourceforge.pmd.lang.java.ast.ASTTemplateFragment: These nodes were introduced with Java 21 and 22 Preview to support String Templates. However, the String Template preview feature was not finalized and has been removed from Java for now. We now cleaned up the PMD implementation of it.
✨ Merged pull requests
- #5327: [apex] Update apex-parser and summit-ast - Andreas Dangel (@adangel)
- #5412: [java] Support exhaustive switches - Andreas Dangel (@adangel)
- #5449: Use new gpg key (A0B5CA1A4E086838) - Andreas Dangel (@adangel)
- #5458: [doc] Move Wiki pages into main documentation, cleanups - Andreas Dangel (@adangel)
- #5471: [java] Support Java 24 - Andreas Dangel (@adangel)
- #5488: [apex] Fix #3158: Recognize Named Credentials merge fields in ApexSuggestUsingNamedCredRule - William Brockhus (@YodaDaCoda)
📦 Dependency updates
- #5423: Bump PMD from 7.8.0 to 7.9.0
- #5433: Bump org.codehaus.mojo:exec-maven-plugin from 3.2.0 to 3.5.0
- #5434: Bump commons-logging:commons-logging from 1.3.0 to 1.3.4
- #5435: Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.4.1 to 3.5.0
- #5436: Bump the all-gems group across 2 directories with 1 update
- #5445: Bump org.junit.platform:junit-platform-commons from 1.11.2 to 1.11.4
- #5446: Bump org.sonarsource.scanner.maven:sonar-maven-plugin from 3.10.0.2594 to 5.0.0.4389
- #5459: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.7
- #5460: Bump org.apache.commons:commons-text from 1.12.0 to 1.13.0
- #5461: Bump com.google.protobuf:protobuf-java from 4.29.1 to 4.29.3
- #5472: Bump net.bytebuddy:byte-buddy-agent from 1.15.11 to 1.16.1
- #5473: Bump org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0
- #5474: Bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.23.0 to 0.23.1
- #5475: Bump liquid from 5.6.0 to 5.7.0 in the all-gems group across 1 directory
- #5479: Bump pmd-designer from 7.2.0 to 7.10.0
- #5480: Bump scalameta.version from 4.9.1 to 4.12.7
- #5481: Bump liquid from 5.7.0 to 5.7.1 in the all-gems group across 1 directory
- #5482: Bump org.codehaus.mojo:versions-maven-plugin from 2.17.1 to 2.18.0
- #5483: Bump org.jetbrains.dokka:dokka-maven-plugin from 1.9.20 to 2.0.0
- #5484: Bump com.github.hazendaz.maven:coveralls-maven-plugin from 4.5.0-M5 to 4.5.0-M6
- #5485: Bump com.puppycrawl.tools:checkstyle from 10.20.2 to 10.21.2
📈 Stats
- 70 commits
- 13 closed tickets & PRs
- Days since last release: 34
27-December-2024 - 7.9.0
The PMD team is pleased to announce PMD 7.9.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
New: CPD support for Rust
CPD now supports Rust, a blazingly fast and memory-efficient programming language.
It is shipped in the new module pmd-rust.
🐛 Fixed Issues
- cli
- java
- #5096: [java] StackOverflowError with recursively bound type variable
- java-bestpractices
- #4861: [java] UnusedPrivateMethod - false positive with static methods in core JDK classes
- java-documentation
- #2996: [java] CommentSize rule violation is not suppressed at method level
🚨 API Changes
Experimental API
- pmd-core:
RuleContext#addViolationWithPosition
✨ Merged pull requests
- #4939: [java] Fix #2996 - CommentSize/CommentContent suppression - Clément Fournier (@oowekyala)
- #5376: [java] Fix #4861 - UnusedPrivateMethod FP in JDK classes - Clément Fournier (@oowekyala)
- #5387: [java] Fix #5096 - StackOverflowError with recursively bounded tvar - Clément Fournier (@oowekyala)
- #5400: Fix #5399: [cli] pmd.bat: Quote all variables when using SET - Andreas Dangel (@adangel)
- #5402: Fix #5401: [cli] pmd.bat: set codepage to 65001 (UTF-8) - Andreas Dangel (@adangel)
- #5404: [doc] Update tools / integrations / ide plugins / news pages - Andreas Dangel (@adangel)
- #5414: Add Rust CPD - Julia Paluch (@juliapaluch)
📦 Dependency updates
- #5375: Bump pmd from 7.7.0 to 7.8.0
- #5377: Bump com.puppycrawl.tools:checkstyle from 10.20.1 to 10.20.2
- #5378: Bump net.bytebuddy:byte-buddy from 1.14.12 to 1.15.10
- #5379: Bump io.github.git-commit-id:git-commit-id-maven-plugin from 7.0.0 to 9.0.1
- #5380: Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.6.0
- #5384: Bump org.apache.groovy:groovy from 4.0.19 to 4.0.24
- #5390: Bump com.google.protobuf:protobuf-java from 4.28.2 to 4.29.1
- #5391: Bump org.hamcrest:hamcrest from 2.2 to 3.0
- #5392: Bump org.codehaus.mojo:build-helper-maven-plugin from 3.5.0 to 3.6.0
- #5393: Bump org.jsoup:jsoup from 1.17.2 to 1.18.3
- #5394: Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.2
- #5395: Bump webrick from 1.9.0 to 1.9.1 in /docs in the all-gems group across 1 directory
- #5405: Bump org.yaml:snakeyaml from 2.2 to 2.3
- #5406: Bump io.github.apex-dev-tools:apex-ls_2.13 from 5.5.0 to 5.7.0
- #5407: Bump net.bytebuddy:byte-buddy-agent from 1.14.19 to 1.15.11
- #5409: Bump net.bytebuddy:byte-buddy from 1.15.10 to 1.15.11
- #5410: Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.11.2
- #5411: Bump csv from 3.3.0 to 3.3.1 in /docs in the all-gems group across 1 directory
- #5417: Bump org.cyclonedx:cyclonedx-maven-plugin from 2.7.11 to 2.9.1
- #5418: Bump org.checkerframework:checker-qual from 3.48.1 to 3.48.3
- #5419: Bump org.apache.maven.plugins:maven-checkstyle-plugin from 3.5.0 to 3.6.0
- #5422: Bump the all-gems group across 2 directories with 2 updates
📈 Stats
- 69 commits
- 12 closed tickets & PRs
- Days since last release: 28
29-November-2024 - 7.8.0
The PMD team is pleased to announce PMD 7.8.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🌟 New and changed rules
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
🌟 New and changed rules
New Rules
- The new Apex rule
QueueableWithoutFinalizerdetects when the Queueable interface is used but a Finalizer is not attached. Without attaching a Finalizer, there is no way of designing error recovery actions should the Queueable action fail.
🐛 Fixed Issues
- ant
- #1860: [ant] Reflective access warnings on java > 9 and java < 17
- apex
- html
- #5322: [html] CPD throws exception on when HTML file is missing closing tag
- java
- #5283: [java] AssertionError “this should be unreachable” with scala library
- #5293: [java] Deadlock when executing PMD in multiple threads
- #5324: [java] Issue with type inference of nested lambdas
- #5329: [java] Type inference issue with unknown method ref in call chain
- #5338: [java] Unresolved target type for lambdas make overload resolution fail
- java-bestpractices
- #4113: [java] JUnitTestsShouldIncludeAssert - false positive with SoftAssertionsExtension
- #5083: [java] UnusedPrivateMethod false positive when method reference has no target type
- #5097: [java] UnusedPrivateMethod FP with raw type missing from the classpath
- #5318: [java] PreserveStackTraceRule: false-positive on Pattern Matching with instanceof
- java-codestyle
- java-design
- #4763: [java] SimplifyBooleanReturns - wrong suggested solution
- java-errorprone
- #5070: [java] ConfusingArgumentToVarargsMethod FP when types are unresolved
- java-performance
🚨 API Changes
Deprecations
- pmd-coco
CocoBaseListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.CocoBaseVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.CocoListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.CocoParseris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.CocoVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
- pmd-gherkin
GherkinBaseListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.GherkinBaseVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.GherkinListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.GherkinParseris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.GherkinVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
- pmd-julia
JuliaBaseListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.JuliaBaseVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.JuliaListeneris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.JuliaParseris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.JuliaVisitoris deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
- pmd-kotlin
UnicodeClassesis deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
- pmd-xml
XMLLexeris deprecated for removal. Usenet.sourceforge.pmd.lang.xml.ast.XMLLexerinstead (note different packageastinstead ofantlr4).
✨ Merged pull requests
- #5240: Release notes improvements - Andreas Dangel (@adangel)
- #5284: [apex] Use case-insensitive input stream to avoid choking on Unicode escape sequences - Willem A. Hajenius (@wahajenius)
- #5286: [ant] Formatter: avoid reflective access to determine console encoding - Andreas Dangel (@adangel)
- #5289: [java] TooFewBranchesForSwitch - allow list of case constants - Andreas Dangel (@adangel)
- #5296: [xml] Have pmd-xml Lexer in line with other antlr grammars - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5300: Add rule test cases for issues fixed with PMD 7.0.0 - Andreas Dangel (@adangel)
- #5303: [apex] New Rule: Queueable Should Attach Finalizer - Mitch Spano (@mitchspano)
- #5309: [java] Fix #5293: Parse number of type parameters eagerly - Andreas Dangel (@adangel)
- #5310: [java] Fix #5283 - inner class has public private modifiers - Clément Fournier (@oowekyala)
- #5325: [java] Fix inference dependency issue with nested lambdas - Clément Fournier (@oowekyala)
- #5326: [java] UseStringBufferLength - consider sb.toString().equals(“”) - Andreas Dangel (@adangel)
- #5328: [html] Test for a closing tag when determining node positions - Andreas Dangel (@adangel)
- #5330: [java] Propagate unknown type better when mref is unresolved - Clément Fournier (@oowekyala)
- #5331: [java] PreserveStackTrace - consider instance type patterns - Andreas Dangel (@adangel)
- #5332: [java] InsufficientStringBufferDeclaration: Fix CCE for Character - Andreas Dangel (@adangel)
- #5334: [java] UnitTestShouldIncludeAssert - consider SoftAssertionsExtension - Andreas Dangel (@adangel)
- #5335: [kotlin] Prevent auxiliary grammars from generating lexers - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5336: [gherkin] Remove generated gherkin code from coverage report - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5337: [doc] Introducing PMD Guru on Gurubase.io - Kursat Aktas (@kursataktas)
- #5339: [java] Allow lambdas with unresolved target types to succeed inference - Clément Fournier (@oowekyala)
- #5340: [java] Fix #5097 - problem with unchecked conversion - Clément Fournier (@oowekyala)
- #5341: [java] Fix #5083 - UnusedPrivateMethod false positive with mref without target type but with exact method - Clément Fournier (@oowekyala)
- #5342: [julia] Ignore generated code in Julia module - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5345: [coco] Remove generated coco files form coverage - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5346: [typescript] Add cleanup after generating ts lexer - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5347: [tsql] Flag generated lexer as generated - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5352: [java] Add permitted subtypes to symbol API - Clément Fournier (@oowekyala)
- #5353: [java] Fix #5263 - UnnecessaryFullyQualifiedName FP with forward references - Clément Fournier (@oowekyala)
- #5354: [apex] Updated the docs for UnusedMethod as per discussion #5200 - samc-gearset (@sam-gearset)
- #5370: [java] Fix #5214 - LambdaCanBeMethodReference issue with method of enclosing class - Clément Fournier (@oowekyala)
- #5371: [doc] Improve docs on adding Antlr languages - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5372: [java] Fix #5315 - UnusedImport FP with import on demand - Clément Fournier (@oowekyala)
- #5373: [java] Fix #4763 - wrong message for SimplifyBooleanReturns - Clément Fournier (@oowekyala)
- #5374: [java] Fix #5070 - confusing argument to varargs method FP when types are unknown - Clément Fournier (@oowekyala)
📦 Dependency updates
- #5285: Bump pmd from 7.5.0 to 7.7.0
- #5288: Bump asm from 9.7 to 9.7.1
- #5290: Bump org.apache.maven.plugins:maven-assembly-plugin from 3.6.0 to 3.7.1
- #5301: Bump gems and bundler
- #5307: Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.2 to 3.4.0
- #5308: Bump webrick from 1.8.2 to 1.9.0 in /docs in the all-gems group across 1 directory
- #5312: Bump maven-pmd-plugin from 3.24.0 to 3.26.0
- #5316: Bump rouge from 4.4.0 to 4.5.0 in the all-gems group across 1 directory
- #5317: Bump org.apache.commons:commons-compress from 1.26.0 to 1.27.1
- #5348: Bump rouge from 4.5.0 to 4.5.1 in the all-gems group across 1 directory
- #5350: Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0
- #5356: Bump build-tools to 28
- #5357: Bump log4j.version from 2.23.0 to 2.24.2
- #5358: Bump org.apache.maven.plugins:maven-dependency-plugin from 3.7.1 to 3.8.1
- #5359: Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.1
- #5360: Bump io.github.apex-dev-tools:apex-ls_2.13 from 5.2.0 to 5.5.0
- #5361: Bump ant.version from 1.10.14 to 1.10.15
- #5362: Bump org.jetbrains:annotations from 24.1.0 to 26.0.1
- #5363: Bump com.puppycrawl.tools:checkstyle from 10.18.1 to 10.20.1
- #5364: Bump info.picocli:picocli from 4.7.5 to 4.7.6
- #5365: Bump com.github.hazendaz.maven:coveralls-maven-plugin from 4.5.0-M3 to 4.5.0-M5
- #5366: Bump org.mockito:mockito-core from 4.11.0 to 5.14.2
- #5367: Bump surefire.version from 3.2.5 to 3.5.2
- #5368: Bump org.junit.platform:junit-platform-suite from 1.11.2 to 1.11.3
📈 Stats
- 216 commits
- 55 closed tickets & PRs
- Days since last release: 35
25-October-2024 - 7.7.0
The PMD team is pleased to announce PMD 7.7.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🌟 Rule Changes
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
CPD can now ignore literals and identifiers in C++ code
When searching for duplicated code in C++ differences in literals or identifiers can be
ignored now (like in Java). This can be enabled via the command line options --ignore-literal
and --ignore-identifiers.
See PR #5040 for details.
🌟 Rule Changes
Changed Rules
SwitchStmtsShouldHaveDefault(Java Best Practices) doesn’t report empty switch statements anymore. To detect these, useEmptyControlStatement.UnitTestShouldUseAfterAnnotation(Java Best Practices) now also considers JUnit 5 and TestNG tests.UnitTestShouldUseBeforeAnnotation(Java Best Practices) now also considers JUnit 5 and TestNG tests.TooFewBranchesForSwitch(Java Performance) doesn’t report empty switches anymore. To detect these, useEmptyControlStatement.
Renamed Rules
- Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.
UnitTestAssertionsShouldIncludeMessage(Java Best Practices) has been renamed fromJUnitAssertionsShouldIncludeMessage.UnitTestContainsTooManyAsserts(Java Best Practices) has been renamed fromJUnitTestContainsTooManyAsserts.UnitTestShouldIncludeAssert(Java Best Practices) has been renamed fromJUnitTestsShouldIncludeAssert.UnitTestShouldUseAfterAnnotation(Java Best Practices) has been renamed fromJUnit4TestShouldUseAfterAnnotation.UnitTestShouldUseBeforeAnnotation(Java Best Practices) has been renamed fromJUnit4TestShouldUseBeforeAnnotation.UnitTestShouldUseTestAnnotation(Java Best Practices) has been renamed fromJUnit4TestShouldUseTestAnnotation.
- Several rules about switch statements and switch expression have been renamed, as they apply both to Switch Statements
and to Switch Expressions:
DefaultLabelNotLastInSwitch(Java Best Practices) has been renamed fromDefaultLabelNotLastInSwitchStmt.NonCaseLabelInSwitch(Java Error Prone) has been renamed fromNonCaseLabelInSwitchStatement.TooFewBranchesForSwitch(Java Performance) has been renamed fromTooFewBranchesForASwitchStatement.NonExhaustiveSwitch(Java Best Practices) has been renamed fromSwitchStmtsShouldHaveDefault.
The old rule names still work but are deprecated.
🐛 Fixed Issues
- apex-performance
- #5270: [apex] AvoidNonRestrictiveQueries when LIMIT is followed by bind expression
- java
- java-bestpractices
- java-codestyle
- #5253: [java] BooleanGetMethodName: False-negatives with
Booleanwrapper
- #5253: [java] BooleanGetMethodName: False-negatives with
- java-design
- #5030: [java] SwitchDensity false positive with pattern matching
- java-errorprone
- java-performance
🚨 API Changes
- java-bestpractices
- The old rule name
JUnit4TestShouldUseAfterAnnotationhas been deprecated. Use the new nameUnitTestShouldUseAfterAnnotationinstead. - The old rule name
JUnit4TestShouldUseBeforeAnnotationhas been deprecated. Use the new nameUnitTestShouldUseBeforeAnnotationinstead. - The old rule name
JUnit4TestShouldUseTestAnnotationhas been deprecated. Use the new nameUnitTestShouldUseTestAnnotationinstead. - The old rule name
JUnitAssertionsShouldIncludeMessagehas been deprecated. Use the new nameUnitTestAssertionsShouldIncludeMessageinstead. - The old rule name
JUnitTestContainsTooManyAssertshas been deprecated. Use the new nameUnitTestContainsTooManyAssertsinstead. - The old rule name
JUnitTestsShouldIncludeAsserthas been deprecated. Use the new nameUnitTestShouldIncludeAssertinstead. - The old rule name
DefaultLabelNotLastInSwitchStmthas been deprecated. Use the new nameDefaultLabelNotLastInSwitchinstead. - The old rule name
SwitchStmtsShouldHaveDefaulthas been deprecated. USe the new nameNonExhaustiveSwitchinstead.
- The old rule name
- java-errorprone
- The old rule name
NonCaseLabelInSwitchStatementhas been deprecated. Use the new nameNonCaseLabelInSwitchinstead.
- The old rule name
- java-performance
- The old rule name
TooFewBranchesForASwitchStatementhas been deprecated. Use the new nameTooFewBranchesForSwitchinstead.
- The old rule name
✨ Merged pull requests
- #4965: Fix #4532: [java] Rename JUnit rules with overly restrictive names - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5040: [cpp] Ignore literals and ignore identifiers capability to C++ CPD - Jakub Dupak (@jdupak)
- #5225: Fix #5067: [java] CloseResource: False positive for FileSystems.getDefault() - Lukas Gräf (@lukasgraef)
- #5241: Ignore javacc code in coverage report - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5245: [java] Improve UnitTestShouldUse{After,Before}Annotation rules to support JUnit5 and TestNG - Andreas Dangel (@adangel)
- #5247: Fix #5030: [java] SwitchDensity false positive with pattern matching - Andreas Dangel (@adangel)
- #5248: Fix #3362: [java] ImplicitSwitchFallThrough should consider switch expressions - Andreas Dangel (@adangel)
- #5251: Fix #5249 and #5250: [java] TooFewBranchesForSwitch ignore pattern matching and support switch expressions - Andreas Dangel (@adangel)
- #5252: Fix #4813: [java] SwitchStmtsShouldHaveDefault false positive with pattern matching - Andreas Dangel (@adangel)
- #5255: [java] Rename rule DefaultLabelNotLastInSwitch - Andreas Dangel (@adangel)
- #5256: Fix #5257: [java] NonCaseLabelInSwitch - support switch expressions - Andreas Dangel (@adangel)
- #5258: Ignore generated antlr classes in coverage reports - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5264: Fix #5261: [java] Fix NPE with empty pattern list - Clément Fournier (@oowekyala)
- #5267: [java] Rename rule SwitchStmtsShouldHaveDefault to NonExhaustiveSwitch - Andreas Dangel (@adangel)
- #5269: Fix #5253: [java] Support Boolean wrapper class for BooleanGetMethodName rule - Aryant Tripathi (@Aryant-Tripathi)
- #5273: Fix #5270: [apex] AvoidNonRestrictiveQueries: Fix regex for detecting LIMIT clause - Andreas Dangel (@adangel)
- #5275: Use plugin-classpath to simplify javacc-wrapper.xml - Andreas Dangel (@adangel)
- #5278: [java] CouplingBetweenObjects: improve violation message - Andreas Dangel (@adangel)
- #5279: Fix #5244: [java] UselessOperationOnImmutable: consider java.time.* types - Andreas Dangel (@adangel)
📦 Dependency updates
- #5234: Bump com.google.protobuf:protobuf-java from 3.25.3 to 4.28.2
- #5274: Bump org.junit from 5.8.2 to 5.11.2
- #5276: Bump org.checkerframework:checker-qual from 2.11.1 to 3.48.1
- #5280: Bump danger from 9.5.0 to 9.5.1 in the all-gems group across 1 directory
- #5281: Bump org.scala-lang:scala-reflect from 2.13.13 to 2.13.15
📈 Stats
- 98 commits
- 32 closed tickets & PRs
- Days since last release: 27
27-September-2024 - 7.6.0
The PMD team is pleased to announce PMD 7.6.0.
This is a minor release.
Table Of Contents
- 🚀 New and noteworthy
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ Merged pull requests
- 📦 Dependency updates
- 📈 Stats
🚀 New and noteworthy
New Git default branch - “main”
We are joining the Git community and updating “master” to “main”. Using the term “master” for the main
development branch can be offensive to some people. Existing versions of Git have been always capable of
working with any branch name and since 2.28.0 (July 2020) the default initial branch is configurable
(init.defaultBranch). Since October 2020, the default branch for new repositories on GitHub
is “main”. Finally, PMD will also use this new name for the main branch in all our own repositories.
Why “main”? PMD uses a very simple branching model - pull requests with feature branches and one main development branch, from which releases are created. That’s why “main” is currently the best fitting name.
More information:
- https://sfconservancy.org/news/2020/jun/23/gitbranchname/
- https://github.blog/changelog/2020-10-01-the-default-branch-for-newly-created-repositories-is-now-main/
What changes?
- We change the default branch on GitHub, so that pull requests are automatically created against
mainfrom now on. - If you have already a local clone of PMD’s repository, you’ll need to rename the old master branch locally:
git branch --move master main git fetch origin git branch --set-upstream-to=origin/main main git remote set-head origin --autoMore info: https://git-scm.com/book/en/v2/Git-Branching-Branch-Management#_changing_master and https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/renaming-a-branch#updating-a-local-clone-after-a-branch-name-changes
- If you created a fork on GitHub, you’ll need to change the default branch in your fork to
mainas well (Settings > Default Branch). - Some time after this release, we’ll delete the old master branch on GitHub. Then only
maincan be used. - This change is expanded to the other PMD repositories as well, e.g. pmd-designer and pmd-regression-tester.
🐛 Fixed Issues
- apex
- #5138: [apex] Various false-negatives since 7.3.0 when using triggers (ApexCRUDViolation, CognitiveComplexity, OperationWithLimitsInLoop)
- #5163: [apex] Parser error when using toLabel in SOSL query
- #5182: [apex] Parser error when using GROUPING in a SOQL query
- #5218: [apex] Parser error when using nested subqueries in SOQL
- #5228: [apex] Parser error when using convertCurrency() in SOQL
- core
- #5059: [core] xml output doesn’t escape CDATA inside its own CDATA
- #5201: [core] PMD sarif schema file points to nonexistent location
- #5222: [core] RuleReference/RuleSetWriter don’t handle changed default property values correctly
- #5229: [doc] CLI flag
--show-suppressedneeds to mention xml, html, summaryhtml
- java
- #5190: [java] NPE in type inference
- java-codestyle
- #5046: [java] LocalVariableCouldBeFinal false positive with try/catch
- java-errorprone
🚨 API Changes
No changes.
✨ Merged pull requests
- #5186: [java] Cleanup things about implicit classes - Clément Fournier (@oowekyala)
- #5188: [apex] Use new apex-parser 4.2.0 - Andreas Dangel (@adangel)
- #5191: [java] Fix #5046 - FPs in LocalVariableCouldBeFinal - Clément Fournier (@oowekyala)
- #5192: [java] Fix #5190 - NPE in type inference caused by null type - Clément Fournier (@oowekyala)
- #5195: [apex] Fix various FNs when using triggers - Andreas Dangel (@adangel)
- #5202: [core] Sarif format: refer to schemastore.org - David Schach (@dschach)
- #5208: [doc] Added Codety to “Tools / Integrations” - Tony (@random1223)
- #5210: [core] Fix PMD’s XMLRenderer to escape CDATA - Andreas Dangel (@adangel)
- #5211: Change branch master to main - Andreas Dangel (@adangel)
- #5212: [java] Adjust signature matching in CheckSkipResultRule - Juan Martín Sotuyo Dodero (@jsotuyod)
- #5223: [core] Fix RuleReference / RuleSetWriter handling of properties - Andreas Dangel (@adangel)
- #5224: [java] Fix #5068: Class incorrectly identified as non-instantiatable - Lukas Gräf (@lukasgraef)
- #5230: [doc] Documentation update for –show-suppressed flag - David Schach (@dschach)
- #5237: [apex] Support convertCurrency() in SOQL/SOSL - Andreas Dangel (@adangel)
📦 Dependency updates
- #5185: Bump checkstyle from 10.14.0 to 10.18.1
- #5187: Bump org.apache.maven.plugins:maven-install-plugin from 3.1.1 to 3.1.3
- #5199: Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.1 to 3.1.3
- #5216: Bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.20.0 to 0.23.0
- #5226: Bump rouge from 4.3.0 to 4.4.0 in the all-gems group across 1 directory
- #5227: Bump com.google.code.gson:gson from 2.10.1 to 2.11.0
- #5232: Bump com.google.protobuf:protobuf-java from 3.25.3 to 3.25.5
- #5233: Bump webrick from 1.8.1 to 1.8.2 in /docs
📈 Stats
- 60 commits
- 27 closed tickets & PRs
- Days since last release: 27
30-August-2024 - 7.5.0
The PMD team is pleased to announce PMD 7.5.0.
This is a minor release.
Table Of Contents
- 🚀 New: Java 23 Support
- 🌟 New Rules
- 🐛 Fixed Issues
- 🚨 API Changes
- ✨ External Contributions
- 📦 Dependency updates
- 📈 Stats
🚀 New: Java 23 Support
This release of PMD brings support for Java 23. There are no new standard language features, but a couple of preview language features:
- JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview)
- JEP 476: Module Import Declarations (Preview)
- JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview)
- JEP 482: Flexible Constructor Bodies (Second Preview)
Note that String Templates (introduced as preview in Java 21 and 22) are not supported anymore in Java 23, see JDK-8329949 for details.
In order to analyze a project with PMD that uses these preview language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 23-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-23-preview ...
Note: Support for Java 21 preview language features have been removed. The version “21-preview” are no longer available.
🌟 New Rules
- The new Java rule
AvoidSynchronizedStatementfinds synchronization blocks that could cause performance issues with virtual threads due to pinning. - The new JavaScript rule
AvoidConsoleStatementsfinds any function calls on the Console API (e.g.console.log). Using these in production code might negatively impact performance.
🐛 Fixed Issues
- apex-performance
- #5139: [apex] OperationWithHighCostInLoop: false negative for triggers
- java
- java-bestpractices
- #3602: [java] GuardLogStatement: False positive when compile-time constant is created from external constants
- #4731: [java] GuardLogStatement: Documentation is unclear why getters are flagged
- #5145: [java] UnusedPrivateMethod: False positive with method calls inside lambda
- #5151: [java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is a constant from another class
- #5152: [java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is “this”
- #5153: [java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is an array element
- java-design
- java-multithreading
- #5175: [java] Update AvoidSynchronizedAtMethodLevel message to mention ReentrantLock, new rule AvoidSynchronizedStatement
- javascript-performance
- #5105: [javascript] Prohibit any console methods
- plsql
- #5125: [plsql] Improve merge statement (order of merge insert/update flexible, allow prefixes in column names)
- plsql-bestpractices
- #5132: [plsql] TomKytesDespair: XPathException for more complex exception handler
🚨 API Changes
Deprecations
- pmd-jsp
JspParserImplis deprecated now. It should have been package-private because this is an implementation class that should not be used directly.
- pmd-plsql
MergeUpdateClausePrefixis deprecated. This production is not used anymore and will be removed. Note: The whole parser implementation class has been deprecated since 7.3.0, as it is supposed to be internalized.
- pmd-velocity
VtlParserImplis deprecated now. It should have been package-private because this is an implementation class that should not be used directly.
- pmd-visualforce
VfParserImplis deprecated now. It should have been package-private because this is an implementation class that should not be used directly.
Experimental
- pmd-java
✨ External Contributions
- #5125: [plsql] Improve merge statement (order of merge insert/update flexible, allow prefixes in column names) - Arjen Duursma (@duursma)
- #5175: [java] Update AvoidSynchronizedAtMethodLevel message to mention ReentrantLock, new rule AvoidSynchronizedStatement - Chas Honton (@chonton)
📦 Dependency updates
- #5100: Enable Dependabot
- #5141: Bump org.apache.maven.plugins:maven-checkstyle-plugin from 3.3.1 to 3.4.0
- #5142: Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0
- #5144: Bump org.codehaus.mojo:versions-maven-plugin from 2.16.2 to 2.17.1
- #5148: Bump org.apache.commons:commons-text from 1.11.0 to 1.12.0
- #5149: Bump org.apache.maven.plugins:maven-site-plugin from 4.0.0-M13 to 4.0.0-M16
- #5160: Bump org.pcollections:pcollections from 3.2.0 to 4.0.2
- #5161: Bump danger from 9.4.3 to 9.5.0 in the all-gems group across 1 directory
- #5164: Bump org.apache.maven.plugins:maven-dependency-plugin from 3.6.1 to 3.7.1
- #5165: Bump the all-gems group across 1 directory with 2 updates
- #5171: Bump net.bytebuddy:byte-buddy-agent from 1.14.12 to 1.14.19
- #5180: Bump net.sf.saxon:Saxon-HE from 12.4 to 12.5
📈 Stats
- 87 commits
- 25 closed tickets & PRs
- Days since last release: 35
26-July-2024 - 7.4.0
The PMD team is pleased to announce PMD 7.4.0.
This is a minor release.
Table Of Contents
🌟 New and changed rules
New Rules
- The new Apex rule
AvoidNonRestrictiveQueriesfinds SOQL and SOSL queries without a where or limit statement. This can quickly cause governor limit exceptions.
Changed rules
ClassNamingConventions(Apex Codestyle): Two new properties to configure different patterns for inner classes and interfaces:innerClassPatternandinnerInterfacePattern.
Renamed rules
InaccurateNumericLiteral(JavaScript Error Prone) has been renamed fromInnaccurateNumericLiteral. The old rule name still works but is deprecated.
🐛 Fixed Issues
- apex
- #5094: [apex] “No adapter exists for type” error message printed to stdout instead of stderr
- apex-bestpractices
- #5095: [apex] ApexUnitTestShouldNotUseSeeAllDataTrue false negative due to casing (regression in PMD 7)
- apex-codestyle
- #4800: [apex] ClassNamingConvention: Support naming convention for inner classes
- apex-performance
- #635: [apex] New Rule: Avoid soql/sosl queries without a where clause or limit statement
- java-bestpractices
- java-errorprone
- #1488: [java] MissingStaticMethodInNonInstantiatableClass: False positive with Lombok Builder on Constructor
- javascript-errorprone
- plsql
- #5086: [plsql] Fixed issue with missing optional table alias in MERGE usage
- #5087: [plsql] Add support for SQL_MACRO
- #5088: [plsql] Add support for ‘DEFAULT’ clause on the arguments of some oracle functions
- #5133: [plsql] AssertionError: Root of the tree should implement RootNode for a PL/SQL type declaration
- cli
- #5120: [cli] Can’t start designer under Windows
- core
- #5091: [core] PMD CPD v7.3.0 gives deprecation warning for skipLexicalErrors even when not used
🚨 API Changes
- javascript
- The old rule name
InnaccurateNumericLiteralhas been deprecated. Use the new nameInaccurateNumericLiteralinstead.
- The old rule name
✨ External Contributions
- #5048: [apex] Added Inner Classes to Apex Class Naming Conventions Rule - Justin Stroud (@justinstroudbah / @sgnl-labs)
- #5086: [plsql] Fixed issue with missing optional table alias in MERGE usage - Arjen Duursma (@duursma)
- #5087: [plsql] Add support for SQL_MACRO - Arjen Duursma (@duursma)
- #5088: [plsql] Add support for ‘DEFAULT’ clause on the arguments of some oracle functions - Arjen Duursma (@duursma)
- #5107: [doc] Update maven.md - Typo fixed for maven target - karthikaiyasamy (@karthikaiyasamy)
- #5109: [java] Exclude constructor with lombok.Builder for MissingStaticMethodInNonInstantiatableClass - Krzysztof Debski (@kdebski85)
- #5111: [java] Fix UnusedPrivateMethod for @lombok.Builder.ObtainVia - Krzysztof Debski (@kdebski85)
- #5118: [java] FP for UnusedPrivateMethod with Jakarta @PostConstruct/PreDestroy annotations - Krzysztof Debski (@kdebski85)
- #5121: [plsql] Fixed issue with missing optional table alias in MERGE usage - Arjen Duursma (@duursma)
📈 Stats
- 81 commits
- 32 closed tickets & PRs
- Days since last release: 27
28-June-2024 - 7.3.0
The PMD team is pleased to announce PMD 7.3.0.
This is a minor release.
Table Of Contents
🚀 New and noteworthy
✨ New Rules
- The new Java rule
UseEnumCollectionsreports usages forHashSetandHashMapwhen the keys are of an enum type. The specialized enum collections are more space- and time-efficient.
💥 pmd-compat6 removed (breaking)
The already deprecated PMD 6 compatibility module (pmd-compat6) has been removed. It was intended to be used with older versions of the maven-pmd-plugin, but since maven-pmd-plugin 3.22.0, PMD 7 is supported directly and this module is not needed anymore.
If you currently use this dependency (net.sourceforge.pmd:pmd-compat6), remove it and upgrade maven-pmd-plugin
to the latest version (3.23.0 or newer).
See also Maven PMD Plugin.
🐛 Fixed Issues
- cli
- #2827: [cli] Consider processing errors in exit status
- core
- apex
- apex-bestpractices
- #5000: [apex] UnusedLocalVariable FP with binds in SOSL / SOQL
- java
- java-bestpractices
- plsql
🚨 API Changes
CPD Report Format XML
There are some important changes:
- The XML format will now use an XSD schema, that is available at https://pmd.github.io/schema/cpd-report_1_0_0.xsd. This schema defines the valid elements and attributes that one can expect from a CPD report.
- The root element
pmd-cpdcontains the new attributespmdVersion,timestampandversion. The latter is the schema version and is currently “1.0.0”. - The CPD XML report will now also contain recoverable errors as additional
<error>elements.
See Report formats for CPD for an example.
The XML format should be compatible as only attributes and elements have been added. However, if you parse
the document with a namespace aware parser, you might encounter some issues like no elements being found.
In case the new format doesn’t work for you (e.g. namespaces, unexpected error elements), you can
go back using the old format with the renderer “xmlold” (XMLOldRenderer). Note, that
this old renderer is deprecated and only there for compatibility reasons. Whatever tooling is used to
read the XML format should be updated.
CLI
-
New exit code 5 introduced. PMD and CPD will exit now by default with exit code 5, if any recoverable error (e.g. parsing exception, lexing exception or rule exception) occurred. PMD will still create a report with all detected violations or duplications if recoverable errors occurred. Such errors mean, that the report might be incomplete, as either violations or duplications for an entire file or for a specific rule are missing. These cases can be considered as false-negatives.
In any case, the root cause should be investigated. If it’s a problem in PMD itself, please create a bug report.
-
New CLI parameter
--no-fail-on-errorto ignore such errors and not exit with code 5. By default, a build with errors will now fail and with that parameter, the previous behavior can be restored. This parameter is available for both PMD and CPD. -
The CLI parameter
--skip-lexical-errorsis deprecated. By default, lexical errors are skipped but the build is failed. Use the new parameter--[no-]fail-on-errorinstead to control whether to fail the build or not.
Ant
- CPDTask has a new parameter
failOnError. It controls, whether to fail the build if any recoverable error occurred. By default, the build will fail. CPD will still create a report with all detected duplications, but the report might be incomplete. - The parameter
skipLexicalErrorin CPDTask is deprecated and ignored. Lexical errors are now always skipped. Use the new parameterfailOnErrorinstead to control whether to fail the build or not.
Deprecated API
- pmd-ant
CPDTask#setSkipLexicalErrors: UsesetFailOnErrorinstead to control, whether to ignore errors or fail the build.
- pmd-core
CPDConfiguration#isSkipLexicalErrorsandsetSkipLexicalErrors: UsesetFailOnErrorto control whether to ignore errors or fail the build.net.sourceforge.pmd.cpd.XMLOldRenderer(the CPD format “xmlold”).- The constructor
AntlrToken#AntlrTokenshouldn’t be used directly. UseAntlrTokenManagerinstead.
- pmd-java
ASTResource#getStableNameand the corresponding attribute@StableName.ASTRecordPattern#getVarIdThis method was added here by mistake. Record patterns don’t declare a pattern variable for the whole pattern, but rather for individual record components, which can be accessed viagetComponentPatterns.
- pmd-plsql
PLSQLParserImplis deprecated now. It should have been package-private because this is an implementation class that should not be used directly.- The node
ASTKEYWORD_UNRESERVEDis deprecated and is now removed from the AST.
Breaking changes: pmd-compat6 removed
The already deprecated PMD 6 compatibility module (pmd-compat6) has been removed. See above for details.
📈 Stats
- 88 commits
- 32 closed tickets & PRs
- Days since last release: 27
31-May-2024 - 7.2.0
The PMD team is pleased to announce PMD 7.2.0.
This is a minor release.
Table Of Contents
🚀 New and noteworthy
Collections exposed as XPath attributes
Up to now, all AST node getters would be exposed to XPath, as long as the return type was a primitive (boxed or unboxed), String or Enum. That meant that collections, even of these basic types, were not exposed, so for instance accessing Apex’s ASTUserClass.getInterfaceNames() to list the interfaces implemented by a class was impossible from XPath, and would require writing a Java rule to check it.
Since this release, PMD will also expose any getter returning a collection of any supported type as a sequence through an XPath attribute. They would require to use apropriate XQuery functions to manipulate the sequence. So for instance, to detect any given ASTUserClass in Apex that implements Queueable, it is now possible to write:
/UserClass[@InterfaceNames = 'Queueable']
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog (7.2.0).
🐛 Fixed Issues
- core
- java
- #4912: [java] Unable to parse some Java9+ resource references
- #4973: [java] Stop parsing Java for CPD
- #4980: [java] Bad intersection, unrelated class types java.lang.Object[] and java.lang.Number
- #4988: [java] Fix impl of ASTVariableId::isResourceDeclaration / VariableId/@ResourceDeclaration
- #4990: [java] Add an attribute @PackageQualifier to ASTClassType
- #5006: [java] Bad intersection, unrelated class types Child and Parent<? extends Child>
- #5029: [java] PMD 7.x throws stack overflow in TypeOps$ProjectionVisitor while parsing a Java class
- java-bestpractices
- #4278: [java] UnusedPrivateMethod FP with Junit 5 @MethodSource and default factory method name
- #4852: [java] ReplaceVectorWithList false-positive (neither Vector nor List usage)
- #4975: [java] UnusedPrivateMethod false positive when using @MethodSource on a @Nested test
- #4985: [java] UnusedPrivateMethod false-positive / method reference in combination with custom object
- java-codestyle
- #1619: [java] LocalVariableCouldBeFinal on ‘size’ variable in for loop
- #3122: [java] LocalVariableCouldBeFinal should consider blank local variables
- #4903: [java] UnnecessaryBoxing, but explicit conversion is necessary
- #4924: [java] UnnecessaryBoxing false positive in PMD 7.0.0 in lambda
- #4930: [java] EmptyControlStatement should not allow empty try with concise resources
- #4954: [java] LocalVariableNamingConventions should allow unnamed variables by default
- #5028: [java] FormalParameterNamingConventions should accept unnamed parameters by default
- java-errorprone
- java-multithreading
- #2368: [java] False positive UnsynchronizedStaticFormatter in static initializer
🚨 API Changes
Deprecated API
- pmd-java
ASTResource#getStableNameand the corresponding attribute@StableName
✨ External Contributions
📈 Stats
- 152 commits
- 46 closed tickets & PRs
- Days since last release: 35
26-April-2024 - 7.1.0
The PMD team is pleased to announce PMD 7.1.0.
This is a minor release.
Table Of Contents
🚀 New and noteworthy
More robust CPD reports
There were a number of circumstances, specially around (but not limited to) literal sequences, were CPD would report duplicate overlapping or partially overlapping matches. These have now been fixed, and CPD will report only the longest non-overlapping duplicate.
These improvements apply to all supported languages, irrespective of supported flags.
✨ New Rules
- The new Java rule
UnnecessaryVarargsArrayCreationreports explicit array creation when a varargs is expected. This is more heavy to read and could be simplified. - The new Java rule
ConfusingArgumentToVarargsMethodreports some confusing situations where a varargs method is called with an inexact argument type. These may end up in a mismatch between the expected parameter type and the actual value. - The new Java rule
LambdaCanBeMethodReferencereports lambda expressions that can be replaced with a method reference. Please read the documentation of the rule for more info. This rule is now part of the Quickstart ruleset.
🌟 Rule Changes
JUnitTestsShouldIncludeAssertandJUnitTestContainsTooManyAssertshave a new property namedextraAssertMethodNames. With this property, you can configure which additional static methods should be considered as valid verification methods. This allows to use custom mocking or assertion libraries.
🐛 Fixed Issues
- core
- cli
- doc
- #4901: [doc] Improve documentation on usage of violationSuppressXPath
- apex
- #4418: [apex] ASTAnnotation.getImage() does not return value as written in the class
- apex-errorprone
- #3953: [apex] EmptyCatchBlock false positive with formal (doc) comments
- cpp
- #2438: [cpp] Repeated Duplication blocks
- java
- java-bestpractices
- #1084: [java] Allow JUnitTestsShouldIncludeAssert to configure verification methods
- #3216: [java] New rule: UnnecessaryVarargsArrayCreation
- #4435: [java] [7.0-rc1] UnusedAssignment for used field
- #4569: [java] ForLoopCanBeForeach reports on loop
for (int i = 0; i < list.size(); i += 2) - #4618: [java] UnusedAssignment false positive with conditional assignments of fields
- java-codestyle
- #4602: [java] UnnecessaryImport: false positives with static imports
- #4785: [java] False Positive: PMD Incorrectly report violation for UnnecessaryImport
- #4779: [java] Examples in documentation of MethodArgumentCanBeFinal do not trigger the rule
- #4881: [java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0)
- java-design
- java-errorprone
- #2056: [java] CloseResource false-positive with URLClassLoader in cast expression
- #4751: [java] PMD crashes when analyzing CloseResource Rule
- #4928: [java] EmptyCatchBlock false negative when allowCommentedBlocks=true
- #4948: [java] ImplicitSwitchFallThrough: False-positive with nested switch statements
- java-performance
- pom-errorprone
- #4388: [pom] InvalidDependencyTypes doesn’t consider dependencies at all
- misc
- #4967: Fix reproducible build issues with 7.0.0
🚨 API Changes
Deprecated methods
- pmd-java
ASTLambdaExpression#getBlockandASTLambdaExpression#getExpressionSingularFieldRule#mayBeSingularhas been deprecated for removal. The method is only useful for the rule itself and shouldn’t be used otherwise.
✨ External Contributions
- #4864: Fix #1084 [Java] add extra assert method names to Junit rules - Erwan Moutymbo (@emouty)
- #4894: Fix #4791 Error caused by space in JDK path - Scrates1 (@Scrates1)
📈 Stats
- 205 commits
- 71 closed tickets & PRs
- Days since last release: 34
22-March-2024 - 7.0.0
🎉 After a long time, we’re excited to bring you now the next major version of PMD! 🎉
Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate page with the full Detailed Release Notes for PMD 7.0.0.
🤝🙏 Many thanks to all users and contributors who were testing the release candidates and provided feedback and/or PRs!
✨ PMD 7…
- …has a new logo
- …analyzes Java 21 and Java 22 projects with even better type resolution and symbol table support
- …analyzes Kotlin and Swift
- …analyzes Apex with a new parser
- …finds duplicated code in Coco, Julia, TypeScript
- …ships 11 new rules and tons of improvements for existing rules
- …provides a new CLI interface with progress bar
- …supports Antlr based languages
- …and many more enhancements
💥 Note: Since PMD 7 is a major release, it is not a drop-in replacement for PMD 6.55.0. A detailed documentation of required changes are available in the Migration Guide for PMD 7.
Expand to see Release Notes
Table Of Contents
- Changes since 7.0.0-rc4
- 🚀 Major Features and Enhancements
- 🎉 Language Related Changes
- New: CPD support for Apache Velocity Template Language (VTL)
- New: CPD support for Coco
- New: CPD support for Julia
- New: CPD support for TypeScript
- New: Java 21 and 22 Support
- New: Kotlin support
- New: Swift support
- Changed: Apex Support: Replaced Jorje with fully open source front-end
- Changed: CPP can now ignore identifiers in sequences (CPD)
- Changed: Groovy Support (CPD)
- Changed: HTML support
- Changed: JavaScript support
- Changed: Language versions
- Changed: Rule properties
- Changed: Velocity Template Language (VTL)
- Changed: Visualforce
- 🌟 New and changed rules
- 🚨 API
- 💥 Compatibility and migration notes
- 🐛 Fixed Issues
- ✨ External Contributions
- 📈 Stats
Changes since 7.0.0-rc4
This section lists the most important changes from the last release candidate. The remaining section describes the complete release notes for 7.0.0.
New and Noteworthy
Maven PMD Plugin compatibility with PMD 7
In order to use PMD 7 with maven-pmd-plugin a new compatibility module has been created. This allows to use PMD 7 by simply adding one additional dependency:
- Follow the guide Upgrading PMD at Runtime
- Add additionally the following dependency:
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-compat6</artifactId>
<version>${pmdVersion}</version>
</dependency>
It is important to add this dependency as the first in the list, so that maven-pmd-plugin sees the (old) compatible versions of some classes.
This module is available beginning with version 7.0.0-rc4 and will be there at least for the first final version PMD 7 (7.0.0). It’s not decided yet, whether we will keep updating it, after PMD 7 is finally released.
Note: This compatibility module only works for the built-in rules, that are still available in PMD 7. E.g. you need to review your rulesets and look out for deprecated rules and such. See the use case I’m using only built-in rules in the Migration Guide for PMD 7.
As PMD 7 revamped the Java module, if you have custom rules, you need to migrate these rules. See the use case I’m using custom rules in the Migration Guide.
Note: Once the default version of PMD is upgraded to PMD7 in maven-pmd-plugin (see MPMD-379), this compatibility module is no longer needed. The module pmd-compat6 might not be maintained then any further, hence it is already declared as deprecated.
No guarantee is given, that the (deprecated) module pmd-compat6 is being maintained over the whole lifetime of PMD 7.
Java 22 Support
This release of PMD brings support for Java 22. There are the following new standard language features, that are supported now:
PMD also supports the following preview language features:
- JEP 447: Statements before super(…) (Preview)
- JEP 459: String Templates (Second Preview)
- JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
In order to analyze a project with PMD that uses these language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 22-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-22-preview ...
Note: Support for Java 20 preview language features have been removed. The version “20-preview” is no longer available.
Swift Support
- limited support for Swift 5.9 (Macro Expansions)
Groovy Support (CPD)
- We now support parsing all Groovy features from Groovy 3 and 4.
- We now support suppression through
CPD-ON/CPD-OFFcomment pairs. - See PR #4726 for details.
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. The designer artifact has been renamed from “pmd-ui” to “pmd-designer”. While the designer still works with Java 8, the recommended Java Runtime is Java 11 (or later) with OpenJFX 17 (or later).
For the detailed changes, see PMD Designer Changelog (7.0.0).
Apex Support: Replaced Jorje with fully open source front-end
When PMD added Apex support with version 5.5.0, it utilized the Apex Jorje library to parse Apex source and generate an AST. This library is however a binary-blob provided as part of the Salesforce Extensions for VS Code, and it is closed-source.
This causes problems, if binary blobs are not allowed by e.g. a company-wide policy. In that case, the Jorje library prevented that PMD Apex could be used at all.
Also having access to the source code, enhancements and modifications are easier to do.
Under the hood, we use two open source libraries instead:
- apex-parser originally by Kevin Jones (@nawforce). This project provides the grammar for a ANTLR based parser.
- Summit-AST by Google (@google) This project translates the ANTLR parse tree into an AST, that is similar to the AST Jorje provided. Note: This is not an official Google product.
Although the parser is completely switched, there are only little known changes to the AST. These are documented in the Migration Guide for PMD 7: Apex AST.
With the new Apex parser, the new language constructs like
User Mode Database Operations
and the new Null Coalescing Operator ??
can be parsed now. PMD should be able to parse Apex code up to version 60.0 (Spring ‘24).
See #3766 for details.
Contributors: Aaron Hurst (@aaronhurst-google), Edward Klimoshenko (@eklimo)
Changed: Visualforce
There was an inconsistency between the naming of the maven module and the language id. The language id used the abbreviation “vf”, while the maven module used the longer name “visualforce”. This has been solved by renaming the language module to its full name “visualforce”. The java packages have been renamed as well.
If you import rules, you also need to adjust the paths, e.g.
category/vf/security.xml➡️category/visualforce/security.xml
Changed: HTML support
Support for HTML was introduced in PMD 6.55.0 as an experimental feature. With PMD 7.0.0 this is now considered stable.
Changed: Kotlin support
Support for Kotlin was introduced with PMD 7.0.0-rc1 as an experimental feature. With PMD 7.0.0 this is now considered stable.
Changed: Velocity Template Language (VTL)
The module was named just “vm” which was not a good name. Its module name, language id and package names have been renamed to “velocity”.
If you import rules, you also need to adjust the paths, e.g.
category/vm/...➡️category/velocity/...
Rule Changes
New Rules
OperationWithHighCostInLoopfinds Schema class methods called in a loop, which is a potential performance issue.UseExplicitTypesreports usages ofvarkeyword, which was introduced with Java 10.MissingEncodingfinds XML files without explicit encoding.
Changed Rules
EmptyControlStatement: The rule has a new property to allow empty blocks when they contain a comment (allowCommentedBlocks).MethodNamingConventions: The deprecated rule propertyskipTestMethodUnderscoreshas been removed. It was actually deprecated since PMD 6.15.0, but was not mentioned in the release notes back then. Use the propertytestPatterninstead to configure valid names for test methods.CommentRequired: The deprecated propertyheaderCommentRequirementhas been removed. Use the propertyclassCommentRequirementinstead.NonSerializableClass: The deprecated propertyprefixhas been removed without replacement. In a serializable class all fields have to be serializable regardless of the name.
Renamed Rulesets
category/vf/security.xml➡️category/visualforce/security.xmlcategory/vm/bestpractices.xml➡️category/velocity/bestpractices.xmlcategory/vm/design.xml➡️category/velocity/design.xmlcategory/vm/errorprone.xml➡️category/velocity/errorprone.xml
Removed Rules
The following previously deprecated rules have been finally removed:
- Apex
- performance.xml/AvoidSoqlInLoops (deleted) ➡️ use
OperationWithLimitsInLoop - performance.xml/AvoidSoslInLoops (deleted) ➡️ use
OperationWithLimitsInLoop - performance.xml/AvoidDmlStatementsInLoops (deleted) ➡️ use
OperationWithLimitsInLoop
- performance.xml/AvoidSoqlInLoops (deleted) ➡️ use
- Java
- design.xml/ExcessiveClassLength (deleted) ➡️ use
NcssCount - design.xml/ExcessiveMethodLength (deleted) ➡️ use
NcssCount - errorprone.xml/BeanMembersShouldSerialize (deleted) ➡️ use
NonSerializableClass - errorprone.xml/EmptyFinallyBlock (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyIfStmt (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyInitializer (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyStatementBlock (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyStatementNotInLoop (deleted) ➡️ use
UnnecessarySemicolon - errorprone.xml/EmptySwitchStatements (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptySynchronizedBlock (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyTryBlock (deleted) ➡️ use
EmptyControlStatement - errorprone.xml/EmptyWhileStmt (deleted) ➡️ use
EmptyControlStatement
- design.xml/ExcessiveClassLength (deleted) ➡️ use
Removed deprecated rulesets
The following previously deprecated rulesets have been removed. These were the left-over rulesets from PMD 5. The rules have been moved into categories with PMD 6.
List of deprecated rulesets
- rulesets/apex/apexunit.xml
- rulesets/apex/braces.xml
- rulesets/apex/complexity.xml
- rulesets/apex/empty.xml
- rulesets/apex/metrics.xml
- rulesets/apex/performance.xml
- rulesets/apex/ruleset.xml
- rulesets/apex/securty.xml
- rulesets/apex/style.xml
- rulesets/java/android.xml
- rulesets/java/basic.xml
- rulesets/java/clone.xml
- rulesets/java/codesize.xml
- rulesets/java/comments.xml
- rulesets/java/controversial.xml
- rulesets/java/coupling.xml
- rulesets/java/design.xml
- rulesets/java/empty.xml
- rulesets/java/finalizers.xml
- rulesets/java/imports.xml
- rulesets/java/j2ee.xml
- rulesets/java/javabeans.xml
- rulesets/java/junit.xml
- rulesets/java/logging-jakarta-commons.xml
- rulesets/java/logging-java.xml
- rulesets/java/metrics.xml
- rulesets/java/migrating.xml
- rulesets/java/migrating_to_13.xml
- rulesets/java/migrating_to_14.xml
- rulesets/java/migrating_to_15.xml
- rulesets/java/migrating_to_junit4.xml
- rulesets/java/naming.xml
- rulesets/java/optimizations.xml
- rulesets/java/strictexception.xml
- rulesets/java/strings.xml
- rulesets/java/sunsecure.xml
- rulesets/java/typeresolution.xml
- rulesets/java/unnecessary.xml
- rulesets/java/unusedcode.xml
- rulesets/ecmascript/basic.xml
- rulesets/ecmascript/braces.xml
- rulesets/ecmascript/controversial.xml
- rulesets/ecmascript/unnecessary.xml
- rulesets/jsp/basic.xml
- rulesets/jsp/basic-jsf.xml
- rulesets/plsql/codesize.xml
- rulesets/plsql/dates.xml
- rulesets/plsql/strictsyntax.xml
- rulesets/plsql/TomKytesDespair.xml
- rulesets/vf/security.xml
- rulesets/vm/basic.xml
- rulesets/pom/basic.xml
- rulesets/xml/basic.xml
- rulesets/xsl/xpath.xml
- rulesets/releases/*
Fixed issues
- cli
- core
- #1027: [core] Apply the new PropertyDescriptor<Pattern> type where applicable
- #3903: [core] Consolidate
n.s.pmd.reportingpackage - #3905: [core] Stabilize tree export API
- #3917: [core] Consolidate
n.s.pmd.lang.rulepackage - #4065: [core] Rename TokenMgrError to LexException, Tokenizer to CpdLexer
- #4309: [core] Cleanups in XPath area
- #4312: [core] Remove unnecessary property
colorand system propertypmd.colorinTextColorRenderer - #4313: [core] Remove support for <lang>-<ruleset> hyphen notation for ruleset references
- #4314: [core] Remove ruleset compatibility filter (RuleSetFactoryCompatibility) and CLI option
--no-ruleset-compatibility - #4348: [core] Consolidate @InternalApi classes
- #4349: [core] Cleanup remaining experimental and deprecated API
- #4378: [core] Ruleset loading processes commented rules
- #4674: [core] WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass
- #4694: [core] Fix line/col numbers in TokenMgrError
- #4717: [core] XSLTRenderer doesn’t close report file
- #4750: [core] Fix flaky SummaryHTMLRenderer
- #4782: [core] Avoid using getImage/@Image
- doc
- #995: [doc] Document API evolution principles as ADR
- #2511: [doc] Review guides for writing java/xpath rules for correctness with PMD 7
- #3175: [doc] Document language module features
- #4308: [doc] Document XPath API @DeprecatedAttribute
- #4319: [doc] Document TypeRes API and Symbols API
- #4659: [doc] Improve ant documentation
- #4669: [doc] Add bld PMD Extension to Tools / Integrations
- #4676: [doc] Clarify how CPD
--ignore-literalsand--ignore-identifierswork - #4704: [doc] Multivalued properties do not accept | as a separator
- miscellaneous
- #4699: Make PMD buildable with java 21
- #4586: Use explicit encoding in ruleset xml files
- #4642: Update regression tests with Java 21 language features
- #4736: [ci] Improve build procedure
- #4741: Add pmd-compat6 module for maven-pmd-plugin
- #4749: Fixes NoSuchMethodError on processing errors in pmd-compat6
- #4776: [ci] Upgrade to ruby 3
- #4796: Remove deprecated and release rulesets
- #4823: Update to use renamed pmd-designer
- #4827: [compat6] Support config errors and cpd for csharp
- #4830: Consolidate packages in each maven module
- #4867: [dist] ./mvnw command not found in dist-src
- apex
- apex-bestpractices
- #4556: [apex] UnusedLocalVariable flags for variables which are using in SOQL/SOSL binds
- apex-documentation
- #4774: [apex] ApexDoc false-positive for the first method of an annotated Apex class
- apex-performance
- #4675: [apex] New Rule: OperationWithHighCostInLoop
- groovy
- #4726: [groovy] Support Groovy to 3 and 4 and CPD suppressions
- java
- java-bestpractices
- java-codestyle
- #2847: [java] New Rule: Use Explicit Types
- #4239: [java] UnnecessaryLocalBeforeReturn - false positive with catch clause
- #4578: [java] CommentDefaultAccessModifier comment needs to be before annotation if present
- #4631: [java] UnnecessaryFullyQualifiedName fails to recognize illegal self reference in enums
- #4645: [java] CommentDefaultAccessModifier - False Positive with JUnit5’s ParameterizedTest
- #4754: [java] EmptyControlStatementRule: Add allowCommentedBlocks property
- #4816: [java] UnnecessaryImport false-positive on generic method call with on lambda
- java-design
- #174: [java] SingularField false positive with switch in method that both assigns and reads field
- java-errorprone
- #718: [java] BrokenNullCheck false positive with parameter/field confusion
- #932: [java] SingletonClassReturningNewInstance false positive with double assignment
- #1831: [java] DetachedTestCase reports abstract methods
- #4719: [java] UnnecessaryCaseChange: example doc toUpperCase() should compare to a capitalized string
- javascript
- plsql
- #4820: [plsql] WITH clause is ignored for SELECT INTO statements
- swift
- #4697: [swift] Support Swift 5.9 features (mainly macros expansion expressions)
- xml-bestpractices
- #4592: [xml] Add MissingEncoding rule
API Changes
See Detailed Release Notes for PMD 7.
External Contributions
- #4093: [apex] Summit-AST Apex module - Part 1 - Edward Klimoshenko (@eklimo)
- #4151: [apex] Summit-AST Apex module - Part 2 - expression nodes - Aaron Hurst (@aaronhurst-google)
- #4171: [apex] Summit-AST Apex module - Part 3 - initializers - Aaron Hurst (@aaronhurst-google)
- #4206: [apex] Summit-AST Apex module - Part 4 - statements - Aaron Hurst (@aaronhurst-google)
- #4219: [apex] Summit-AST Apex module - Part 5 - annotations, triggers, misc. - Aaron Hurst (@aaronhurst-google)
- #4242: [apex] Merge 6.52 into experimental-apex-parser - Aaron Hurst (@aaronhurst-google)
- #4251: [apex] Summit-AST Apex module - Part 6 Passing testsuite - Aaron Hurst (@aaronhurst-google)
- #4448: [apex] Bump summit-ast to new release 2.1.0 (and remove workaround) - Aaron Hurst (@aaronhurst-google)
- #4479: [apex] Merge main (7.x) branch into experimental-apex-parser and fix tests - Aaron Hurst (@aaronhurst-google)
- #4562: [apex] Fixes #4556 - Update Apex bind regex match for all possible combinations - nwcm (@nwcm)
- #4640: [cli] Launch script fails if run via “bash pmd” - Shai Bennathan (@shai-bennathan)
- #4673: [javascript] CPD: Added support for decorator notation - Wener (@wener-tiobe)
- #4677: [apex] Add new rule: OperationWithHighCostInLoop - Thomas Prouvot (@tprouvot)
- #4698: [swift] Add macro expansion support for swift 5.9 - Richard B. (@kenji21)
- #4706: [java] DetachedTestCase should not report on abstract methods - Debamoy Datta (@Debamoy)
- #4719: [java] UnnecessaryCaseChange: example doc toUpperCase() should compare to a capitalized string - ciufudean (@ciufudean)
- #4738: [doc] Added reference to the PMD extension for bld - Erik C. Thauvin (@ethauvin)
- #4749: Fixes NoSuchMethodError on processing errors in pmd-compat6 - Andreas Bergander (@bergander)
- #4750: [core] Fix flaky SummaryHTMLRenderer - 219sansim (@219sansim)
- #4752: [core] Fix flaky LatticeRelationTest - 219sansim (@219sansim)
- #4754: [java] EmptyControlStatementRule: Add allowCommentedBlocks property - Andreas Bergander (@bergander)
- #4759: [java] fix: remove delimiter attribute from ruleset category/java/errorprone.xml - Marcin Dąbrowski (@marcindabrowski)
- #4825: [plsql] Fix ignored WITH clause for SELECT INTO statements - Laurent Bovet (@lbovet)
- #4857: [javascript] Fix UnnecessaryBlock issues with empty statements - Oleksandr Shvets (@oleksandr-shvets)
🚀 Major Features and Enhancements
New official logo
The new official logo of PMD:

For more information, see the Detailed Release Notes for PMD 7.
Revamped Java module
- Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS)
- Built-in rules have been upgraded for the changed AST
- Rewritten type resolution framework and symbol table correctly implements the JLS
- AST exposes more semantic information (method calls, field accesses)
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Clément Fournier (@oowekyala), Andreas Dangel (@adangel), Juan Martín Sotuyo Dodero (@jsotuyod)
Revamped Command Line Interface
- Unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities
- Single script
pmd(pmd.batfor Windows) to launch the different utilities:pmd checkto run PMD rules and analyze a projectpmd cpdto run CPD (copy paste detector)pmd designerto run the PMD Rule Designer
- Progress bar support for
pmd check - Shell completion

For more information, see the Detailed Release Notes for PMD 7.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Full Antlr support
- Antlr based grammars can now be used to build full-fledged PMD rules.
- Previously, Antlr grammar could only be used for CPD
- New supported languages: Swift and Kotlin
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. The designer artifact has been renamed from “pmd-ui” to “pmd-designer”. While the designer still works with Java 8, the recommended Java Runtime is Java 11 (or later) with OpenJFX 17 (or later).
For the detailed changes, see
- PMD Designer Changelog (7.0.0).
- PMD Designer Changelog (7.0.0-rc4).
- PMD Designer Changelog (7.0.0-rc1).
New CPD report format cpdhtml-v2.xslt
Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. It uses an XSLT stylesheet to convert CPD’s XML format into HTML.
See the example report.
Contributors: Mohan Chinnappan (@mohan-chinnappan-n)
🎉 Language Related Changes
Note that this is just a concise listing of the highlights. For more information on the languages, see the Detailed Release Notes for PMD 7.
New: CPD support for Apache Velocity Template Language (VTL)
PMD supported Apache Velocity for a very long time, but the CPD integration never got finished.
This is now done and CPD supports Apache Velocity Template language for detecting copy and paste.
It is shipped in the module pmd-velocity.
New: CPD support for Coco
Thanks to a contribution, CPD now supports Coco, a modern programming language
designed specifically for building event-driven software. It is shipped in the new
module pmd-coco.
Contributors: Wener (@wener-tiobe)
New: CPD support for Julia
Thanks to a contribution, CPD now supports the Julia language. It is shipped
in the new module pmd-julia.
Contributors: Wener (@wener-tiobe)
New: CPD support for TypeScript
Thanks to a contribution, CPD now supports the TypeScript language. It is shipped
with the rest of the JavaScript support in the module pmd-javascript.
Contributors: Paul Guyot (@pguyot)
New: Java 21 and 22 Support
This release of PMD brings support for Java 21 and 22. There are the following new standard language features, that are supported now:
- JEP 456: Unnamed Variables & Patterns (Java 22)
- JEP 440: Record Patterns (Java 21)
- JEP 441: Pattern Matching for switch (Java 21)
PMD also supports the following preview language features:
- JEP 447: Statements before super(…) (Preview) (Java 22)
- JEP 459: String Templates (Second Preview) (Java 21 and 22)
- JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview) (Java 21 and 22)
In order to analyze a project with PMD that uses these preview language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 22-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-22-preview ...
Note: Support for Java 19 and Java 20 preview language features have been removed. The versions “19-preview” and “20-preview” are no longer available.
New: Kotlin support
- Use PMD to analyze Kotlin code with PMD rules.
- Support for Kotlin 1.8 grammar
- Initially 2 built-in rules
- Support for Kotlin was introduced with PMD 7.0.0-rc1 as an experimental feature. With PMD 7.0.0 this is now considered stable.
Contributors: Jeroen Borgers (@jborgers), Peter Paul Bakker (@stokpop)
New: Swift support
- Use PMD to analyze Swift code with PMD rules.
- Limited support for Swift 5.9 (Macro Expansions)
- Initially 4 built-in rules
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
Changed: Apex Support: Replaced Jorje with fully open source front-end
When PMD added Apex support with version 5.5.0, it utilized the Apex Jorje library to parse Apex source and generate an AST. This library is however a binary-blob provided as part of the Salesforce Extensions for VS Code, and it is closed-source.
This causes problems, if binary blobs are not allowed by e.g. a company-wide policy. In that case, the Jorje library prevented that PMD Apex could be used at all.
Also having access to the source code, enhancements and modifications are easier to do.
Under the hood, we use two open source libraries instead:
- apex-parser by Kevin Jones (@nawforce) This project provides the grammar for a ANTLR based parser.
- Summit-AST by Google (@google) This project translates the ANTLR parse tree into an AST, that is similar to the AST Jorje provided. Note: This is not an official Google product.
Although the parsers is completely switched, there are only little known changes to the AST.
These are documented in the Migration Guide for PMD 7: Apex AST.
With the new Apex parser, the new language constructs like
User Mode Database Operations
and the new Null Coalescing Operator ??
can be parsed now. PMD should be able to parse Apex code up to version 60.0 (Spring ‘24).
See #3766 for details.
Contributors: Aaron Hurst (@aaronhurst-google), Edward Klimoshenko (@eklimo)
Changed: CPP can now ignore identifiers in sequences (CPD)
- New command line option for CPD:
--ignore-sequences. - This option is used for CPP only: with the already existing option
--ignore-literal-sequences, only literals were ignored. The new option additionally ignores identifiers as well in sequences. - See PR #4470 for details.
Contributors: Wener (@wener-tiobe)
Changed: Groovy Support (CPD)
- We now support parsing all Groovy features from Groovy 3 and 4.
- We now support suppression through
CPD-ON/CPD-OFFcomment pairs. - See PR #4726 for details.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Changed: HTML support
Support for HTML was introduced in PMD 6.55.0 as an experimental feature. With PMD 7.0.0 this is now considered stable.
Changed: JavaScript support
- Latest version supports ES6 and also some new constructs (see Rhino)
- Comments are retained
Changed: Language versions
- More predefined language versions for each supported language
- Can be used to limit rule execution for specific versions only with
minimumLanguageVersionandmaximumLanguageVersionattributes.
Changed: Rule properties
- The old deprecated classes like
IntPropertyandStringPropertyhave been removed. Please usePropertyFactoryto create properties. - All properties which accept multiple values now use a comma (
,) as a delimiter. The previous default was a pipe character (|). The delimiter is not configurable anymore. If needed, the comma can be escaped with a backslash. - The
minandmaxattributes in property definitions in the XML are now optional and can appear separately or be omitted.
Changed: Velocity Template Language (VTL)
The module was named just “vm” which was not a good name. Its module name, language id and package names have been renamed to “velocity”.
If you import rules, you also need to adjust the paths, e.g.
category/vm/...➡️category/velocity/...
Changed: Visualforce
There was an inconsistency between the naming of the maven module and the language id. The language id used the abbreviation “vf”, while the maven module used the longer name “visualforce”. This has been solved by renaming the language module to its full name “visualforce”. The java packages have been renamed as well.
If you import rules, you also need to adjust the paths, e.g.
category/vf/security.xml➡️category/visualforce/security.xml
🌟 New and changed rules
New Rules
Apex
OperationWithHighCostInLoopfinds Schema class methods called in a loop, which is a potential performance issue.UnusedMethodfinds unused methods in your code.
Java
UnnecessaryBoxingreports boxing and unboxing conversions that may be made implicit.UseExplicitTypesreports usages ofvarkeyword, which was introduced with Java 10.
Kotlin
FunctionNameTooShortfinds functions with a too short name.OverrideBothEqualsAndHashcodefinds classes with only eitherequalsorhashCodeoverridden, but not both. This leads to unexpected behavior once instances of such classes are used in collections (Lists, HashMaps, …).
Swift
ForceCastflags all force casts, making sure you are defensively considering all types. Having the application crash shouldn’t be an option.ForceTryflags all force tries, making sure you are defensively handling exceptions. Having the application crash shouldn’t be an option.ProhibitedInterfaceBuilderflags any usage of interface builder. Interface builder files are prone to merge conflicts, and are impossible to code review, so larger teams usually try to avoid it or reduce its usage.UnavailableFunctionflags any function throwing afatalErrornot marked as@available(*, unavailable)to ensure no calls are actually performed in the codebase.
XML
MissingEncodingfinds XML files without explicit encoding.
Other changes
The information about changed rules, removed rules and rulesets can be found in the Detailed Release Notes for PMD 7.
🚨 API
The API of PMD has been growing over the years and needed some cleanup. The goal is, to have a clear separation between a well-defined API and the implementation, which is internal. This should help us in future development.
Also, there are some improvement and changes in different areas. For the detailed description of the changes listed here, see Detailed Release Notes for PMD 7.
- Miscellaneous smaller changes and cleanups
- XPath 3.1 support for XPath-based rules
- Node stream API for AST traversal
- Metrics framework
- Testing framework
- Language Lifecycle and Language Properties
- Rule Properties
- New Programmatic API for CPD
💥 Compatibility and migration notes
A detailed documentation of required changes are available in the Migration Guide for PMD 7.
See also Detailed Release Notes for PMD 7.
🐛 Fixed Issues
More than 300 issues have been fixed in PMD 7. See Detailed Release Notes for PMD 7 for the complete list of fixed issues.
✨ External Contributions
Many thanks to the following contributors: @219sansim, @aaronhurst-google, @anastasiia-koba, @AndreyBozhko, @bergander, @ciufudean, @cyw3, @dague1, @Debamoy, @eklimo, @ethauvin, @JerritEic, @joaodinissf, @kenji21, @krdabrowski, @lbovet, @lsoncini, @LynnBroe, @marcindabrowski, @matifraga, @mohan-chinnappan-n, @mohui1999, @nawforce, @nirvikpatel, @nwcm, @oleksandr-shvets, @pguyot, @PimvanderLoos, @rcorfieldffdc, @sfdcsteve, @shai-bennathan, @tomidelucca, @tprouvot, @wener-tiobe.
See Detailed Release Notes for PMD 7 for the full list of PRs.
📈 Stats
- 5741 commits
- 849 closed tickets & PRs
- Days since last release (6.55.0): 390
- Days since last release (7.0.0-rc4): 173
30-September-2023 - 7.0.0-rc4
We’re excited to bring you the next major version of PMD!
Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate page with the full Detailed Release Notes for PMD 7.0.0.
PMD 7.0.0 is finally almost ready. In order to gather feedback, we are going to ship a couple of release candidates. These are officially available on GitHub and Maven Central and can be used as usual (e.g. as a dependency). We encourage you to try out the new features, but keep in mind that we may introduce API breaking changes between the release candidates. It should be stable enough if you don't use custom rules.
We have still some tasks planned for the next release candidates. You can see the progress in PMD 7 Tracking Issue #3898.
If you find any problem or difficulty while updating from PMD 6, please provide feedback via our issue tracker. That way we can improve the experience for all.
Table Of Contents
- Changes since 7.0.0-rc3
- 🚀 Major Features and Enhancements
- 🎉 Language Related Changes
- New: Swift support
- New: Kotlin support (experimental)
- New: CPD support for TypeScript
- New: CPD support for Julia
- New: CPD support for Coco
- New: Java 21 Support
- Changed: JavaScript support
- Changed: Language versions
- Changed: CPP can now ignore identifiers in sequences (CPD)
- Changed: Apex Jorje Updated
- Changed: Rule properties
- 🌟 New and changed rules
- 🚨 API
- 💥 Compatibility and migration notes
- 🐛 Fixed Issues
- ✨ External Contributions
- 📈 Stats
Changes since 7.0.0-rc3
This section lists the most important changes from the last release candidate. The remaining section describes the complete release notes for 7.0.0.
New and Noteworthy
Migration Guide for PMD 7
A detailed documentation of required changes are available in the Migration Guide for PMD 7.
Apex Jorje Updated
With the new version of Apex Jorje, the new language constructs like User Mode Database Operations can be parsed now. PMD should now be able to parse Apex code up to version 59.0 (Winter ‘23).
Java 21 Support
This release of PMD brings support for Java 21. There are the following new standard language features, that are supported now:
PMD also supports the following preview language features:
- JEP 430: String Templates (Preview)
- JEP 443: Unnamed Patterns and Variables (Preview)
- JEP 445: Unnamed Classes and Instance Main Methods (Preview)
In order to analyze a project with PMD that uses these language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 21-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-21-preview ...
Note: Support for Java 19 preview language features have been removed. The version “19-preview” is no longer available.
Fixed issues
- miscellaneous
- core
- #1204: [core] Allow numeric properties in XML to be within an unbounded range
- #3919: [core] Merge CPD and PMD language
- #4204: [core] Provide a CpdAnalysis class as a programmatic entry point into CPD
- #4301: [core] Remove deprecated property concrete classes
- #4302: [core] Migrate Property Framework API to Java 8
- #4323: [core] Refactor CPD integration
- #4397: [core] Refactor CPD
- #4611: [core] Fix loading language properties from env vars
- #4621: [core] Make
ClasspathClassLoader::getResourcechild first
- cli
- #4423: [cli] Fix NPE when only
--file-listis specified
- #4423: [cli] Fix NPE when only
- doc
- apex
- apex-design
- #4596: [apex] ExcessivePublicCount ignores properties
- apex-security
- #4646: [apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types
- java
- java-bestpractices
- #4634: [java] JUnit4TestShouldUseTestAnnotation false positive with TestNG
API Changes
pmd-java
- Support for Java 19 preview language features have been removed. The version “19-preview” is no longer available.
Rule properties
- The old deprecated classes like
IntPropertyandStringPropertyhave been removed. Please usePropertyFactoryto create properties. - All properties which accept multiple values now use a comma (
,) as a delimiter. The previous default was a pipe character (|). The delimiter is not configurable anymore. If needed, the comma can be escaped with a backslash. - The
minandmaxattributes in property definitions in the XML are now optional and can appear separately or be omitted.
New Programmatic API for CPD
See Detailed Release Notes for PMD 7 and PR #4397 for details.
Removed classes and methods
The following previously deprecated classes have been removed:
- pmd-core
net.sourceforge.pmd.cpd.AbstractTokenizer➡️ useAnyTokenizerinsteadnet.sourceforge.pmd.cpd.CPD➡️ usePmdClifrompmd-climodule for CLI support or useCpdAnalysisfor programmatic APInet.sourceforge.pmd.cpd.GridBagHelper(now package private)net.sourceforge.pmd.cpd.TokenEntry.Statenet.sourceforge.pmd.lang.document.CpdCompatnet.sourceforge.pmd.properties.BooleanMultiPropertynet.sourceforge.pmd.properties.BooleanPropertynet.sourceforge.pmd.properties.CharacterMultiPropertynet.sourceforge.pmd.properties.CharacterPropertynet.sourceforge.pmd.properties.DoubleMultiPropertynet.sourceforge.pmd.properties.DoublePropertynet.sourceforge.pmd.properties.EnumeratedMultiPropertynet.sourceforge.pmd.properties.EnumeratedPropertynet.sourceforge.pmd.properties.EnumeratedPropertyDescriptornet.sourceforge.pmd.properties.FileProperty(note: without replacement)net.sourceforge.pmd.properties.FloatMultiPropertynet.sourceforge.pmd.properties.FloatPropertynet.sourceforge.pmd.properties.IntegerMultiPropertynet.sourceforge.pmd.properties.IntegerPropertynet.sourceforge.pmd.properties.LongMultiPropertynet.sourceforge.pmd.properties.LongPropertynet.sourceforge.pmd.properties.MultiValuePropertyDescriptornet.sourceforge.pmd.properties.NumericPropertyDescriptornet.sourceforge.pmd.properties.PropertyDescriptorFieldnet.sourceforge.pmd.properties.RegexPropertynet.sourceforge.pmd.properties.SingleValuePropertyDescriptornet.sourceforge.pmd.properties.StringMultiPropertynet.sourceforge.pmd.properties.StringPropertynet.sourceforge.pmd.properties.ValueParsernet.sourceforge.pmd.properties.ValueParserConstantsnet.sourceforge.pmd.properties.builders.MultiNumericPropertyBuildernet.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuildernet.sourceforge.pmd.properties.builders.MultiValuePropertyBuildernet.sourceforge.pmd.properties.builders.PropertyDescriptorBuildernet.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrappernet.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuildernet.sourceforge.pmd.properties.builders.SingleNumericPropertyBuildernet.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuildernet.sourceforge.pmd.properties.builders.SingleValuePropertyBuildernet.sourceforge.pmd.properties.modules.EnumeratedPropertyModulenet.sourceforge.pmd.properties.modules.NumericPropertyModule
The following previously deprecated methods have been removed:
- pmd-core
net.sourceforge.pmd.properties.PropertyBuilder.GenericCollectionPropertyBuilder#delim(char)net.sourceforge.pmd.properties.PropertySource#setProperty(...)net.sourceforge.pmd.properties.internal.PropertyTypeId#factoryFor(...)net.sourceforge.pmd.properties.internal.PropertyTypeId#typeIdFor(...)net.sourceforge.pmd.properties.PropertyDescriptor: removed methods errorFor, type, isMultiValue, uiOrder, compareTo, isDefinedExternally, valueFrom, asDelimitedString
The following methods have been removed:
- pmd-core
CPDConfiguration#sourceCodeFor(File),#postConstruct(),#tokenizer(),#filenameFilter()removed
Mark#getSourceSlice(),#setLineCount(int),#getLineCount(),#setSourceCode(SourceCode)removed#getBeginColumn(),#getBeginLine(),#getEndLine(),#getEndColumn()removed ➡️ usegetLocationinstead
Match#LABEL_COMPARATORremoved#setMarkSet(...),#setLabel(...),#getLabel(),#addTokenEntry(...)removed#getSourceCodeSlice()removed ➡️ useCPDReport#getSourceCodeSliceinstead
TokenEntry#getEOF(),#clearImages(),#getIdentifier(),#getIndex(),#setHashCode(int)removed#EOFremoved ➡️ useisEofinstead
Parser.ParserTask#getFileDisplayName()removed ➡️ usegetFileIdinstead (getFileId().getAbsolutePath())
The following classes have been removed:
- pmd-core
net.sourceforge.pmd.cpd.AbstractLanguagenet.sourceforge.pmd.cpd.AnyLanguagenet.sourceforge.pmd.cpd.Languagenet.sourceforge.pmd.cpd.LanguageFactorynet.sourceforge.pmd.cpd.MatchAlgorithm(now package private)net.sourceforge.pmd.cpd.MatchCollector(now package private)net.sourceforge.pmd.cpd.SourceCode(and all inner classes likeFileCodeLoader, …)net.sourceforge.pmd.cpd.token.TokenFilter
Moved packages
- pmd-core
NumericConstraints(old package:net.sourceforge.pmd.properties.constraints.NumericConstraints)PropertyConstraint(old package:net.sourceforge.pmd.properties.constraints.PropertyConstraint)- not experimental anymore
ReportException(old package:net.sourceforge.pmd.cpd, moved to modulepmd-ant)- it is now a RuntimeException
CPDReportRenderer(old package:net.sourceforge.pmd.cpd.renderer)AntlrTokenFilter(old package:net.sourceforge.pmd.cpd.token)BaseTokenFilter(old package:net.sourceforge.pmd.cpd.token.internal)JavaCCTokenFilter(old package:net.sourceforge.pmd.cpd.token)
Changed types and other changes
- pmd-core
PropertyDescriptoris now a class (was an interface) and it is not comparable anymore.AbstractConfiguration#setSourceEncoding- previously this method took a simple String for the encoding.
PmdConfigurationandCPDConfiguration- many getters and setters have been moved to the parent class
AbstractConfiguration
- many getters and setters have been moved to the parent class
CPDListener#addedFile- no
Fileparameter anymore
- no
CPDReport#getNumberOfTokensPerFilereturns aMapofFileId,Integerinstead ofStringCPDReport#filterMatchesnow takes ajava.util.function.Predicateas parameterTokenizer- constants are now
PropertyDescriptorinstead ofString, to be used as language properties tokenizechanged parameters. Now takes aTextDocumentand aTokenFactory(instead ofSourceCodeandTokens)
- constants are now
Language- method
#createProcessor(LanguagePropertyBundle)moved toPmdCapableLanguage
- method
StringUtil#linesWithTrimIndentnow takes aCharsinstead of aString.
- All language modules (like pmd-apex, pmd-cpp, …)
- consistent package naming:
net.sourceforge.pmd.lang.<langId>.cpd - adapted to use
CpdCapableLanguage - consistent static method
#getInstance() - removed constants like
ID,TERSE_NAMEorNAME. UsegetInstance().getName()etc. instead
- consistent package naming:
Internal APIs
Deprecated API
-
Language#getTerseName➡️ usegetIdinstead -
The method
ASTPattern#getParenthesisDepthhas been deprecated and will be removed. It was introduced for supporting parenthesized patterns, but that was removed with Java 21. It is only used when parsing code as java-19-preview.
Experimental APIs
- To support the Java preview language features “String Templates” and “Unnamed Patterns and Variables”, the following AST nodes have been introduced as experimental:
- The AST nodes for supporting “Record Patterns” and “Pattern Matching for switch” are not experimental anymore:
ASTRecordPatternASTPatternList(Note: it was renamed fromASTComponentPatternList)ast(Note: it was renamed fromASTSwitchGuard)
External Contributions
- #4528: [apex] Update to apexlink - Kevin Jones (@nawforce)
- #4637: [java] fix #4634 - JUnit4TestShouldUseTestAnnotation false positive with TestNG - Krystian Dabrowski (@krdabrowski)
- #4649: [apex] Add SObjectType and SObjectField to list of injectable SOQL variable types - Richard Corfield (@rcorfieldffdc)
- #4651: [doc] Add “Tencent Cloud Code Analysis” in Tools / Integrations - yale (@cyw3)
- #4664: [cli] CPD: Fix NPE when only
--file-listis specified - Wener (@wener-tiobe) - #4665: [java] Doc: Fix references AutoClosable -> AutoCloseable - Andrey Bozhko (@AndreyBozhko)
🚀 Major Features and Enhancements
New official logo
The new official logo of PMD:

Revamped Java module
- Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS)
- Built-in rules have been upgraded for the changed AST
- Rewritten type resolution framework and symbol table correctly implements the JLS
- AST exposes more semantic information (method calls, field accesses)
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Clément Fournier (@oowekyala), Andreas Dangel (@adangel), Juan Martín Sotuyo Dodero (@jsotuyod)
Revamped Command Line Interface
- unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities
- single script
pmd(pmd.batfor Windows) to launch the different utilities:pmd checkto run PMD rules and analyze a projectpmd cpdto run CPD (copy paste detector)pmd designerto run the PMD Rule Designer
- progress bar support for
pmd check - shell completion

For more information, see the Detailed Release Notes for PMD 7.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Full Antlr support
- Antlr based grammars can now be used to build full-fledged PMD rules.
- Previously, Antlr grammar could only be used for CPD
- New supported languages: Swift and Kotlin
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog.
New CPD report format cpdhtml-v2.xslt
Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. It uses an XSLT stylesheet to convert CPD’s XML format into HTML.
See the example report.
🎉 Language Related Changes
Note that this is just a concise listing of the highlight. For more information on the languages, see the Detailed Release Notes for PMD 7.
New: Swift support
- use PMD to analyze Swift code with PMD rules
- initially 4 built-in rules
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
New: Kotlin support (experimental)
- use PMD to analyze Kotlin code with PMD rules
- Support for Kotlin 1.8 grammar
- initially 2 built-in rules
New: CPD support for TypeScript
Thanks to a contribution, CPD now supports the TypeScript language. It is shipped
with the rest of the JavaScript support in the module pmd-javascript.
Contributors: Paul Guyot (@pguyot)
New: CPD support for Julia
Thanks to a contribution, CPD now supports the Julia language. It is shipped
in the new module pmd-julia.
Contributors: Wener (@wener-tiobe)
New: CPD support for Coco
Thanks to a contribution, CPD now supports Coco, a modern programming language
designed specifically for building event-driven software. It is shipped in the new
module pmd-coco.
Contributors: Wener (@wener-tiobe)
New: Java 21 Support
This release of PMD brings support for Java 21. There are the following new standard language features, that are supported now:
PMD also supports the following preview language features:
- JEP 430: String Templates (Preview)
- JEP 443: Unnamed Patterns and Variables (Preview)
- JEP 445: Unnamed Classes and Instance Main Methods (Preview)
In order to analyze a project with PMD that uses these language features,
you’ll need to enable it via the environment variable PMD_JAVA_OPTS and select the new language
version 21-preview:
export PMD_JAVA_OPTS=--enable-preview
pmd check --use-version java-21-preview ...
Note: Support for Java 19 preview language features have been removed. The version “19-preview” is no longer available.
Changed: JavaScript support
- latest version supports ES6 and also some new constructs (see Rhino])
- comments are retained
Changed: Language versions
- more predefined language versions for each supported language
- can be used to limit rule execution for specific versions only with
minimumLanguageVersionandmaximumLanguageVersionattributes.
Changed: CPP can now ignore identifiers in sequences (CPD)
- new command line option for CPD:
--ignore-sequences. - This option is used for CPP only: with the already existing option
--ignore-literal-sequences, only literals were ignored. The new option additional ignores identifiers as well in sequences. - See PR #4470 for details.
Changed: Apex Jorje Updated
With the new version of Apex Jorje, the new language constructs like User Mode Database Operations can be parsed now. PMD should now be able to parse Apex code up to version 59.0 (Winter ‘23).
Changed: Rule properties
- The old deprecated classes like
IntPropertyandStringPropertyhave been removed. Please usePropertyFactoryto create properties. - All properties which accept multiple values now use a comma (
,) as a delimiter. The previous default was a pipe character (|). The delimiter is not configurable anymore. If needed, the comma can be escaped with a backslash. - The
minandmaxattributes in property definitions in the XML are now optional and can appear separately or be omitted.
🌟 New and changed rules
New Rules
Apex
UnusedMethodfinds unused methods in your code.
Java
UnnecessaryBoxingreports boxing and unboxing conversions that may be made implicit.
Kotlin
Swift
Changed Rules
General changes
- All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified.
The properties
topscoreandsigmahave been removed. The propertyminimumis still there, however the type is not a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL and Velocity Template Language (vm):- Apex:
ExcessiveClassLength,ExcessiveParameterList,ExcessivePublicCount,NcssConstructorCount,NcssMethodCount,NcssTypeCount - Java:
ExcessiveImports,ExcessiveParameterList,ExcessivePublicCount,SwitchDensity - PLSQL:
ExcessiveMethodLength,ExcessiveObjectLength,ExcessivePackageBodyLength,ExcessivePackageSpecificationLength,ExcessiveParameterList,ExcessiveTypeLength,NcssMethodCount,NcssObjectCount,NPathComplexity - VM:
ExcessiveTemplateLength
- Apex:
- The general property
violationSuppressXPathwhich is available for all rules to suppress warnings now uses XPath version 3.1 by default. This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. If you upgrade from PMD 6, you need to verify yourviolationSuppressXPathproperties.
Apex General changes
- The properties
cc_categories,cc_remediation_points_multiplier,cc_block_highlightinghave been removed from all rules. These properties have been deprecated since PMD 6.13.0. See issue #1648 for more details.
Java General changes
-
Violations reported on methods or classes previously reported the line range of the entire method or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. This affects various rules, e.g.
CognitiveComplexity.The report location is controlled by the overrides of the method
getReportLocationin different node types.See issue #4439 and issue #730 for more details.
Java Best Practices
ArrayIsStoredDirectly: Violations are now reported on the assignment and not anymore on the formal parameter. The reported line numbers will probably move.AvoidReassigningLoopVariables: This rule might not report anymore all reassignments of the control variable in for-loops when the propertyforReassignis set toskip. See issue #4500 for more details.LooseCoupling: The rule has a new property to allow some types to be coupled to (allowedTypes).UnusedLocalVariable: This rule has some important false-negatives fixed and finds many more cases now. For details see issues #2130, #4516, and #4517.
Java Codestyle
MethodNamingConventions: The propertycheckNativeMethodshas been removed. The property was deprecated since PMD 6.3.0. Use the propertynativePatternto control whether native methods should be considered or not.ShortVariable: This rule now also reports short enum constant names.UseDiamondOperator: The propertyjava7Compatibilityhas been removed. The rule now handles Java 7 properly without a property.UnnecessaryFullyQualifiedName: The rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise.UselessParentheses: The rule has two new properties which control how strict the rule should be applied. WithignoreClarifying(default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other propertyignoreBalancing(default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.
Java Design
CyclomaticComplexity: The propertyreportLevelhas been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods usingclassReportLevelandmethodReportLevelinstead.ImmutableField: The propertyignoredAnnotationshas been removed. The property was deprecated since PMD 6.52.0.LawOfDemeter: The rule has a new propertytrustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.NPathComplexity: The propertyminimumhas been removed. It was deprecated since PMD 6.0.0. Use the propertyreportLevelinstead.SingularField: The propertiescheckInnerClassesanddisallowNotAssignmenthave been removed. The rule is now more precise and will check these cases properly.UseUtilityClass: The propertyignoredAnnotationshas been removed.
Java Documentation
CommentContent: The propertiescaseSensitiveanddisallowedTermsare removed. The new propertyforbiddenRegexcan be used now to define the disallowed terms with a single regular expression.CommentRequired:- Overridden methods are now detected even without the
@Overrideannotation. This is relevant for the propertymethodWithOverrideCommentRequirement. See also pull request #3757. - Elements in annotation types are now detected as well. This might lead to an increased number of violations for missing public method comments.
- Overridden methods are now detected even without the
CommentSize: When determining the line-length of a comment, the leading comment prefix markers (e.g.*or//) are ignored and don’t add up to the line-length. See also pull request #4369.
Java Error Prone
AvoidDuplicateLiterals: The propertyexceptionfilehas been removed. The property was deprecated since PMD 6.10.0. Use the propertyexceptionListinstead.DontImportSun:sun.misc.Signalis not special-cased anymore.EmptyCatchBlock:CloneNotSupportedExceptionandInterruptedExceptionare not special-cased anymore. Rename the exception parameter toignoredto ignore them.ImplicitSwitchFallThrough: Violations are now reported on the case statements rather than on the switch statements. This is more accurate but might result in more violations now.
Removed Rules
Many rules, that were previously deprecated have been finally removed. See Detailed Release Notes for PMD 7 for the complete list.
🚨 API
The API of PMD has been growing over the years and needed some cleanup. The goal is, to have a clear separation between a well-defined API and the implementation, which is internal. This should help us in future development.
Also, there are some improvement and changes in different areas. For the detailed description of the changes listed here, see Detailed Release Notes for PMD 7.
- Miscellaneous smaller changes and cleanups
- XPath 3.1 support for XPath-based rules
- Node stream API for AST traversal
- Metrics framework
- Testing framework
- Language Lifecycle and Language Properties
- Rule Properties
- New Programmatic API for CPD
💥 Compatibility and migration notes
A detailed documentation of required changes are available in the Migration Guide for PMD 7.
See also Detailed Release Notes for PMD 7.
🐛 Fixed Issues
- miscellaneous
- #881: [all] Breaking API changes for 7.0.0
- #896: [all] Use slf4j
- #1431: [ui] Remove old GUI applications (designerold, bgastviewer)
- #1451: [core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string
- #2496: Update PMD 7 Logo on landing page
- #2497: PMD 7 Logo page
- #2498: Update PMD 7 Logo in documentation
- #3797: [all] Use JUnit5
- #4462: Provide Software Bill of Materials (SBOM)
- #4460: Fix assembly-plugin warnings
- #4582: [dist] Download link broken
- #4691: [CVEs] Critical and High CEVs reported on PMD and PMD dependencies
- ant
- #4080: [ant] Split off Ant integration into a new submodule
- core
- #880: [core] Make visitors generic
- #1204: [core] Allow numeric properties in XML to be within an unbounded range
- #1622: [core] NodeStream API
- #1687: [core] Deprecate and Remove XPath 1.0 support
- #1785: [core] Allow abstract node types to be valid rulechain visits
- #1825: [core] Support NoAttribute for XPath
- #2038: [core] Remove DCD
- #2218: [core]
isFindBoundaryshould not be an attribute - #2234: [core] Consolidate PMD CLI into a single command
- #2239: [core] Merging Javacc build scripts
- #2500: [core] Clarify API for ANTLR based languages
- #2518: [core] Language properties
- #2602: [core] Remove ParserOptions
- #2614: [core] Upgrade Saxon, add XPath 3.1, remove Jaxen
- #2696: [core] Remove DFA
- #2821: [core] Rule processing error filenames are missing paths
- #2873: [core] Utility classes in pmd 7
- #2885: [core] Error recovery mode
- #3203: [core] Replace RuleViolationFactory implementations with ViolationDecorator
- #3692: [core] Analysis listeners
- #3782: [core] Language lifecycle
- #3815: [core] Update Saxon HE to 10.7
- #3893: [core] Text documents
- #3902: [core] Violation decorators
- #3918: [core] Make LanguageRegistry non static
- #3919: [core] Merge CPD and PMD language
- #3922: [core] Better error reporting for the ruleset parser
- #4035: [core] ConcurrentModificationException in DefaultRuleViolationFactory
- #4120: [core] Explicitly name all language versions
- #4204: [core] Provide a CpdAnalysis class as a programmatic entry point into CPD
- #4301: [core] Remove deprecated property concrete classes
- #4302: [core] Migrate Property Framework API to Java 8
- #4323: [core] Refactor CPD integration
- #4353: [core] Micro optimizations for Node API
- #4365: [core] Improve benchmarking
- #4397: [core] Refactor CPD
- #4420: [core] Remove PMD.EOL
- #4425: [core] Replace TextFile::pathId
- #4454: [core] “Unknown option: ‘-min’” but is referenced in documentation
- #4611: [core] Fix loading language properties from env vars
- #4621: [core] Make
ClasspathClassLoader::getResourcechild first
- cli
- #2234: [core] Consolidate PMD CLI into a single command
- #3828: [core] Progress reporting
- #4079: [cli] Split off CLI implementation into a pmd-cli submodule
- #4423: [cli] Fix NPE when only
--file-listis specified - #4482: [cli] pmd.bat can only be executed once
- #4484: [cli] ast-dump with no properties produce an NPE
- doc
- testing
Language specific fixes:
- apex
- #1937: [apex] Apex should only have a single RootNode
- #1648: [apex,vf] Remove CodeClimate dependency
- #1750: [apex] Remove apex statistical rules
- #2836: [apex] Remove Apex ProjectMirror
- #3973: [apex] Update parser to support new ‘as user’ keywords (User Mode for Database Operations)
- #4427: [apex] ApexBadCrypto test failing to detect inline code
- #4453: [apex] [7.0-rc1] Exception while initializing Apexlink (Index 34812 out of bounds for length 34812)
- apex-design
- apex-security
- #4646: [apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types
- java
- #520: [java] Allow
@SuppressWarningswith constants instead of literals - #864: [java] Similar/duplicated implementations for determining FQCN
- #905: [java] Add new node for anonymous class declaration
- #910: [java] AST inconsistency between primitive and reference type arrays
- #997: [java] Java8 parsing corner case with annotated array types
- #998: [java] AST inconsistencies around FormalParameter
- #1019: [java] Breaking Java Grammar changes for PMD 7.0.0
- #1124: [java] ImmutableList implementation in the qname codebase
- #1128: [java] Improve ASTLocalVariableDeclaration
- #1150: [java] ClassOrInterfaceType AST improvements
- #1207: [java] Resolve explicit types using FQCNs, without hitting the classloader
- #1367: [java] Parsing error on annotated inner class
- #1661: [java] About operator nodes
- #2366: [java] Remove qualified names
- #2819: [java] GLB bugs in pmd 7
- #3642: [java] Parse error on rare extra dimensions on method return type on annotation methods
- #3763: [java] Ambiguous reference error in valid code
- #3749: [java] Improve
isOverriddenin ASTMethodDeclaration - #3750: [java] Make symbol table support instanceof pattern bindings
- #3752: [java] Expose annotations in symbol API
- #4237: [java] Cleanup handling of Java comments
- #4317: [java] Some AST nodes should not be TypeNodes
- #4359: [java] Type resolution fails with NPE when the scope is not a type declaration
- #4367: [java] Move testrule TypeResTest into internal
- #4383: [java] IllegalStateException: Object is not an array type!
- #4401: [java] PMD 7 fails to build under Java 19
- #4405: [java] Processing error with ArrayIndexOutOfBoundsException
- #4583: [java] Support JDK 21 (LTS)
- #520: [java] Allow
- java-bestpractices
- #342: [java] AccessorMethodGeneration: Name clash with another public field not properly handled
- #755: [java] AccessorClassGeneration false positive for private constructors
- #770: [java] UnusedPrivateMethod yields false positive for counter-variant arguments
- #807: [java] AccessorMethodGeneration false positive with overloads
- #833: [java] ForLoopCanBeForeach should consider iterating on this
- #1189: [java] UnusedPrivateMethod false positive from inner class via external class
- #1205: [java] Improve ConstantsInInterface message to mention alternatives
- #1212: [java] Don’t raise JUnitTestContainsTooManyAsserts on JUnit 5’s assertAll
- #1422: [java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field
- #1455: [java] JUnitTestsShouldIncludeAssert: False positives for assert methods named “check” and “verify”
- #1563: [java] ForLoopCanBeForeach false positive with method call using index variable
- #1565: [java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ
- #1747: [java] PreserveStackTrace false-positive
- #1969: [java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class
- #1998: [java] AccessorClassGeneration false-negative: subclass calls private constructor
- #2130: [java] UnusedLocalVariable: false-negative with array
- #2147: [java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods
- #2464: [java] LooseCoupling must ignore class literals: ArrayList.class
- #2542: [java] UseCollectionIsEmpty can not detect the case
foo.bar().size() - #2650: [java] UseTryWithResources false positive when AutoCloseable helper used
- #2796: [java] UnusedAssignment false positive with call chains
- #2797: [java] MissingOverride long-standing issues
- #2806: [java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches
- #2822: [java] LooseCoupling rule: Extend to cover user defined implementations and interfaces
- #2843: [java] Fix UnusedAssignment FP with field accesses
- #2882: [java] UseTryWithResources - false negative for explicit close
- #2883: [java] JUnitAssertionsShouldIncludeMessage false positive with method call
- #2890: [java] UnusedPrivateMethod false positive with generics
- #2946: [java] SwitchStmtsShouldHaveDefault false positive on enum inside enums
- #3672: [java] LooseCoupling - fix false positive with generics
- #3675: [java] MissingOverride - fix false positive with mixing type vars
- #3858: [java] UseCollectionIsEmpty should infer local variable type from method invocation
- #4433: [java] [7.0-rc1] ReplaceHashtableWithMap on java.util.Properties
- #4492: [java] GuardLogStatement gives false positive when argument is a Java method reference
- #4503: [java] JUnitTestsShouldIncludeAssert: false negative with TestNG
- #4516: [java] UnusedLocalVariable: false-negative with try-with-resources
- #4517: [java] UnusedLocalVariable: false-negative with compound assignments
- #4518: [java] UnusedLocalVariable: false-positive with multiple for-loop indices
- #4634: [java] JUnit4TestShouldUseTestAnnotation false positive with TestNG
- java-codestyle
- #1208: [java] PrematureDeclaration rule false-positive on variable declared to measure time
- #1429: [java] PrematureDeclaration as result of method call (false positive)
- #1480: [java] IdenticalCatchBranches false positive with return expressions
- #1673: [java] UselessParentheses false positive with conditional operator
- #1790: [java] UnnecessaryFullyQualifiedName false positive with enum constant
- #1918: [java] UselessParentheses false positive with boolean operators
- #2134: [java] PreserveStackTrace not handling
Throwable.addSuppressed(...) - #2299: [java] UnnecessaryFullyQualifiedName false positive with similar package name
- #2391: [java] UseDiamondOperator FP when expected type and constructed type have a different parameterization
- #2528: [java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest
- #2739: [java] UselessParentheses false positive for string concatenation
- #2748: [java] UnnecessaryCast false positive with unchecked cast
- #2973: [java] New rule: UnnecessaryBoxing
- #3195: [java] Improve rule UnnecessaryReturn to detect more cases
- #3218: [java] Generalize UnnecessaryCast to flag all unnecessary casts
- #3221: [java] PrematureDeclaration false positive for unused variables
- #3238: [java] Improve ExprContext, fix FNs of UnnecessaryCast
- #3500: [java] UnnecessaryBoxing - check for Integer.valueOf(String) calls
- #4268: [java] CommentDefaultAccessModifier: false positive with TestNG annotations
- #4273: [java] CommentDefaultAccessModifier ignoredAnnotations should include “org.junit.jupiter.api.extension.RegisterExtension” by default
- #4357: [java] Fix IllegalStateException in UseDiamondOperator rule
- #4432: [java] [7.0-rc1] UnnecessaryImport - Unused static import is being used
- #4455: [java] FieldNamingConventions: false positive with lombok’s @UtilityClass
- #4487: [java] UnnecessaryConstructor: false-positive with @Inject and @Autowired
- #4511: [java] LocalVariableCouldBeFinal shouldn’t report unused variables
- #4512: [java] MethodArgumentCouldBeFinal shouldn’t report unused parameters
- #4557: [java] UnnecessaryImport FP with static imports of overloaded methods
- java-design
- #1014: [java] LawOfDemeter: False positive with lambda expression
- #1605: [java] LawOfDemeter: False positive for standard UTF-8 charset name
- #2160: [java] Issues with Law of Demeter
- #2175: [java] LawOfDemeter: False positive for chained methods with generic method call
- #2179: [java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property
- #2180: [java] LawOfDemeter: False positive with Thread and ThreadLocalRandom
- #2182: [java] LawOfDemeter: False positive with package-private access
- #2188: [java] LawOfDemeter: False positive with fields assigned to local vars
- #2536: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can’t detect inner class
- #3668: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes
- #3754: [java] SingularField false positive with read in while condition
- #3786: [java] SimplifyBooleanReturns should consider operator precedence
- #3840: [java] LawOfDemeter disallows method call on locally created object
- #4238: [java] Make LawOfDemeter not use the rulechain
- #4254: [java] ImmutableField - false positive with Lombok @Setter
- #4434: [java] [7.0-rc1] ExceptionAsFlowControl when simply propagating
- #4456: [java] FinalFieldCouldBeStatic: false positive with lombok’s @UtilityClass
- #4477: [java] SignatureDeclareThrowsException: false-positive with TestNG annotations
- #4490: [java] ImmutableField - false negative with Lombok @Getter
- #4549: [java] Make LawOfDemeter results deterministic
- java-documentation
- java-errorprone
- #659: [java] MissingBreakInSwitch - last default case does not contain a break
- #1005: [java] CloneMethodMustImplementCloneable triggers for interfaces
- #1669: [java] NullAssignment - FP with ternay and null as constructor argument
- #1899: [java] Recognize @SuppressWanings(“fallthrough”) for MissingBreakInSwitch
- #2320: [java] NullAssignment - FP with ternary and null as method argument
- #2532: [java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case
new BigDecimal(Expression) - #2579: [java] MissingBreakInSwitch detects the lack of break in the last case
- #2880: [java] CompareObjectsWithEquals - false negative with type res
- #2893: [java] Remove special cases from rule EmptyCatchBlock
- #2894: [java] Improve MissingBreakInSwitch
- #3071: [java] BrokenNullCheck FP with PMD 6.30.0
- #3087: [java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion
- #3100: [java] UseCorrectExceptionLogging FP in 6.31.0
- #3173: [java] UseProperClassLoader false positive
- #3351: [java] ConstructorCallsOverridableMethod ignores abstract methods
- #3400: [java] AvoidUsingOctalValues FN with underscores
- #3843: [java] UseEqualsToCompareStrings should consider return type
- #4063: [java] AvoidBranchingStatementAsLastInLoop: False-negative about try/finally block
- #4356: [java] Fix NPE in CloseResourceRule
- #4449: [java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression
- #4457: [java] OverrideBothEqualsAndHashcode: false negative with anonymous classes
- #4493: [java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject
- #4505: [java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1
- #4510: [java] ConstructorCallsOverridableMethod: false positive with lombok’s @Value
- #4513: [java] UselessOperationOnImmutable various false negatives with String
- #4514: [java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true
- #4546: [java] OverrideBothEqualsAndHashCode ignores records
- java-multithreading
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
this.run() - #2538: [java] DontCallThreadRun can’t detect the case that call run() in
foo.bar.run() - #2577: [java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument:
foo.notify(bar) - #4483: [java] NonThreadSafeSingleton false positive with double-checked locking
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
- java-performance
- #1224: [java] InefficientEmptyStringCheck false negative in anonymous class
- #2587: [java] AvoidArrayLoops could also check for list copy through iterated List.add()
- #2712: [java] SimplifyStartsWith false-positive with AssertJ
- #3486: [java] InsufficientStringBufferDeclaration: Fix NPE
- #3848: [java] StringInstantiation: false negative when using method result
- #4070: [java] A false positive about the rule RedundantFieldInitializer
- #4458: [java] RedundantFieldInitializer: false positive with lombok’s @Value
- kotlin
- swift
- xml
- #1800: [xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper
✨ External Contributions
- #1658: [core] Node support for Antlr-based languages - Matías Fraga (@matifraga)
- #1698: [core] [swift] Antlr Base Parser adapter and Swift Implementation - Lucas Soncini (@lsoncini)
- #1774: [core] Antlr visitor rules - Lucas Soncini (@lsoncini)
- #1877: [swift] Feature/swift rules - Matías Fraga (@matifraga)
- #1881: [doc] Add ANTLR documentation - Matías Fraga (@matifraga)
- #1882: [swift] UnavailableFunction Swift rule - Tomás de Lucca (@tomidelucca)
- #2830: [apex] Apexlink POC - Kevin Jones (@nawforce)
- #3866: [core] Add CLI Progress Bar - @JerritEic (@JerritEic)
- #4402: [javascript] CPD: add support for Typescript using antlr4 grammar - Paul Guyot (@pguyot)
- #4403: [julia] CPD: Add support for Julia code duplication - Wener (@wener-tiobe)
- #4412: [doc] Added new error msg to ConstantsInInterface - David Ljunggren (@dague1)
- #4426: [cpd] New XML to HTML XLST report format for PMD CPD - mohan-chinnappan-n (@mohan-chinnappan-n)
- #4428: [apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - Steven Stearns (@sfdcsteve)
- #4431: [coco] CPD: Coco support for code duplication detection - Wener (@wener-tiobe)
- #4444: [java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - Nirvik Patel (@nirvikpatel)
- #4450: [java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - Seren (@mohui1999)
- #4452: [doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - nwcm (@nwcm)
- #4470: [cpp] CPD: Added strings as literal and ignore identifiers in sequences - Wener (@wener-tiobe)
- #4474: [java] ImmutableField: False positive with lombok (fixes #4254) - Pim van der Loos (@PimvanderLoos)
- #4488: [java] Fix #4477: A false-positive about SignatureDeclareThrowsException - AnnaDev (@LynnBroe)
- #4494: [java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - AnnaDev (@LynnBroe)
- #4495: [java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - AnnaDev (@LynnBroe)
- #4507: [java] Fix #4503: A false negative about JUnitTestsShouldIncludeAssert and testng - AnnaDev (@LynnBroe)
- #4520: [doc] Fix typo: missing closing quotation mark after CPD-END - João Dinis Ferreira (@joaodinissf)
- #4528: [apex] Update to apexlink - Kevin Jones (@nawforce)
- #4533: [java] Fix #4063: False-negative about try/catch block in Loop - AnnaDev (@LynnBroe)
- #4536: [java] Fix #4268: CommentDefaultAccessModifier - false positive with TestNG’s @Test annotation - AnnaDev (@LynnBroe)
- #4537: [java] Fix #4455: A false positive about FieldNamingConventions and UtilityClass - AnnaDev (@LynnBroe)
- #4538: [java] Fix #4456: A false positive about FinalFieldCouldBeStatic and UtilityClass - AnnaDev (@LynnBroe)
- #4540: [java] Fix #4457: false negative about OverrideBothEqualsAndHashcode - AnnaDev (@LynnBroe)
- #4541: [java] Fix #4458: A false positive about RedundantFieldInitializer and @Value - AnnaDev (@LynnBroe)
- #4542: [java] Fix #4510: A false positive about ConstructorCallsOverridableMethod and @Value - AnnaDev (@LynnBroe)
- #4553: [java] Fix #4492: GuardLogStatement gives false positive when argument is a Java method reference - Anastasiia Koba (@anastasiia-koba)
- #4637: [java] fix #4634 - JUnit4TestShouldUseTestAnnotation false positive with TestNG - Krystian Dabrowski (@krdabrowski)
- #4649: [apex] Add SObjectType and SObjectField to list of injectable SOQL variable types - Richard Corfield (@rcorfieldffdc)
- #4651: [doc] Add “Tencent Cloud Code Analysis” in Tools / Integrations - yale (@cyw3)
- #4664: [cli] CPD: Fix NPE when only
--file-listis specified - Wener (@wener-tiobe) - #4665: [java] Doc: Fix references AutoClosable -> AutoCloseable - Andrey Bozhko (@AndreyBozhko)
📈 Stats
- 5007 commits
- 658 closed tickets & PRs
- Days since last release: 122
30-May-2023 - 7.0.0-rc3
We’re excited to bring you the next major version of PMD!
Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate page with the full Detailed Release Notes for PMD 7.0.0.
PMD 7.0.0 is finally almost ready. In order to gather feedback, we are going to ship a couple of release candidates. These are officially available on GitHub and Maven Central and can be used as usual (e.g. as a dependency). We encourage you to try out the new features, but keep in mind that we may introduce API breaking changes between the release candidates. It should be stable enough if you don't use custom rules.
We have still some tasks planned for the next release candidates. You can see the progress in PMD 7 Tracking Issue #3898.
If you find any problem or difficulty while updating from PMD 6, please provide feedback via our issue tracker. That way we can improve the experience for all.
Table Of Contents
- Changes since 7.0.0-rc2
- 🚀 Major Features and Enhancements
- 🎉 Language Related Changes
- 🌟 New and changed rules
- 🚨 API
- 💥 Compatibility and migration notes
- 🐛 Fixed Issues
- ✨ External Contributions
- 📈 Stats
Changes since 7.0.0-rc2
This section lists the most important changes from the last release candidate. The remaining section describes the complete release notes for 7.0.0.
New CPD report format cpdhtml-v2.xslt
Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. It uses an XSLT stylesheet to convert CPD’s XML format into HTML.
See the example report.
Fixed issues
- miscellaneous
- #4460: Fix assembly-plugin warnings
- core
- java-bestpractices
- java-codestyle
- #4268: [java] CommentDefaultAccessModifier: false positive with TestNG annotations
- #4432: [java] [7.0-rc1] UnnecessaryImport - Unused static import is being used
- #4455: [java] FieldNamingConventions: false positive with lombok’s @UtilityClass
- #4557: [java] UnnecessaryImport FP with static imports of overloaded methods
- java-design
- java-errorprone
- #4063: [java] AvoidBranchingStatementAsLastInLoop: False-negative about try/finally block
- #4457: [java] OverrideBothEqualsAndHashcode: false negative with anonymous classes
- #4510: [java] ConstructorCallsOverridableMethod: false positive with lombok’s @Value
- #4546: [java] OverrideBothEqualsAndHashCode ignores records
- java-performance
- #4458: [java] RedundantFieldInitializer: false positive with lombok’s @Value
API Changes
- The following previously deprecated classes have been removed:
- pmd-core
net.sourceforge.pmd.PMDnet.sourceforge.pmd.cli.PMDCommandLineInterfacenet.sourceforge.pmd.cli.PMDParametersnet.sourceforge.pmd.cli.PmdParametersParseResult
- pmd-core
-
The asset filenames of PMD on GitHub Releases are now
pmd-dist-<version>-bin.zip,pmd-dist-<version>-src.zipandpmd-dist-<version>-doc.zip. Keep that in mind, if you have an automated download script.The structure inside the ZIP files stay the same, e.g. we still provide inside the binary distribution ZIP file the base directory
pmd-bin-<version>. - The CLI option
--stress(or-stress) has been removed without replacement. - The CLI option
--minimum-prioritywas changed with 7.0.0-rc1 to only take the following values: High, Medium High, Medium, Medium Low, Low. With 7.0.0-rc2 compatibility has been restored, so that the equivalent integer values (1 to 5) are supported as well. -
Replaced
RuleViolation::getFilenamewith newRuleViolation#getFileId, that returns aFileId. This is an identifier for aTextFileand could represent a path name. This allows to have a separate display name, e.g. renderers useFileNameRendererto either display the full path name or a relative path name (seeRenderer#setFileNameRendererandConfigurableFileNameRenderer). Many places where we used a simple String for a path-like name before have been adapted to use the newFileId.See PR #4425 for details.
External Contributions
- #4426: [cpd] New XML to HTML XLST report format for PMD CPD - mohan-chinnappan-n (@mohan-chinnappan-n)
- #4431: [coco] CPD: Coco support for code duplication detection - Wener (@wener-tiobe)
- #4470: [cpp] CPD: Added strings as literal and ignore identifiers in sequences - Wener (@wener-tiobe)
- #4507: [java] Fix #4503: A false negative about JUnitTestsShouldIncludeAssert and testng - AnnaDev (@LynnBroe)
- #4533: [java] Fix #4063: False-negative about try/catch block in Loop - AnnaDev (@LynnBroe)
- #4536: [java] Fix #4268: CommentDefaultAccessModifier - false positive with TestNG’s @Test annotation - AnnaDev (@LynnBroe)
- #4537: [java] Fix #4455: A false positive about FieldNamingConventions and UtilityClass - AnnaDev (@LynnBroe)
- #4538: [java] Fix #4456: A false positive about FinalFieldCouldBeStatic and UtilityClass - AnnaDev (@LynnBroe)
- #4540: [java] Fix #4457: false negative about OverrideBothEqualsAndHashcode - AnnaDev (@LynnBroe)
- #4541: [java] Fix #4458: A false positive about RedundantFieldInitializer and @Value - AnnaDev (@LynnBroe)
- #4542: [java] Fix #4510: A false positive about ConstructorCallsOverridableMethod and @Value - AnnaDev (@LynnBroe)
- #4553: [java] Fix #4492: GuardLogStatement gives false positive when argument is a Java method reference - Anastasiia Koba (@anastasiia-koba)
🚀 Major Features and Enhancements
New official logo
The new official logo of PMD:

Revamped Java module
- Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS)
- Built-in rules have been upgraded for the changed AST
- Rewritten type resolution framework and symbol table correctly implements the JLS
- AST exposes more semantic information (method calls, field accesses)
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Clément Fournier (@oowekyala), Andreas Dangel (@adangel), Juan Martín Sotuyo Dodero (@jsotuyod)
Revamped Command Line Interface
- unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities
- single script
pmd(pmd.batfor Windows) to launch the different utilities:pmd checkto run PMD rules and analyze a projectpmd cpdto run CPD (copy paste detector)pmd designerto run the PMD Rule Designer
- progress bar support for
pmd check - shell completion

For more information, see the Detailed Release Notes for PMD 7.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Full Antlr support
- Antlr based grammars can now be used to build full-fledged PMD rules.
- Previously, Antlr grammar could only be used for CPD
- New supported languages: Swift and Kotlin
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog.
New CPD report format cpdhtml-v2.xslt
Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. It uses an XSLT stylesheet to convert CPD’s XML format into HTML.
See the example report.
🎉 Language Related Changes
Note that this is just a concise listing of the highlight. For more information on the languages, see the Detailed Release Notes for PMD 7.
New: Swift support
- use PMD to analyze Swift code with PMD rules
- initially 4 built-in rules
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
New: Kotlin support (experimental)
- use PMD to analyze Kotlin code with PMD rules
- Support for Kotlin 1.8 grammar
- initially 2 built-in rules
New: CPD support for TypeScript
Thanks to a contribution, CPD now supports the TypeScript language. It is shipped
with the rest of the JavaScript support in the module pmd-javascript.
Contributors: Paul Guyot (@pguyot)
New: CPD support for Julia
Thanks to a contribution, CPD now supports the Julia language. It is shipped
in the new module pmd-julia.
Contributors: Wener (@wener-tiobe)
New: CPD support for Coco
Thanks to a contribution, CPD now supports Coco, a modern programming language
designed specifically for building event-driven software. It is shipped in the new
module pmd-coco.
Contributors: Wener (@wener-tiobe)
Changed: JavaScript support
- latest version supports ES6 and also some new constructs (see Rhino])
- comments are retained
Changed: Language versions
- more predefined language versions for each supported language
- can be used to limit rule execution for specific versions only with
minimumLanguageVersionandmaximumLanguageVersionattributes.
Changed: CPP can now ignore identifiers in sequences (CPD)
- new command line option for CPD:
--ignore-sequences. - This option is used for CPP only: with the already existing option
--ignore-literal-sequences, only literals were ignored. The new option additional ignores identifiers as well in sequences. - See PR #4470 for details.
🌟 New and changed rules
New Rules
Apex
UnusedMethodfinds unused methods in your code.
Java
UnnecessaryBoxingreports boxing and unboxing conversions that may be made implicit.
Kotlin
Swift
Changed Rules
General changes
- All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified.
The properties
topscoreandsigmahave been removed. The propertyminimumis still there, however the type is not a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL and Velocity Template Language (vm):- Apex:
ExcessiveClassLength,ExcessiveParameterList,ExcessivePublicCount,NcssConstructorCount,NcssMethodCount,NcssTypeCount - Java:
ExcessiveImports,ExcessiveParameterList,ExcessivePublicCount,SwitchDensity - PLSQL:
ExcessiveMethodLength,ExcessiveObjectLength,ExcessivePackageBodyLength,ExcessivePackageSpecificationLength,ExcessiveParameterList,ExcessiveTypeLength,NcssMethodCount,NcssObjectCount,NPathComplexity - VM:
ExcessiveTemplateLength
- Apex:
- The general property
violationSuppressXPathwhich is available for all rules to suppress warnings now uses XPath version 3.1 by default. This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. If you upgrade from PMD 6, you need to verify yourviolationSuppressXPathproperties.
Apex General changes
- The properties
cc_categories,cc_remediation_points_multiplier,cc_block_highlightinghave been removed from all rules. These properties have been deprecated since PMD 6.13.0. See issue #1648 for more details.
Java General changes
-
Violations reported on methods or classes previously reported the line range of the entire method or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. This affects various rules, e.g.
CognitiveComplexity.The report location is controlled by the overrides of the method
getReportLocationin different node types.See issue #4439 and issue #730 for more details.
Java Best Practices
ArrayIsStoredDirectly: Violations are now reported on the assignment and not anymore on the formal parameter. The reported line numbers will probably move.AvoidReassigningLoopVariables: This rule might not report anymore all reassignments of the control variable in for-loops when the propertyforReassignis set toskip. See issue #4500 for more details.LooseCoupling: The rule has a new property to allow some types to be coupled to (allowedTypes).UnusedLocalVariable: This rule has some important false-negatives fixed and finds many more cases now. For details see issues #2130, #4516, and #4517.
Java Codestyle
MethodNamingConventions: The propertycheckNativeMethodshas been removed. The property was deprecated since PMD 6.3.0. Use the propertynativePatternto control whether native methods should be considered or not.ShortVariable: This rule now also reports short enum constant names.UseDiamondOperator: The propertyjava7Compatibilityhas been removed. The rule now handles Java 7 properly without a property.UnnecessaryFullyQualifiedName: The rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise.UselessParentheses: The rule has two new properties which control how strict the rule should be applied. WithignoreClarifying(default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other propertyignoreBalancing(default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.
Java Design
CyclomaticComplexity: The propertyreportLevelhas been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods usingclassReportLevelandmethodReportLevelinstead.ImmutableField: The propertyignoredAnnotationshas been removed. The property was deprecated since PMD 6.52.0.LawOfDemeter: The rule has a new propertytrustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.NPathComplexity: The propertyminimumhas been removed. It was deprecated since PMD 6.0.0. Use the propertyreportLevelinstead.SingularField: The propertiescheckInnerClassesanddisallowNotAssignmenthave been removed. The rule is now more precise and will check these cases properly.UseUtilityClass: The propertyignoredAnnotationshas been removed.
Java Documentation
CommentContent: The propertiescaseSensitiveanddisallowedTermsare removed. The new propertyforbiddenRegexcan be used now to define the disallowed terms with a single regular expression.CommentRequired:- Overridden methods are now detected even without the
@Overrideannotation. This is relevant for the propertymethodWithOverrideCommentRequirement. See also pull request #3757. - Elements in annotation types are now detected as well. This might lead to an increased number of violations for missing public method comments.
- Overridden methods are now detected even without the
CommentSize: When determining the line-length of a comment, the leading comment prefix markers (e.g.*or//) are ignored and don’t add up to the line-length. See also pull request #4369.
Java Error Prone
AvoidDuplicateLiterals: The propertyexceptionfilehas been removed. The property was deprecated since PMD 6.10.0. Use the propertyexceptionListinstead.DontImportSun:sun.misc.Signalis not special-cased anymore.EmptyCatchBlock:CloneNotSupportedExceptionandInterruptedExceptionare not special-cased anymore. Rename the exception parameter toignoredto ignore them.ImplicitSwitchFallThrough: Violations are now reported on the case statements rather than on the switch statements. This is more accurate but might result in more violations now.
Removed Rules
Many rules, that were previously deprecated have been finally removed. See Detailed Release Notes for PMD 7 for the complete list.
🚨 API
The API of PMD has been growing over the years and needed some cleanup. The goal is, to have a clear separation between a well-defined API and the implementation, which is internal. This should help us in future development.
Also, there are some improvement and changes in different areas. For the detailed description of the changes listed here, see Detailed Release Notes for PMD 7.
- Miscellaneous smaller changes and cleanups
- XPath 3.1 support for XPath-based rules
- Node stream API for AST traversal
- Metrics framework
- Testing framework
- Language Lifecycle and Language Properties
💥 Compatibility and migration notes
See Detailed Release Notes for PMD 7.
🐛 Fixed Issues
- miscellaneous
- #881: [all] Breaking API changes for 7.0.0
- #896: [all] Use slf4j
- #1431: [ui] Remove old GUI applications (designerold, bgastviewer)
- #1451: [core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string
- #2496: Update PMD 7 Logo on landing page
- #2497: PMD 7 Logo page
- #2498: Update PMD 7 Logo in documentation
- #3797: [all] Use JUnit5
- #4462: Provide Software Bill of Materials (SBOM)
- #4460: Fix assembly-plugin warnings
- ant
- #4080: [ant] Split off Ant integration into a new submodule
- core
- #880: [core] Make visitors generic
- #1622: [core] NodeStream API
- #1687: [core] Deprecate and Remove XPath 1.0 support
- #1785: [core] Allow abstract node types to be valid rulechain visits
- #1825: [core] Support NoAttribute for XPath
- #2038: [core] Remove DCD
- #2218: [core]
isFindBoundaryshould not be an attribute - #2234: [core] Consolidate PMD CLI into a single command
- #2239: [core] Merging Javacc build scripts
- #2500: [core] Clarify API for ANTLR based languages
- #2518: [core] Language properties
- #2602: [core] Remove ParserOptions
- #2614: [core] Upgrade Saxon, add XPath 3.1, remove Jaxen
- #2696: [core] Remove DFA
- #2821: [core] Rule processing error filenames are missing paths
- #2873: [core] Utility classes in pmd 7
- #2885: [core] Error recovery mode
- #3203: [core] Replace RuleViolationFactory implementations with ViolationDecorator
- #3692: [core] Analysis listeners
- #3782: [core] Language lifecycle
- #3815: [core] Update Saxon HE to 10.7
- #3893: [core] Text documents
- #3902: [core] Violation decorators
- #3918: [core] Make LanguageRegistry non static
- #3922: [core] Better error reporting for the ruleset parser
- #4035: [core] ConcurrentModificationException in DefaultRuleViolationFactory
- #4120: [core] Explicitly name all language versions
- #4353: [core] Micro optimizations for Node API
- #4365: [core] Improve benchmarking
- #4420: [core] Remove PMD.EOL
- #4425: [core] Replace TextFile::pathId
- #4454: [core] “Unknown option: ‘-min’” but is referenced in documentation
- cli
- doc
- testing
Language specific fixes:
- apex
- apex-design
- java
- #520: [java] Allow
@SuppressWarningswith constants instead of literals - #864: [java] Similar/duplicated implementations for determining FQCN
- #905: [java] Add new node for anonymous class declaration
- #910: [java] AST inconsistency between primitive and reference type arrays
- #997: [java] Java8 parsing corner case with annotated array types
- #998: [java] AST inconsistencies around FormalParameter
- #1019: [java] Breaking Java Grammar changes for PMD 7.0.0
- #1124: [java] ImmutableList implementation in the qname codebase
- #1128: [java] Improve ASTLocalVariableDeclaration
- #1150: [java] ClassOrInterfaceType AST improvements
- #1207: [java] Resolve explicit types using FQCNs, without hitting the classloader
- #1367: [java] Parsing error on annotated inner class
- #1661: [java] About operator nodes
- #2366: [java] Remove qualified names
- #2819: [java] GLB bugs in pmd 7
- #3642: [java] Parse error on rare extra dimensions on method return type on annotation methods
- #3763: [java] Ambiguous reference error in valid code
- #3749: [java] Improve
isOverriddenin ASTMethodDeclaration - #3750: [java] Make symbol table support instanceof pattern bindings
- #3752: [java] Expose annotations in symbol API
- #4237: [java] Cleanup handling of Java comments
- #4317: [java] Some AST nodes should not be TypeNodes
- #4359: [java] Type resolution fails with NPE when the scope is not a type declaration
- #4367: [java] Move testrule TypeResTest into internal
- #4383: [java] IllegalStateException: Object is not an array type!
- #4405: [java] Processing error with ArrayIndexOutOfBoundsException
- #520: [java] Allow
- java-bestpractices
- #342: [java] AccessorMethodGeneration: Name clash with another public field not properly handled
- #755: [java] AccessorClassGeneration false positive for private constructors
- #770: [java] UnusedPrivateMethod yields false positive for counter-variant arguments
- #807: [java] AccessorMethodGeneration false positive with overloads
- #833: [java] ForLoopCanBeForeach should consider iterating on this
- #1189: [java] UnusedPrivateMethod false positive from inner class via external class
- #1205: [java] Improve ConstantsInInterface message to mention alternatives
- #1212: [java] Don’t raise JUnitTestContainsTooManyAsserts on JUnit 5’s assertAll
- #1422: [java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field
- #1455: [java] JUnitTestsShouldIncludeAssert: False positives for assert methods named “check” and “verify”
- #1563: [java] ForLoopCanBeForeach false positive with method call using index variable
- #1565: [java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ
- #1747: [java] PreserveStackTrace false-positive
- #1969: [java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class
- #1998: [java] AccessorClassGeneration false-negative: subclass calls private constructor
- #2130: [java] UnusedLocalVariable: false-negative with array
- #2147: [java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods
- #2464: [java] LooseCoupling must ignore class literals: ArrayList.class
- #2542: [java] UseCollectionIsEmpty can not detect the case
foo.bar().size() - #2650: [java] UseTryWithResources false positive when AutoCloseable helper used
- #2796: [java] UnusedAssignment false positive with call chains
- #2797: [java] MissingOverride long-standing issues
- #2806: [java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches
- #2822: [java] LooseCoupling rule: Extend to cover user defined implementations and interfaces
- #2843: [java] Fix UnusedAssignment FP with field accesses
- #2882: [java] UseTryWithResources - false negative for explicit close
- #2883: [java] JUnitAssertionsShouldIncludeMessage false positive with method call
- #2890: [java] UnusedPrivateMethod false positive with generics
- #2946: [java] SwitchStmtsShouldHaveDefault false positive on enum inside enums
- #3672: [java] LooseCoupling - fix false positive with generics
- #3675: [java] MissingOverride - fix false positive with mixing type vars
- #3858: [java] UseCollectionIsEmpty should infer local variable type from method invocation
- #4433: [java] [7.0-rc1] ReplaceHashtableWithMap on java.util.Properties
- #4492: [java] GuardLogStatement gives false positive when argument is a Java method reference
- #4503: [java] JUnitTestsShouldIncludeAssert: false negative with TestNG
- #4516: [java] UnusedLocalVariable: false-negative with try-with-resources
- #4517: [java] UnusedLocalVariable: false-negative with compound assignments
- #4518: [java] UnusedLocalVariable: false-positive with multiple for-loop indices
- java-codestyle
- #1208: [java] PrematureDeclaration rule false-positive on variable declared to measure time
- #1429: [java] PrematureDeclaration as result of method call (false positive)
- #1480: [java] IdenticalCatchBranches false positive with return expressions
- #1673: [java] UselessParentheses false positive with conditional operator
- #1790: [java] UnnecessaryFullyQualifiedName false positive with enum constant
- #1918: [java] UselessParentheses false positive with boolean operators
- #2134: [java] PreserveStackTrace not handling
Throwable.addSuppressed(...) - #2299: [java] UnnecessaryFullyQualifiedName false positive with similar package name
- #2391: [java] UseDiamondOperator FP when expected type and constructed type have a different parameterization
- #2528: [java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest
- #2739: [java] UselessParentheses false positive for string concatenation
- #2748: [java] UnnecessaryCast false positive with unchecked cast
- #2973: [java] New rule: UnnecessaryBoxing
- #3195: [java] Improve rule UnnecessaryReturn to detect more cases
- #3218: [java] Generalize UnnecessaryCast to flag all unnecessary casts
- #3221: [java] PrematureDeclaration false positive for unused variables
- #3238: [java] Improve ExprContext, fix FNs of UnnecessaryCast
- #3500: [java] UnnecessaryBoxing - check for Integer.valueOf(String) calls
- #4268: [java] CommentDefaultAccessModifier: false positive with TestNG annotations
- #4273: [java] CommentDefaultAccessModifier ignoredAnnotations should include “org.junit.jupiter.api.extension.RegisterExtension” by default
- #4357: [java] Fix IllegalStateException in UseDiamondOperator rule
- #4432: [java] [7.0-rc1] UnnecessaryImport - Unused static import is being used
- #4455: [java] FieldNamingConventions: false positive with lombok’s @UtilityClass
- #4487: [java] UnnecessaryConstructor: false-positive with @Inject and @Autowired
- #4511: [java] LocalVariableCouldBeFinal shouldn’t report unused variables
- #4512: [java] MethodArgumentCouldBeFinal shouldn’t report unused parameters
- #4557: [java] UnnecessaryImport FP with static imports of overloaded methods
- java-design
- #1014: [java] LawOfDemeter: False positive with lambda expression
- #1605: [java] LawOfDemeter: False positive for standard UTF-8 charset name
- #2160: [java] Issues with Law of Demeter
- #2175: [java] LawOfDemeter: False positive for chained methods with generic method call
- #2179: [java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property
- #2180: [java] LawOfDemeter: False positive with Thread and ThreadLocalRandom
- #2182: [java] LawOfDemeter: False positive with package-private access
- #2188: [java] LawOfDemeter: False positive with fields assigned to local vars
- #2536: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can’t detect inner class
- #3668: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes
- #3754: [java] SingularField false positive with read in while condition
- #3786: [java] SimplifyBooleanReturns should consider operator precedence
- #3840: [java] LawOfDemeter disallows method call on locally created object
- #4238: [java] Make LawOfDemeter not use the rulechain
- #4254: [java] ImmutableField - false positive with Lombok @Setter
- #4434: [java] [7.0-rc1] ExceptionAsFlowControl when simply propagating
- #4456: [java] FinalFieldCouldBeStatic: false positive with lombok’s @UtilityClass
- #4477: [java] SignatureDeclareThrowsException: false-positive with TestNG annotations
- #4490: [java] ImmutableField - false negative with Lombok @Getter
- #4549: [java] Make LawOfDemeter results deterministic
- java-documentation
- java-errorprone
- #659: [java] MissingBreakInSwitch - last default case does not contain a break
- #1005: [java] CloneMethodMustImplementCloneable triggers for interfaces
- #1669: [java] NullAssignment - FP with ternay and null as constructor argument
- #1899: [java] Recognize @SuppressWanings(“fallthrough”) for MissingBreakInSwitch
- #2320: [java] NullAssignment - FP with ternary and null as method argument
- #2532: [java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case
new BigDecimal(Expression) - #2579: [java] MissingBreakInSwitch detects the lack of break in the last case
- #2880: [java] CompareObjectsWithEquals - false negative with type res
- #2893: [java] Remove special cases from rule EmptyCatchBlock
- #2894: [java] Improve MissingBreakInSwitch
- #3071: [java] BrokenNullCheck FP with PMD 6.30.0
- #3087: [java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion
- #3100: [java] UseCorrectExceptionLogging FP in 6.31.0
- #3173: [java] UseProperClassLoader false positive
- #3351: [java] ConstructorCallsOverridableMethod ignores abstract methods
- #3400: [java] AvoidUsingOctalValues FN with underscores
- #3843: [java] UseEqualsToCompareStrings should consider return type
- #4063: [java] AvoidBranchingStatementAsLastInLoop: False-negative about try/finally block
- #4356: [java] Fix NPE in CloseResourceRule
- #4449: [java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression
- #4457: [java] OverrideBothEqualsAndHashcode: false negative with anonymous classes
- #4493: [java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject
- #4505: [java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1
- #4510: [java] ConstructorCallsOverridableMethod: false positive with lombok’s @Value
- #4513: [java] UselessOperationOnImmutable various false negatives with String
- #4514: [java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true
- #4546: [java] OverrideBothEqualsAndHashCode ignores records
- java-multithreading
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
this.run() - #2538: [java] DontCallThreadRun can’t detect the case that call run() in
foo.bar.run() - #2577: [java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument:
foo.notify(bar) - #4483: [java] NonThreadSafeSingleton false positive with double-checked locking
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
- java-performance
- #1224: [java] InefficientEmptyStringCheck false negative in anonymous class
- #2587: [java] AvoidArrayLoops could also check for list copy through iterated List.add()
- #2712: [java] SimplifyStartsWith false-positive with AssertJ
- #3486: [java] InsufficientStringBufferDeclaration: Fix NPE
- #3848: [java] StringInstantiation: false negative when using method result
- #4070: [java] A false positive about the rule RedundantFieldInitializer
- #4458: [java] RedundantFieldInitializer: false positive with lombok’s @Value
- kotlin
- swift
- xml
- #1800: [xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper
✨ External Contributions
- #1658: [core] Node support for Antlr-based languages - Matías Fraga (@matifraga)
- #1698: [core] [swift] Antlr Base Parser adapter and Swift Implementation - Lucas Soncini (@lsoncini)
- #1774: [core] Antlr visitor rules - Lucas Soncini (@lsoncini)
- #1877: [swift] Feature/swift rules - Matías Fraga (@matifraga)
- #1881: [doc] Add ANTLR documentation - Matías Fraga (@matifraga)
- #1882: [swift] UnavailableFunction Swift rule - Tomás de Lucca (@tomidelucca)
- #2830: [apex] Apexlink POC - Kevin Jones (@nawforce)
- #3866: [core] Add CLI Progress Bar - @JerritEic (@JerritEic)
- #4402: [javascript] CPD: add support for Typescript using antlr4 grammar - Paul Guyot (@pguyot)
- #4403: [julia] CPD: Add support for Julia code duplication - Wener (@wener-tiobe)
- #4412: [doc] Added new error msg to ConstantsInInterface - David Ljunggren (@dague1)
- #4426: [cpd] New XML to HTML XLST report format for PMD CPD - mohan-chinnappan-n (@mohan-chinnappan-n)
- #4428: [apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - Steven Stearns (@sfdcsteve)
- #4431: [coco] CPD: Coco support for code duplication detection - Wener (@wener-tiobe)
- #4444: [java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - Nirvik Patel (@nirvikpatel)
- #4450: [java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - Seren (@mohui1999)
- #4452: [doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - nwcm (@nwcm)
- #4470: [cpp] CPD: Added strings as literal and ignore identifiers in sequences - Wener (@wener-tiobe)
- #4474: [java] ImmutableField: False positive with lombok (fixes #4254) - Pim van der Loos (@PimvanderLoos)
- #4488: [java] Fix #4477: A false-positive about SignatureDeclareThrowsException - AnnaDev (@LynnBroe)
- #4494: [java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - AnnaDev (@LynnBroe)
- #4495: [java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - AnnaDev (@LynnBroe)
- #4507: [java] Fix #4503: A false negative about JUnitTestsShouldIncludeAssert and testng - AnnaDev (@LynnBroe)
- #4520: [doc] Fix typo: missing closing quotation mark after CPD-END - João Dinis Ferreira (@joaodinissf)
- #4533: [java] Fix #4063: False-negative about try/catch block in Loop - AnnaDev (@LynnBroe)
- #4536: [java] Fix #4268: CommentDefaultAccessModifier - false positive with TestNG’s @Test annotation - AnnaDev (@LynnBroe)
- #4537: [java] Fix #4455: A false positive about FieldNamingConventions and UtilityClass - AnnaDev (@LynnBroe)
- #4538: [java] Fix #4456: A false positive about FinalFieldCouldBeStatic and UtilityClass - AnnaDev (@LynnBroe)
- #4540: [java] Fix #4457: false negative about OverrideBothEqualsAndHashcode - AnnaDev (@LynnBroe)
- #4541: [java] Fix #4458: A false positive about RedundantFieldInitializer and @Value - AnnaDev (@LynnBroe)
- #4542: [java] Fix #4510: A false positive about ConstructorCallsOverridableMethod and @Value - AnnaDev (@LynnBroe)
- #4553: [java] Fix #4492: GuardLogStatement gives false positive when argument is a Java method reference - Anastasiia Koba (@anastasiia-koba)
📈 Stats
- 4694 commits
- 617 closed tickets & PRs
- Days since last release: 30
29-April-2023 - 7.0.0-rc2
We’re excited to bring you the next major version of PMD!
Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate page with the full Detailed Release Notes for PMD 7.0.0.
PMD 7.0.0 is finally almost ready. In order to gather feedback, we are going to ship a couple of release candidates. These are officially available on GitHub and Maven Central and can be used as usual (e.g. as a dependency). We encourage you to try out the new features, but keep in mind that we may introduce API breaking changes between the release candidates. It should be stable enough if you don't use custom rules.
We have still some tasks planned for the next release candidates. You can see the progress in PMD 7 Tracking Issue #3898.
If you find any problem or difficulty while updating from PMD 6, please provide feedback via our issue tracker. That way we can improve the experience for all.
Table Of Contents
- Changes since 7.0.0-rc1
- 🚀 Major Features and Enhancements
- 🎉 Language Related Changes
- 🌟 New and changed rules
- 🚨 API
- 💥 Compatibility and migration notes
- 🐛 Fixed Issues
- ✨ External Contributions
- 📈 Stats
Changes since 7.0.0-rc1
This section lists the most important changes from the last release candidate. The remaining section describes the complete release notes for 7.0.0.
API Changes
- Moved the two classes
AntlrTokenizerandJavaCCTokenizerfrominternalpackage into packagenet.sourceforge.pmd.cpd.impl. These two classes are part of the API and are base classes for CPD language implementations. AntlrBaseRuleis gone in favor ofAbstractVisitorRule.- The classes
KotlinInnerNodeandSwiftInnerNodeare package-private now. - The parameter order of
addSourceFilehas been swapped in order to have the same meaning as in 6.55.0. That will make it easier if you upgrade from 6.55.0 to 7.0.0. However, that means, that you need to change these method calls if you have migrated to 7.0.0-rc1 already.
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog.
Language Related Changes
- New: CPD support for TypeScript
- New: CPD support for Julia
Rule Changes
ImmutableField: the propertyignoredAnnotationshas been removed. The property was deprecated since PMD 6.52.0.SwitchDensity: the type of the propertyminimumhas been changed from decimal to integer for consistency with other statistical rules.
Fixed Issues
- cli
- core
- #2500: [core] Clarify API for ANTLR based languages
- doc
- java-codestyle
- java-design
- java-errorprone
- java-multithreading
- #4483: [java] NonThreadSafeSingleton false positive with double-checked locking
- miscellaneous
- #4462: Provide Software Bill of Materials (SBOM)
External contributions
- #4402: [javascript] CPD: add support for Typescript using antlr4 grammar - Paul Guyot (@pguyot)
- #4403: [julia] CPD: Add support for Julia code duplication - Wener (@wener-tiobe)
- #4444: [java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - Nirvik Patel (@nirvikpatel)
- #4450: [java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - Seren (@mohui1999)
- #4452: [doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - nwcm (@nwcm)
- #4474: [java] ImmutableField: False positive with lombok (fixes #4254) - Pim van der Loos (@PimvanderLoos)
- #4488: [java] Fix #4477: A false-positive about SignatureDeclareThrowsException - AnnaDev (@LynnBroe)
- #4494: [java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - AnnaDev (@LynnBroe)
- #4495: [java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - AnnaDev (@LynnBroe)
- #4520: [doc] Fix typo: missing closing quotation mark after CPD-END - João Dinis Ferreira (@joaodinissf)
🚀 Major Features and Enhancements
New official logo
The new official logo of PMD:

Revamped Java module
- Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS)
- Built-in rules have been upgraded for the changed AST
- Rewritten type resolution framework and symbol table correctly implements the JLS
- AST exposes more semantic information (method calls, field accesses)
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Clément Fournier (@oowekyala), Andreas Dangel (@adangel), Juan Martín Sotuyo Dodero (@jsotuyod)
Revamped Command Line Interface
- unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities
- single script
pmd(pmd.batfor Windows) to launch the different utilities:pmd checkto run PMD rules and analyze a projectpmd cpdto run CPD (copy paste detector)pmd designerto run the PMD Rule Designer
- progress bar support for
pmd check - shell completion

For more information, see the Detailed Release Notes for PMD 7.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Full Antlr support
- Antlr based grammars can now be used to build full-fledged PMD rules.
- Previously, Antlr grammar could only be used for CPD
- New supported languages: Swift and Kotlin
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
Updated PMD Designer
This PMD release ships a new version of the pmd-designer. For the changes, see PMD Designer Changelog.
🎉 Language Related Changes
Note that this is just a concise listing of the highlight. For more information on the languages, see the Detailed Release Notes for PMD 7.
New: Swift support
- use PMD to analyze Swift code with PMD rules
- initially 4 built-in rules
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
New: Kotlin support (experimental)
- use PMD to analyze Kotlin code with PMD rules
- Support for Kotlin 1.8 grammar
- initially 2 built-in rules
New: CPD support for TypeScript
Thanks to a contribution, CPD now supports the TypeScript language. It is shipped
with the rest of the JavaScript support in the module pmd-javascript.
Contributors: Paul Guyot (@pguyot)
New: CPD support for Julia
Thanks to a contribution, CPD now supports the Julia language. It is shipped
in the new module pmd-julia.
Contributors: Wener (@wener-tiobe)
Changed: JavaScript support
- latest version supports ES6 and also some new constructs (see Rhino])
- comments are retained
Changed: Language versions
- more predefined language versions for each supported language
- can be used to limit rule execution for specific versions only with
minimumLanguageVersionandmaximumLanguageVersionattributes.
🌟 New and changed rules
New Rules
Apex
UnusedMethodfinds unused methods in your code.
Java
UnnecessaryBoxingreports boxing and unboxing conversions that may be made implicit.
Kotlin
Swift
Changed Rules
General changes
- All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified.
The properties
topscoreandsigmahave been removed. The propertyminimumis still there, however the type is not a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL and Velocity Template Language (vm):- Apex:
ExcessiveClassLength,ExcessiveParameterList,ExcessivePublicCount,NcssConstructorCount,NcssMethodCount,NcssTypeCount - Java:
ExcessiveImports,ExcessiveParameterList,ExcessivePublicCount,SwitchDensity - PLSQL:
ExcessiveMethodLength,ExcessiveObjectLength,ExcessivePackageBodyLength,ExcessivePackageSpecificationLength,ExcessiveParameterList,ExcessiveTypeLength,NcssMethodCount,NcssObjectCount,NPathComplexity - VM:
ExcessiveTemplateLength
- Apex:
- The general property
violationSuppressXPathwhich is available for all rules to suppress warnings now uses XPath version 3.1 by default. This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. If you upgrade from PMD 6, you need to verify yourviolationSuppressXPathproperties.
Apex General changes
- The properties
cc_categories,cc_remediation_points_multiplier,cc_block_highlightinghave been removed from all rules. These properties have been deprecated since PMD 6.13.0. See issue #1648 for more details.
Java General changes
-
Violations reported on methods or classes previously reported the line range of the entire method or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. This affects various rules, e.g.
CognitiveComplexity.The report location is controlled by the overrides of the method
getReportLocationin different node types.See issue #4439 and issue #730 for more details.
Java Best Practices
ArrayIsStoredDirectly: Violations are now reported on the assignment and not anymore on the formal parameter. The reported line numbers will probably move.AvoidReassigningLoopVariables: This rule might not report anymore all reassignments of the control variable in for-loops when the propertyforReassignis set toskip. See issue #4500 for more details.LooseCoupling: The rule has a new property to allow some types to be coupled to (allowedTypes).UnusedLocalVariable: This rule has some important false-negatives fixed and finds many more cases now. For details see issues #2130, #4516, and #4517.
Java Codestyle
MethodNamingConventions: The propertycheckNativeMethodshas been removed. The property was deprecated since PMD 6.3.0. Use the propertynativePatternto control whether native methods should be considered or not.ShortVariable: This rule now also reports short enum constant names.UseDiamondOperator: The propertyjava7Compatibilityhas been removed. The rule now handles Java 7 properly without a property.UnnecessaryFullyQualifiedName: The rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise.UselessParentheses: The rule has two new properties which control how strict the rule should be applied. WithignoreClarifying(default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other propertyignoreBalancing(default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.
Java Design
CyclomaticComplexity: The propertyreportLevelhas been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods usingclassReportLevelandmethodReportLevelinstead.ImmutableField: The propertyignoredAnnotationshas been removed. The property was deprecated since PMD 6.52.0.LawOfDemeter: The rule has a new propertytrustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.NPathComplexity: The propertyminimumhas been removed. It was deprecated since PMD 6.0.0. Use the propertyreportLevelinstead.SingularField: The propertiescheckInnerClassesanddisallowNotAssignmenthave been removed. The rule is now more precise and will check these cases properly.UseUtilityClass: The propertyignoredAnnotationshas been removed.
Java Documentation
CommentContent: The propertiescaseSensitiveanddisallowedTermsare removed. The new propertyforbiddenRegexcan be used now to define the disallowed terms with a single regular expression.CommentRequired:- Overridden methods are now detected even without the
@Overrideannotation. This is relevant for the propertymethodWithOverrideCommentRequirement. See also pull request #3757. - Elements in annotation types are now detected as well. This might lead to an increased number of violations for missing public method comments.
- Overridden methods are now detected even without the
CommentSize: When determining the line-length of a comment, the leading comment prefix markers (e.g.*or//) are ignored and don’t add up to the line-length. See also pull request #4369.
Java Error Prone
AvoidDuplicateLiterals: The propertyexceptionfilehas been removed. The property was deprecated since PMD 6.10.0. Use the propertyexceptionListinstead.DontImportSun:sun.misc.Signalis not special-cased anymore.EmptyCatchBlock:CloneNotSupportedExceptionandInterruptedExceptionare not special-cased anymore. Rename the exception parameter toignoredto ignore them.ImplicitSwitchFallThrough: Violations are now reported on the case statements rather than on the switch statements. This is more accurate but might result in more violations now.
Removed Rules
Many rules, that were previously deprecated have been finally removed. See Detailed Release Notes for PMD 7 for the complete list.
🚨 API
The API of PMD has been growing over the years and needed some cleanup. The goal is, to have a clear separation between a well-defined API and the implementation, which is internal. This should help us in future development.
Also, there are some improvement and changes in different areas. For the detailed description of the changes listed here, see Detailed Release Notes for PMD 7.
- Miscellaneous smaller changes and cleanups
- XPath 3.1 support for XPath-based rules
- Node stream API for AST traversal
- Metrics framework
- Testing framework
- Language Lifecycle and Language Properties
💥 Compatibility and migration notes
See Detailed Release Notes for PMD 7.
🐛 Fixed Issues
- miscellaneous
- #881: [all] Breaking API changes for 7.0.0
- #896: [all] Use slf4j
- #1431: [ui] Remove old GUI applications (designerold, bgastviewer)
- #1451: [core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string
- #2496: Update PMD 7 Logo on landing page
- #2497: PMD 7 Logo page
- #2498: Update PMD 7 Logo in documentation
- #3797: [all] Use JUnit5
- #4462: Provide Software Bill of Materials (SBOM)
- ant
- #4080: [ant] Split off Ant integration into a new submodule
- core
- #880: [core] Make visitors generic
- #1622: [core] NodeStream API
- #1687: [core] Deprecate and Remove XPath 1.0 support
- #1785: [core] Allow abstract node types to be valid rulechain visits
- #1825: [core] Support NoAttribute for XPath
- #2038: [core] Remove DCD
- #2218: [core]
isFindBoundaryshould not be an attribute - #2234: [core] Consolidate PMD CLI into a single command
- #2239: [core] Merging Javacc build scripts
- #2500: [core] Clarify API for ANTLR based languages
- #2518: [core] Language properties
- #2602: [core] Remove ParserOptions
- #2614: [core] Upgrade Saxon, add XPath 3.1, remove Jaxen
- #2696: [core] Remove DFA
- #2821: [core] Rule processing error filenames are missing paths
- #2873: [core] Utility classes in pmd 7
- #2885: [core] Error recovery mode
- #3203: [core] Replace RuleViolationFactory implementations with ViolationDecorator
- #3692: [core] Analysis listeners
- #3782: [core] Language lifecycle
- #3815: [core] Update Saxon HE to 10.7
- #3893: [core] Text documents
- #3902: [core] Violation decorators
- #3918: [core] Make LanguageRegistry non static
- #3922: [core] Better error reporting for the ruleset parser
- #4035: [core] ConcurrentModificationException in DefaultRuleViolationFactory
- #4120: [core] Explicitly name all language versions
- #4353: [core] Micro optimizations for Node API
- #4365: [core] Improve benchmarking
- #4420: [core] Remove PMD.EOL
- cli
- doc
- testing
Language specific fixes:
- apex
- apex-design
- java
- #520: [java] Allow
@SuppressWarningswith constants instead of literals - #864: [java] Similar/duplicated implementations for determining FQCN
- #905: [java] Add new node for anonymous class declaration
- #910: [java] AST inconsistency between primitive and reference type arrays
- #997: [java] Java8 parsing corner case with annotated array types
- #998: [java] AST inconsistencies around FormalParameter
- #1019: [java] Breaking Java Grammar changes for PMD 7.0.0
- #1124: [java] ImmutableList implementation in the qname codebase
- #1128: [java] Improve ASTLocalVariableDeclaration
- #1150: [java] ClassOrInterfaceType AST improvements
- #1207: [java] Resolve explicit types using FQCNs, without hitting the classloader
- #1367: [java] Parsing error on annotated inner class
- #1661: [java] About operator nodes
- #2366: [java] Remove qualified names
- #2819: [java] GLB bugs in pmd 7
- #3642: [java] Parse error on rare extra dimensions on method return type on annotation methods
- #3763: [java] Ambiguous reference error in valid code
- #3749: [java] Improve
isOverriddenin ASTMethodDeclaration - #3750: [java] Make symbol table support instanceof pattern bindings
- #3752: [java] Expose annotations in symbol API
- #4237: [java] Cleanup handling of Java comments
- #4317: [java] Some AST nodes should not be TypeNodes
- #4359: [java] Type resolution fails with NPE when the scope is not a type declaration
- #4367: [java] Move testrule TypeResTest into internal
- #520: [java] Allow
- java-bestpractices
- #342: [java] AccessorMethodGeneration: Name clash with another public field not properly handled
- #755: [java] AccessorClassGeneration false positive for private constructors
- #770: [java] UnusedPrivateMethod yields false positive for counter-variant arguments
- #807: [java] AccessorMethodGeneration false positive with overloads
- #833: [java] ForLoopCanBeForeach should consider iterating on this
- #1189: [java] UnusedPrivateMethod false positive from inner class via external class
- #1205: [java] Improve ConstantsInInterface message to mention alternatives
- #1212: [java] Don’t raise JUnitTestContainsTooManyAsserts on JUnit 5’s assertAll
- #1422: [java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field
- #1455: [java] JUnitTestsShouldIncludeAssert: False positives for assert methods named “check” and “verify”
- #1563: [java] ForLoopCanBeForeach false positive with method call using index variable
- #1565: [java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ
- #1747: [java] PreserveStackTrace false-positive
- #1969: [java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class
- #1998: [java] AccessorClassGeneration false-negative: subclass calls private constructor
- #2130: [java] UnusedLocalVariable: false-negative with array
- #2147: [java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods
- #2464: [java] LooseCoupling must ignore class literals: ArrayList.class
- #2542: [java] UseCollectionIsEmpty can not detect the case
foo.bar().size() - #2650: [java] UseTryWithResources false positive when AutoCloseable helper used
- #2796: [java] UnusedAssignment false positive with call chains
- #2797: [java] MissingOverride long-standing issues
- #2806: [java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches
- #2822: [java] LooseCoupling rule: Extend to cover user defined implementations and interfaces
- #2843: [java] Fix UnusedAssignment FP with field accesses
- #2882: [java] UseTryWithResources - false negative for explicit close
- #2883: [java] JUnitAssertionsShouldIncludeMessage false positive with method call
- #2890: [java] UnusedPrivateMethod false positive with generics
- #2946: [java] SwitchStmtsShouldHaveDefault false positive on enum inside enums
- #3672: [java] LooseCoupling - fix false positive with generics
- #3675: [java] MissingOverride - fix false positive with mixing type vars
- #3858: [java] UseCollectionIsEmpty should infer local variable type from method invocation
- #4516: [java] UnusedLocalVariable: false-negative with try-with-resources
- #4517: [java] UnusedLocalVariable: false-negative with compound assignments
- #4518: [java] UnusedLocalVariable: false-positive with multiple for-loop indices
- java-codestyle
- #1208: [java] PrematureDeclaration rule false-positive on variable declared to measure time
- #1429: [java] PrematureDeclaration as result of method call (false positive)
- #1480: [java] IdenticalCatchBranches false positive with return expressions
- #1673: [java] UselessParentheses false positive with conditional operator
- #1790: [java] UnnecessaryFullyQualifiedName false positive with enum constant
- #1918: [java] UselessParentheses false positive with boolean operators
- #2134: [java] PreserveStackTrace not handling
Throwable.addSuppressed(...) - #2299: [java] UnnecessaryFullyQualifiedName false positive with similar package name
- #2391: [java] UseDiamondOperator FP when expected type and constructed type have a different parameterization
- #2528: [java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest
- #2739: [java] UselessParentheses false positive for string concatenation
- #2748: [java] UnnecessaryCast false positive with unchecked cast
- #2973: [java] New rule: UnnecessaryBoxing
- #3195: [java] Improve rule UnnecessaryReturn to detect more cases
- #3218: [java] Generalize UnnecessaryCast to flag all unnecessary casts
- #3221: [java] PrematureDeclaration false positive for unused variables
- #3238: [java] Improve ExprContext, fix FNs of UnnecessaryCast
- #3500: [java] UnnecessaryBoxing - check for Integer.valueOf(String) calls
- #4273: [java] CommentDefaultAccessModifier ignoredAnnotations should include “org.junit.jupiter.api.extension.RegisterExtension” by default
- #4357: [java] Fix IllegalStateException in UseDiamondOperator rule
- #4487: [java] UnnecessaryConstructor: false-positive with @Inject and @Autowired
- #4511: [java] LocalVariableCouldBeFinal shouldn’t report unused variables
- #4512: [java] MethodArgumentCouldBeFinal shouldn’t report unused parameters
- java-design
- #1014: [java] LawOfDemeter: False positive with lambda expression
- #1605: [java] LawOfDemeter: False positive for standard UTF-8 charset name
- #2160: [java] Issues with Law of Demeter
- #2175: [java] LawOfDemeter: False positive for chained methods with generic method call
- #2179: [java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property
- #2180: [java] LawOfDemeter: False positive with Thread and ThreadLocalRandom
- #2182: [java] LawOfDemeter: False positive with package-private access
- #2188: [java] LawOfDemeter: False positive with fields assigned to local vars
- #2536: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can’t detect inner class
- #3668: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes
- #3754: [java] SingularField false positive with read in while condition
- #3786: [java] SimplifyBooleanReturns should consider operator precedence
- #4238: [java] Make LawOfDemeter not use the rulechain
- #4254: [java] ImmutableField - false positive with Lombok @Setter
- #4477: [java] SignatureDeclareThrowsException: false-positive with TestNG annotations
- #4490: [java] ImmutableField - false negative with Lombok @Getter
- java-documentation
- java-errorprone
- #659: [java] MissingBreakInSwitch - last default case does not contain a break
- #1005: [java] CloneMethodMustImplementCloneable triggers for interfaces
- #1669: [java] NullAssignment - FP with ternay and null as constructor argument
- #1899: [java] Recognize @SuppressWanings(“fallthrough”) for MissingBreakInSwitch
- #2320: [java] NullAssignment - FP with ternary and null as method argument
- #2532: [java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case
new BigDecimal(Expression) - #2579: [java] MissingBreakInSwitch detects the lack of break in the last case
- #2880: [java] CompareObjectsWithEquals - false negative with type res
- #2893: [java] Remove special cases from rule EmptyCatchBlock
- #2894: [java] Improve MissingBreakInSwitch
- #3071: [java] BrokenNullCheck FP with PMD 6.30.0
- #3087: [java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion
- #3100: [java] UseCorrectExceptionLogging FP in 6.31.0
- #3173: [java] UseProperClassLoader false positive
- #3351: [java] ConstructorCallsOverridableMethod ignores abstract methods
- #3400: [java] AvoidUsingOctalValues FN with underscores
- #3843: [java] UseEqualsToCompareStrings should consider return type
- #4356: [java] Fix NPE in CloseResourceRule
- #4449: [java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression
- #4493: [java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject
- #4505: [java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1
- #4513: [java] UselessOperationOnImmutable various false negatives with String
- #4514: [java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true
- java-multithreading
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
this.run() - #2538: [java] DontCallThreadRun can’t detect the case that call run() in
foo.bar.run() - #2577: [java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument:
foo.notify(bar) - #4483: [java] NonThreadSafeSingleton false positive with double-checked locking
- #2537: [java] DontCallThreadRun can’t detect the case that call run() in
- java-performance
- #1224: [java] InefficientEmptyStringCheck false negative in anonymous class
- #2587: [java] AvoidArrayLoops could also check for list copy through iterated List.add()
- #2712: [java] SimplifyStartsWith false-positive with AssertJ
- #3486: [java] InsufficientStringBufferDeclaration: Fix NPE
- #3848: [java] StringInstantiation: false negative when using method result
- kotlin
- swift
- xml
- #1800: [xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper
✨ External Contributions
- #1658: [core] Node support for Antlr-based languages - Matías Fraga (@matifraga)
- #1698: [core] [swift] Antlr Base Parser adapter and Swift Implementation - Lucas Soncini (@lsoncini)
- #1774: [core] Antlr visitor rules - Lucas Soncini (@lsoncini)
- #1877: [swift] Feature/swift rules - Matías Fraga (@matifraga)
- #1881: [doc] Add ANTLR documentation - Matías Fraga (@matifraga)
- #1882: [swift] UnavailableFunction Swift rule - Tomás de Lucca (@tomidelucca)
- #2830: [apex] Apexlink POC - Kevin Jones (@nawforce)
- #3866: [core] Add CLI Progress Bar - @JerritEic (@JerritEic)
- #4402: [javascript] CPD: add support for Typescript using antlr4 grammar - Paul Guyot (@pguyot)
- #4403: [julia] CPD: Add support for Julia code duplication - Wener (@wener-tiobe)
- #4412: [doc] Added new error msg to ConstantsInInterface - David Ljunggren (@dague1)
- #4428: [apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - Steven Stearns (@sfdcsteve)
- #4444: [java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - Nirvik Patel (@nirvikpatel)
- #4450: [java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - Seren (@mohui1999)
- #4452: [doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - nwcm (@nwcm)
- #4474: [java] ImmutableField: False positive with lombok (fixes #4254) - Pim van der Loos (@PimvanderLoos)
- #4488: [java] Fix #4477: A false-positive about SignatureDeclareThrowsException - AnnaDev (@LynnBroe)
- #4494: [java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - AnnaDev (@LynnBroe)
- #4495: [java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - AnnaDev (@LynnBroe)
- #4520: [doc] Fix typo: missing closing quotation mark after CPD-END - João Dinis Ferreira (@joaodinissf)
📈 Stats
- 4557 commits
- 572 closed tickets & PRs
- Days since last release: 35
25-March-2023 - 7.0.0-rc1
We’re excited to bring you the next major version of PMD!
Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate page with the full Detailed Release Notes for PMD 7.0.0.
PMD 7.0.0 is finally almost ready. In order to gather feedback, we are going to ship a couple of release candidates. These are officially available on GitHub and Maven Central and can be used as usual (e.g. as a dependency). We encourage you to try out the new features, but keep in mind that we may introduce API breaking changes between the release candidates. It should be stable enough if you don't use custom rules.
We have still some tasks planned for the next release candidates. You can see the progress in PMD 7 Tracking Issue #3898.
If you find any problem or difficulty while updating from PMD 6, please provide feedback via our issue tracker. That way we can improve the experience for all.
Table Of Contents
- 🚀 Major Features and Enhancements
- 🎉 Language Related Changes
- 🌟 New and changed rules
- 🚨 API
- 💥 Compatibility and migration notes
- 🐛 Fixed Issues
- ✨ External Contributions
- 📈 Stats
🚀 Major Features and Enhancements
New official logo
The new official logo of PMD:

Revamped Java module
- Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS)
- Built-in rules have been upgraded for the changed AST
- Rewritten type resolution framework and symbol table correctly implements the JLS
- AST exposes more semantic information (method calls, field accesses)
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Clément Fournier (@oowekyala), Andreas Dangel (@adangel), Juan Martín Sotuyo Dodero (@jsotuyod)
Revamped Command Line Interface
- unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities
- single script
pmd(pmd.batfor Windows) to launch the different utilities:pmd checkto run PMD rules and analyze a projectpmd cpdto run CPD (copy paste detector)pmd designerto run the PMD Rule Designer
- progress bar support for
pmd check - shell completion

For more information, see the Detailed Release Notes for PMD 7.
Contributors: Juan Martín Sotuyo Dodero (@jsotuyod)
Full Antlr support
- Antlr based grammars can now be used to build full-fledged PMD rules.
- Previously, Antlr grammar could only be used for CPD
- New supported languages: Swift and Kotlin
For more information, see the Detailed Release Notes for PMD 7.
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
🎉 Language Related Changes
Note that this is just a concise listing of the highlight. For more information on the languages, see the Detailed Release Notes for PMD 7.
New: Swift support
- use PMD to analyze Swift code with PMD rules
- initially 4 built-in rules
Contributors: Lucas Soncini (@lsoncini), Matías Fraga (@matifraga), Tomás De Lucca (@tomidelucca)
New: Kotlin support (experimental)
- use PMD to analyze Kotlin code with PMD rules
- Support for Kotlin 1.8 grammar
- initially 2 built-in rules
Changed: JavaScript support
- latest version supports ES6 and also some new constructs (see Rhino])
- comments are retained
Changed: Language versions
- more predefined language versions for each supported language
- can be used to limit rule execution for specific versions only with
minimumLanguageVersionandmaximumLanguageVersionattributes.
🌟 New and changed rules
New Rules
Apex
UnusedMethodfinds unused methods in your code.
Java
UnnecessaryBoxingreports boxing and unboxing conversions that may be made implicit.
Kotlin
Swift
Changed Rules
Java
UnnecessaryFullyQualifiedName: the rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise.UselessParentheses: the rule has two new properties which control how strict the rule should be applied. WithignoreClarifying(default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other propertyignoreBalancing(default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.LooseCoupling: the rule has a new property to allow some types to be coupled to (allowedTypes).EmptyCatchBlock:CloneNotSupportedExceptionandInterruptedExceptionare not special-cased anymore. Rename the exception parameter toignoredto ignore them.DontImportSun:sun.misc.Signalis not special-cased anymore.UseDiamondOperator: the propertyjava7Compatibilityis removed. The rule now handles Java 7 properly without a property.SingularField: PropertiescheckInnerClassesanddisallowNotAssignmentare removed. The rule is now more precise and will check these cases properly.UseUtilityClass: The propertyignoredAnnotationshas been removed.LawOfDemeter: the rule has a new propertytrustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.CommentContent: The propertiescaseSensitiveanddisallowedTermsare removed. The new propertyfobiddenRegexcan be used now to define the disallowed terms with a single regular expression.
Removed Rules
Many rules, that were previously deprecated have been finally removed. See Detailed Release Notes for PMD 7 for the complete list.
🚨 API
The API of PMD has been growing over the years and needed some cleanup. The goal is, to have a clear separation between a well-defined API and the implementation, which is internal. This should help us in future development.
Also, there are some improvement and changes in different areas. For the detailed description of the changes listed here, see Detailed Release Notes for PMD 7.
- Miscellaneous smaller changes and cleanups
- XPath 3.1 support for XPath-based rules
- Node stream API for AST traversal
- Metrics framework
- Testing framework
- Language Lifecycle and Language Properties
💥 Compatibility and migration notes
See Detailed Release Notes for PMD 7.
🐛 Fixed Issues
- miscellaneous
- #881: [all] Breaking API changes for 7.0.0
- #896: [all] Use slf4j
- #1431: [ui] Remove old GUI applications (designerold, bgastviewer)
- #1451: [core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string
- #2496: Update PMD 7 Logo on landing page
- #2497: PMD 7 Logo page
- #2498: Update PMD 7 Logo in documentation
- #3797: [all] Use JUnit5
- ant
- #4080: [ant] Split off Ant integration into a new submodule
- core
- #880: [core] Make visitors generic
- #1622: [core] NodeStream API
- #1687: [core] Deprecate and Remove XPath 1.0 support
- #1785: [core] Allow abstract node types to be valid rulechain visits
- #1825: [core] Support NoAttribute for XPath
- #2038: [core] Remove DCD
- #2218: [core]
isFindBoundaryshould not be an attribute - #2234: [core] Consolidate PMD CLI into a single command
- #2239: [core] Merging Javacc build scripts
- #2518: [core] Language properties
- #2602: [core] Remove ParserOptions
- #2614: [core] Upgrade Saxon, add XPath 3.1, remove Jaxen
- #2696: [core] Remove DFA
- #2821: [core] Rule processing error filenames are missing paths
- #2873: [core] Utility classes in pmd 7
- #2885: [core] Error recovery mode
- #3203: [core] Replace RuleViolationFactory implementations with ViolationDecorator
- #3692: [core] Analysis listeners
- #3782: [core] Language lifecycle
- #3815: [core] Update Saxon HE to 10.7
- #3893: [core] Text documents
- #3902: [core] Violation decorators
- #3918: [core] Make LanguageRegistry non static
- #3922: [core] Better error reporting for the ruleset parser
- #4035: [core] ConcurrentModificationException in DefaultRuleViolationFactory
- #4120: [core] Explicitly name all language versions
- #4353: [core] Micro optimizations for Node API
- #4365: [core] Improve benchmarking
- #4420: [core] Remove PMD.EOL
- cli
- testing
Language specific fixes:
- apex
- apex-design
- #2667: [apex] Integrate nawforce/ApexLink to build robust Unused rule
- java
- #520: [java] Allow
@SuppressWarningswith constants instead of literals - #864: [java] Similar/duplicated implementations for determining FQCN
- #905: [java] Add new node for anonymous class declaration
- #910: [java] AST inconsistency between primitive and reference type arrays
- #997: [java] Java8 parsing corner case with annotated array types
- #998: [java] AST inconsistencies around FormalParameter
- #1019: [java] Breaking Java Grammar changes for PMD 7.0.0
- #1124: [java] ImmutableList implementation in the qname codebase
- #1128: [java] Improve ASTLocalVariableDeclaration
- #1150: [java] ClassOrInterfaceType AST improvements
- #1207: [java] Resolve explicit types using FQCNs, without hitting the classloader
- #1367: [java] Parsing error on annotated inner class
- #1661: [java] About operator nodes
- #2366: [java] Remove qualified names
- #2819: [java] GLB bugs in pmd 7
- #3763: [java] Ambiguous reference error in valid code
- #3749: [java] Improve
isOverriddenin ASTMethodDeclaration - #3750: [java] Make symbol table support instanceof pattern bindings
- #3752: [java] Expose annotations in symbol API
- #4237: [java] Cleanup handling of Java comments
- #4317: [java] Some AST nodes should not be TypeNodes
- #4359: [java] Type resolution fails with NPE when the scope is not a type declaration
- #4367: [java] Move testrule TypeResTest into internal
- #520: [java] Allow
- java-bestpractices
- #342: [java] AccessorMethodGeneration: Name clash with another public field not properly handled
- #755: [java] AccessorClassGeneration false positive for private constructors
- #770: [java] UnusedPrivateMethod yields false positive for counter-variant arguments
- #807: [java] AccessorMethodGeneration false positive with overloads
- #833: [java] ForLoopCanBeForeach should consider iterating on this
- #1189: [java] UnusedPrivateMethod false positive from inner class via external class
- #1205: [java] Improve ConstantsInInterface message to mention alternatives
- #1212: [java] Don’t raise JUnitTestContainsTooManyAsserts on JUnit 5’s assertAll
- #1422: [java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field
- #1565: [java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ
- #1747: [java] PreserveStackTrace false-positive
- #1969: [java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class
- #1998: [java] AccessorClassGeneration false-negative: subclass calls private constructor
- #2130: [java] UnusedLocalVariable: false-negative with array
- #2147: [java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods
- #2464: [java] LooseCoupling must ignore class literals: ArrayList.class
- #2542: [java] UseCollectionIsEmpty can not detect the case
foo.bar().size() - #2650: [java] UseTryWithResources false positive when AutoCloseable helper used
- #2796: [java] UnusedAssignment false positive with call chains
- #2797: [java] MissingOverride long-standing issues
- #2806: [java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches
- #2822: [java] LooseCoupling rule: Extend to cover user defined implementations and interfaces
- #2843: [java] Fix UnusedAssignment FP with field accesses
- #2882: [java] UseTryWithResources - false negative for explicit close
- #2883: [java] JUnitAssertionsShouldIncludeMessage false positive with method call
- #2890: [java] UnusedPrivateMethod false positive with generics
- #2946: [java] SwitchStmtsShouldHaveDefault false positive on enum inside enums
- #3672: [java] LooseCoupling - fix false positive with generics
- #3675: [java] MissingOverride - fix false positive with mixing type vars
- java-codestyle
- #1208: [java] PrematureDeclaration rule false-positive on variable declared to measure time
- #1429: [java] PrematureDeclaration as result of method call (false positive)
- #1673: [java] UselessParentheses false positive with conditional operator
- #1790: [java] UnnecessaryFullyQualifiedName false positive with enum constant
- #1918: [java] UselessParentheses false positive with boolean operators
- #2134: [java] PreserveStackTrace not handling
Throwable.addSuppressed(...) - #2299: [java] UnnecessaryFullyQualifiedName false positive with similar package name
- #2391: [java] UseDiamondOperator FP when expected type and constructed type have a different parameterization
- #2528: [java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest
- #2739: [java] UselessParentheses false positive for string concatenation
- #2748: [java] UnnecessaryCast false positive with unchecked cast
- #2973: [java] New rule: UnnecessaryBoxing
- #3195: [java] Improve rule UnnecessaryReturn to detect more cases
- #3218: [java] Generalize UnnecessaryCast to flag all unnecessary casts
- #3221: [java] PrematureDeclaration false positive for unused variables
- #3238: [java] Improve ExprContext, fix FNs of UnnecessaryCast
- #3500: [java] UnnecessaryBoxing - check for Integer.valueOf(String) calls
- #4357: [java] Fix IllegalStateException in UseDiamondOperator rule
- java-design
- #1014: [java] LawOfDemeter: False positive with lambda expression
- #1605: [java] LawOfDemeter: False positive for standard UTF-8 charset name
- #2175: [java] LawOfDemeter: False positive for chained methods with generic method call
- #2179: [java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property
- #2180: [java] LawOfDemeter: False positive with Thread and ThreadLocalRandom
- #2182: [java] LawOfDemeter: False positive with package-private access
- #2188: [java] LawOfDemeter: False positive with fields assigned to local vars
- #2536: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can’t detect inner class
- #3668: [java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes
- #3754: [java] SingularField false positive with read in while condition
- #3786: [java] SimplifyBooleanReturns should consider operator precedence
- #4238: [java] Make LawOfDemeter not use the rulechain
- java-documentation
- java-errorprone
- #659: [java] MissingBreakInSwitch - last default case does not contain a break
- #1005: [java] CloneMethodMustImplementCloneable triggers for interfaces
- #1669: [java] NullAssignment - FP with ternay and null as constructor argument
- #1899: [java] Recognize @SuppressWanings(“fallthrough”) for MissingBreakInSwitch
- #2320: [java] NullAssignment - FP with ternary and null as method argument
- #2532: [java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case
new BigDecimal(Expression) - #2579: [java] MissingBreakInSwitch detects the lack of break in the last case
- #2880: [java] CompareObjectsWithEquals - false negative with type res
- #2893: [java] Remove special cases from rule EmptyCatchBlock
- #2894: [java] Improve MissingBreakInSwitch
- #3071: [java] BrokenNullCheck FP with PMD 6.30.0
- #3087: [java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion
- #3100: [java] UseCorrectExceptionLogging FP in 6.31.0
- #3173: [java] UseProperClassLoader false positive
- #3351: [java] ConstructorCallsOverridableMethod ignores abstract methods
- #3400: [java] AvoidUsingOctalValues FN with underscores
- #4356: [java] Fix NPE in CloseResourceRule
- java-multithreading
- java-performance
- kotlin
- swift
- xml
- #1800: [xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper
✨ External Contributions
- #1658: [core] Node support for Antlr-based languages - Matías Fraga (@matifraga)
- #1698: [core] [swift] Antlr Base Parser adapter and Swift Implementation - Lucas Soncini (@lsoncini)
- #1774: [core] Antlr visitor rules - Lucas Soncini (@lsoncini)
- #1877: [swift] Feature/swift rules - Matías Fraga (@matifraga)
- #1881: [doc] Add ANTLR documentation - Matías Fraga (@matifraga)
- #1882: [swift] UnavailableFunction Swift rule - Tomás de Lucca (@tomidelucca)
- #2830: [apex] Apexlink POC - Kevin Jones (@nawforce)
- #3866: [core] Add CLI Progress Bar - @JerritEic (@JerritEic)
- #4412: [doc] Added new error msg to ConstantsInInterface - David Ljunggren (@dague1)
- #4428: [apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - Steven Stearns (@sfdcsteve)
📈 Stats
- 4416 commits
- 464 closed tickets & PRs
- Days since last release: 28