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

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 JUnitJupiterTestNoPrivateModifier find 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 UnnecessaryBlock reports 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 VariableDeclarationUsageDistance flags local variables that are declared far from their usage, which can make code harder to read. The rule has a property maxDistance that allows to configure the maximum allowed distance between declaration and usage.
  • The new Java rule AssertStatementInTest detects usages of assert statement in tests. These should be replaced by framework assertion methods such as assertEquals. Such methods provide better error messages and make test behave correctly when running without -ea.

Changed Rules

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 old names still work but are deprecated.

🐛️ Fixed Issues

  • core
    • #4972: [core] Update ANTLR to 4.13.2
    • #6308: [core] CPD Markdown format: Add syntax highlighting
  • 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
    • #6520: [java] DoNotUseThreads: False positive on legitimate java.lang.Thread.onSpinWait() call
    • #6636: [java] OverridingThreadRun: Fix false negatives with other methods and anonymous classes
  • kotlin
    • #6608: [kotlin] Lexer or parse errors are reported to stderr only without file context
    • #6648: [kotlin] Multi-dollar interpolation parse error in annotations
    • #6659: [kotlin] Parser hangs on complex files due to unbounded ATN prediction loop
    • #6669: [kotlin] Add AST improvements, KotlinAstUtil

🚨️ API Changes

Deprecations

Experimental API

✨️ 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 AvoidInterfaceAsMapKey reports Map declarations (fields, variables, parameters) whose key type is an interface that has at least one abstract implementing class defining equals or hashCode. Using such maps results in potentially duplicated map entries or not being able to get entries by key.
  • The new Java rule OverridingThreadRun finds overridden Thread::run methods. This is not recommended. Instead, implement Runnable and 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

📦️ 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

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 vbhtml or --format yahtml on 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 default html format 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 UnnecessaryInterfaceDeclaration detects 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 CloseResource introduces 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/Writer instances obtained from HttpServletRequest/HttpServletResponse - because the servlet container, not application code, is responsible for closing them. By default, the rule ignores InputStream/OutputStream/Reader/Writer resources returned by methods on (Http)ServletRequest and (Http)ServletResponse (both javax.servlet and jakarta.servlet).

🐛️ Fixed Issues

  • core
    • #6471: [core] BaseAntlrTerminalNode should return type instead of index for getTokenKind()
    • #6475: [core] Fix stored XSS in VBHTMLRenderer and YAHTMLRenderer
  • 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
    • #5787: [java] InvalidLogMessageFormat: False positive with lombok @Value generated methods
    • #6436: [java] CloseResource: Allow to ignore managed resources

🚨️ API Changes

Deprecations

✨️ 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: 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-OFF comment pairs. See #6417

🌟️ New and Changed Rules

New Rules

  • The new Java rule PublicMemberInNonPublicType detects 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 the public modifier can create confusion.
  • The new Java rule UnsupportedJdkApiUsage flags the use of unsupported and non-portable JDK APIs, including sun.* packages, sun.misc.Unsafe, and jdk.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 checkAddressTypes of rule AvoidUsingHardCodedIP has changed:
    • Instead of IPv4 use ipv4
    • Instead of IPv6 use ipv6
    • Instead of IPv4 mapped IPv6 use ipv4MappedIpv6
    • The old values still work, but you’ll see a deprecation warning.
  • The property nullCheckBranch of rule ConfusingTernary has changed:
    • Instead of Any use any
    • Instead of Then use then
    • Instead of Else use else
    • The old values still work, but you’ll see a deprecation warning.
  • The property typeAnnotations of rule ModifierOrder has changed:
    • Instead of ontype use onType
    • Instead of ondecl use onDecl
    • The old values still work, but you’ll see a deprecation warning.
  • The values of the properties of rule CommentRequired have changed:
    • Instead of Required use required
    • Instead of Ignored use ignored
    • Instead of Unwanted use unwanted
    • The old values still work, but you’ll see a deprecation warning.

Deprecated Rules

🐛️ 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
    • #5871: [java] Support Java 26
    • #6364: [java] Parse error with yield lambda inside switch
  • java-design
    • #6231: [java] New Rule: PublicMemberInNonPublicType
  • java-errorprone
    • #3601: [java] InvalidLogMessageFormat: False positive when final parameter is Supplier<Throwable>
    • #5882: [java] UnconditionalIfStatement: False negative when true/false is not literal but local variable
    • #5923: [java] New Rule: Catch usages of sun.misc.Unsafe or jdk.internal.misc.Unsafe
  • java-performance
    • #3857: [java] InsufficientStringBufferDeclaration: False negatives with String constants

🚨️ API Changes

Deprecations

✨️ 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

  • The Java rule OnlyOneReturn has a new property ignoredMethodNames. This property by default is set to compareTo and equals, 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
    • #6234: [java] Parser fails to parse switch expressions in super() constructor calls
    • #6299: [java] Fix grammar of switch label
  • 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
    • #6276: [java] NullAssignment: False positive when assigning null to a final field in a constructor
    • #6343: [java] MissingStaticMethodInNonInstantiatableClass: False negative when method in nested class returns null
  • java-performance
    • #4158: [java] BigIntegerInstantiation: False negative with compile-time constant
    • #4910: [java] ConsecutiveAppendsShouldReuse: False positive within if-statement without curly braces
    • #5877: [java] AvoidArrayLoops: False negative when break inside switch statement
  • 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

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 AvoidFutureAnnotation finds usages of the @Future annotation. It is a legacy way to execute asynchronous Apex code. New code should implement the Queueable interface instead.
  • The new Java rule EnumComparison finds usages of equals() on enum constants or values. Enums should be compared directly with == instead of equals() which has some advantages (e.g. static type checking at compile time).
  • The new Apex rule NcssCount replaces 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 NcssCount replaces 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

🐛️ 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
    • #5689: [java] Members of record should be in scope in record header
    • #6256: [java] java.lang.IllegalArgumentException: Invalid target type of type annotation for method or ctor type annotation: 19
  • java-bestpractices
    • #5820: [java] GuardLogStatement recognizes that a string is a compile-time constant expression only if at first position
    • #6188: [java] UnitTestShouldIncludeAssert false positive when TestNG @Test.expectedException present
    • #6193: [java] New Rule: Always compare enum values with ==
  • 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
    • #4577: [java] UseArraysAsList with condition in loop
    • #5071: [java] UseArraysAsList should not warn when elements are skipped in array
  • 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

✨️ 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

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 IdenticalConditionalBranches finds conditional statements that do the same thing when the condition is true and false. This is either incorrect or redundant.
  • The new Java rule LabeledStatement finds 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 UnusedLabel finds 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

  • ConfusingTernary has a new property nullCheckBranch to control, whether null-checks should be allowed (the default case) or should lead to a violation.
  • AvoidCatchingGenericException is now configurable with the new property typesThatShouldNotBeCaught.
    ⚠️ 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

🐛️ 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
    • #4904: [java] Renderers output wrong class qualified name for nested classes
    • #6127: [java] Incorrect variable name in violation
    • #6132: [java] Implement main method launch protocol priorities
    • #6146: [java] ClassCastException: class InferenceVarSym cannot be cast to class JClassSymbol
  • 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
    • #1499: [java] AvoidDeeplyNestedIfStmts violations can be unintentionally undetected
    • #5569: [java] ExcessivePublicCount should report number of public “things”
  • java-documentation
    • #6058: [java] DanglingJavadoc FP in module-info files
    • #6103: [java] DanglingJavadoc false positive on record compact constructors
  • 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

✨️ 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

✨ 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 AnnotationsNamingConventions enforces that annotations are used consistently in PascalCase.
    The rule is referenced in the quickstart.xml ruleset for Apex.
  • The new java rule TypeParameterNamingConventions replaces 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 OverrideBothEqualsAndHashCodeOnComparable finds missing hashCode() and/or equals() methods on types that implement Comparable. 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 the Set interface. While the Set interface relies on equals() to determine object equality, sorted sets like TreeSet use compareTo() instead. The same issue can arise when such objects are used as keys in sorted maps.
    This rule is very similar to OverrideBothEqualsAndHashcode which has always been skipping Comparable and 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 UselessPureMethodCall finds 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 RelianceOnDefaultCharset finds 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 VariableCanBeInlined finds local variables that are immediately returned or thrown. This rule replaces the old rule UnnecessaryLocalBeforeReturn which 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 CollectionTypeMismatch detects calls to collection methods where we suspect the types are incompatible. This happens for instance when you try to remove a String from a Collection<Integer>: although it is allowed to write this because remove takes an Object parameter, it is most likely a mistake.
    This rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule DanglingJavadoc finds 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 public instead of public static). It ensures modifiers appear in the correct order as recommended by the Java Language Specification.

Deprecated Rules

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
    • #4721: [core] chore: Enable XML rule MissingEncoding in dogfood ruleset
    • #5849: [core] Support Markdown Output for CPD Reports
    • #5958: [core] CSVRenderer: Add begin and end for line and columns (default off)
  • java
    • #5874: [java] Update java regression tests with Java 25 language features
    • #5960: [java] Avoid/reduce duplicate error messages for some rules
    • #6014: [java] Crash when encountering a java comment at the end of a file
  • 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
    • #4911: [java] AvoidRethrowingException should allow rethrowing exception subclasses
    • #5023: [java] UseUtilityClass implementation hardcodes a message instead of using the one defined in the XML
  • 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 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

✨ 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

🚀 New: Java 25 Support

This release of PMD brings support for Java 25.

There are the following new standard language features:

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: ReplaceJavaUtilCalendar and ReplaceJavaUtilDate. These rules help to migrate away from old Java APIs around java.util.Calendar and java.util.Date. It is recommended to use the modern java.time API instead, which is available since Java 8.

🐛 Fixed Issues

  • core
    • #4328: [ci] Improve Github Actions Workflows
    • #5597: [core] POM Incompatibility with Maven 4
  • java
    • #5344: [java] IllegalArgumentException: Invalid type reference for method or ctor type annotation: 16
    • #5478: [java] Support Java 25
  • java-codestyle
    • #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

✨ Merged pull requests

📦 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

✨ New Rules

  • The new Apex rule AvoidBooleanMethodParameters finds 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
    • #5785: [java] UnusedPrivateField doesn’t play well with UnnecessaryWarningSuppression
    • #5793: [java] NonExhaustiveSwitch fails on exhaustive switch with sealed class
  • java-codestyle
    • #1639: [java] UnnecessaryImport false positive for multiline @link Javadoc
    • #2304: [java] UnnecessaryImport false positive for on-demand imports in JavaDoc
    • #5832: [java] UnnecessaryImport false positive for multiline @see Javadoc
  • 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:

✨ 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

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
    • #648: [core] Warn on unneeded suppression
    • #5700: [core] Don’t accidentally catch unexpected runtime exceptions in CpdAnalysis
    • #5705: [cli] PMD’s start script fails if PMD_HOME is set
  • java-bestpractices
    • #5061: [java] UnusedLocalVariable false positive when variable is read as side effect of an assignment
    • #5621: [java] UnusedPrivateMethod with method ref
    • #5724: [java] ImplicitFunctionalInterface should not be reported on sealed interfaces
  • java-codestyle
    • #2462: [java] LinguisticNaming must ignore setters that returns current type (Builder pattern)
    • #5634: [java] CommentDefaultAccessModifier doesn’t recognize /* package */ comment at expected location for constructors
  • java-design
    • #5568: [java] High NPathComplexity in switch expression
    • #5647: [java] NPathComplexity does not account for returns
  • 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 --exclude and --non-recursive.
  • The option --ignore-list in PMD is renamed to --exclude-file-list.

Deprecations

Experimental

✨ Merged pull requests

📦 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

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 TypeShadowsBuiltInNamespace finds Apex classes, enums, and interfaces that have the same name as a class, enum, or interface in the System or Schema namespace. Shadowing these namespaces in this way can lead to confusion and unexpected behavior.

🐛 Fixed Issues

  • core
    • #5438: [core] Support language dialects
    • #5448: Maintain a public PMD docker image
    • #5525: [core] Add rule priority as level to Sarif report
    • #5623: [dist] Make pmd launch script compatible with /bin/sh
  • 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

Experimental API

✨ Merged pull requests

📦 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

✨ New Rules

  • The new Java rule ImplicitFunctionalInterface reports 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
    • #2849: [java] New Rule: ImplicitFunctionalInterface
    • #5369: [java] UnusedPrivateMethod false positives with lombok.val
    • #5590: [java] LiteralsFirstInComparisonsRule not applied on constant
    • #5592: [java] UnusedAssignment false positive in record compact constructor
  • java-codestyle
    • #5079: [java] LocalVariableCouldBeFinal false-positive with lombok.val
    • #5452: [java] PackageCase: Suppression comment has no effect due to finding at wrong position in case of JavaDoc comment
  • plsql
    • #4441: [plsql] Parsing exception with XMLQUERY function in SELECT
    • #5521: [plsql] Long parse time and eventually parse error with XMLAGG order by clause

🚨 API Changes

Deprecations

✨ Merged pull requests

📦 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

✨ New Rules

  • The new Apex rule AvoidStatefulDatabaseResult detects Database.Stateful implementations 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
    • #5442: [java] StackOverflowError with recursive generic types
    • #5493: [java] IllegalArgumentException: <?> cannot be a wildcard bound
    • #5505: [java] java.lang.StackOverflowError while executing a PmdRunnable
  • java-bestpractices
    • #3359: [java] UnusedPrivateMethod does not recognize Lombok @EqualsAndHashCode.Include annotation
    • #5486: [java] UnusedPrivateMethod detected when class is referenced in another class
    • #5504: [java] UnusedAssignment false-positive in for-loop with continue
  • 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

✨ Merged pull requests

📦 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: 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:

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 ExhaustiveSwitchHasDefault finds 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
    • #5388: [apex] Parse error with time literal in SOQL query
    • #5456: [apex] Issue with java dependency apex-parser-4.3.1 but apex-parser-4.3.0 works
  • 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

📦 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

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
    • #5399: [cli] Windows: PMD fails to start with special characters in path names
    • #5401: [cli] Windows: Console output doesn’t use unicode
  • 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

✨ Merged pull requests

📦 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

New Rules

  • The new Apex rule QueueableWithoutFinalizer detects 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
    • #5302: [apex] New Rule: Queueable Should Attach Finalizer
    • #5333: [apex] Token recognition errors for string containing unicode escape sequence
  • 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
    • #5214: [java] Wrong message for LambdaCanBeMethodReference with method of enclosing class
    • #5263: [java] UnnecessaryFullyQualifiedName: false-positive in an enum that uses its own static variables
    • #5315: [java] UnnecessaryImport false positive for on-demand imports
  • java-design
    • #4763: [java] SimplifyBooleanReturns - wrong suggested solution
  • java-errorprone
    • #5070: [java] ConfusingArgumentToVarargsMethod FP when types are unresolved
  • java-performance
    • #5287: [java] TooFewBranchesForSwitch false-positive with switch using list of case constants
    • #5314: [java] InsufficientStringBufferDeclarationRule: Lack of handling for char type parameters
    • #5320: [java] UseStringBufferLength: false-negative on StringBuffer of sb.toString().equals(“”)

🚨 API Changes

Deprecations

  • pmd-coco
    • CocoBaseListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • CocoBaseVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • CocoListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • CocoParser is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • CocoVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
  • pmd-gherkin
    • GherkinBaseListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • GherkinBaseVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • GherkinListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • GherkinParser is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • GherkinVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
  • pmd-julia
    • JuliaBaseListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • JuliaBaseVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • JuliaListener is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • JuliaParser is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
    • JuliaVisitor is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
  • pmd-kotlin
    • UnicodeClasses is deprecated for removal. This class was never intended to be generated. It will be removed with no replacement.
  • pmd-xml

✨ Merged pull requests

📦 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

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

Renamed Rules

The old rule names still work but are deprecated.

🐛 Fixed Issues

  • apex-performance
    • #5270: [apex] AvoidNonRestrictiveQueries when LIMIT is followed by bind expression
  • java
    • #4532: [java] Rule misnomer for JUnit* rules
    • #5261: [java] Record patterns with empty deconstructor lists lead to NPE
  • java-bestpractices
    • #4286: [java] Rename rule SwitchStmtsShouldHaveDefault to NonExhaustiveSwitch
    • #4813: [java] SwitchStmtsShouldHaveDefault false positive with pattern matching
  • java-codestyle
    • #5253: [java] BooleanGetMethodName: False-negatives with Boolean wrapper
  • java-design
    • #5030: [java] SwitchDensity false positive with pattern matching
  • java-errorprone
    • #3362: [java] ImplicitSwitchFallThrough should consider switch expressions
    • #5067: [java] CloseResource: False positive for FileSystems.getDefault()
    • #5244: [java] UselessOperationOnImmutable should detect java.time types
    • #5257: [java] NonCaseLabelInSwitch should consider switch expressions
  • java-performance
    • #5249: [java] TooFewBranchesForASwitchStatement false positive for Pattern Matching
    • #5250: [java] TooFewBranchesForASwitchStatement should consider Switch Expressions

🚨 API Changes

✨ 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

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:

What changes?

🐛 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-suppressed needs to mention xml, html, summaryhtml
  • java
    • #5190: [java] NPE in type inference
  • java-codestyle
    • #5046: [java] LocalVariableCouldBeFinal false positive with try/catch
  • java-errorprone
    • #5068: [java] MissingStaticMethodInNonInstantiatableClass: false positive with builder pattern
    • #5207: [java] CheckSkipResult: false positve for a private method void skip(int) in a subclass of FilterInputStream

🚨 API Changes

No changes.

✨ Merged pull requests

📦 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

This release of PMD brings support for Java 23. There are no new standard language features, but a couple of preview language features:

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 AvoidSynchronizedStatement finds synchronization blocks that could cause performance issues with virtual threads due to pinning.
  • The new JavaScript rule AvoidConsoleStatements finds 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
    • #5062: [java] Support Java 23
    • #5167: [java] java.lang.IllegalArgumentException: <?> cannot be a wildcard bound
  • 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
    • #5048: [java] CognitiveComplexity: Exception when using Map.of()
    • #5162: [java] SingularField: False-positive when preceded by synchronized block
  • 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
    • JspParserImpl is deprecated now. It should have been package-private because this is an implementation class that should not be used directly.
  • pmd-plsql
    • MergeUpdateClausePrefix is 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
    • VtlParserImpl is deprecated now. It should have been package-private because this is an implementation class that should not be used directly.
  • pmd-visualforce
    • VfParserImpl is deprecated now. It should have been package-private because this is an implementation class that should not be used directly.

Experimental

✨ 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 AvoidNonRestrictiveQueries finds 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: innerClassPattern and innerInterfacePattern.

Renamed rules

  • InaccurateNumericLiteral (JavaScript Error Prone) has been renamed from InnaccurateNumericLiteral. 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
    • #5106: [java] AccessorClassGeneration: Node was null for default constructor
    • #5110: [java] UnusedPrivateMethod for method referenced by lombok.Builder.ObtainVia
    • #5117: [java] UnusedPrivateMethod for methods annotated with jakarta.annotation.PostConstruct or PreDestroy
  • java-errorprone
    • #1488: [java] MissingStaticMethodInNonInstantiatableClass: False positive with Lombok Builder on Constructor
  • javascript-errorprone
    • #2367: [javascript] InnaccurateNumericLiteral is misspelled
    • #4716: [javascript] InaccurateNumericLiteral with number 259200000
  • 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

✨ 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 UseEnumCollections reports usages for HashSet and HashMap when 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
    • #4396: [core] CPD is always case sensitive
    • #4992: [core] CPD: Include processing errors in XML report
    • #5066: [core] CPD throws java.lang.OutOfMemoryError: Java heap space (since 7.1.0)
  • apex
    • #4922: [apex] SOQL syntax error with TYPEOF in sub-query
    • #5053: [apex] CPD fails to parse string literals with escaped characters
    • #5055: [apex] SOSL syntax error with WITH USER_MODE or WITH SYSTEM_MODE
  • apex-bestpractices
    • #5000: [apex] UnusedLocalVariable FP with binds in SOSL / SOQL
  • java
    • #4885: [java] AssertionError: Method should be accessible
    • #5050: [java] Problems with pattern variables in switch branches
  • java-bestpractices
    • #577: [java] New Rule: Check that Map<K,V> is an EnumMap if K is an enum value
    • #5047: [java] UnusedPrivateMethod FP for Generics & Overloads
  • plsql
    • #1934: [plsql] ParseException with MERGE statement in anonymous block
    • #2779: [plsql] Error while parsing statement with (Oracle) DML Error Logging
    • #4270: [plsql] Parsing exception COMPOUND TRIGGER with EXCEPTION handler

🚨 API Changes

CPD Report Format XML

There are some important changes:

  1. 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.
  2. The root element pmd-cpd contains the new attributes pmdVersion, timestamp and version. The latter is the schema version and is currently “1.0.0”.
  3. 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-error to 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-errors is deprecated. By default, lexical errors are skipped but the build is failed. Use the new parameter --[no-]fail-on-error instead 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 skipLexicalError in CPDTask is deprecated and ignored. Lexical errors are now always skipped. Use the new parameter failOnError instead to control whether to fail the build or not.

Deprecated API

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
    • #4467: [core] Expose collections from getters as XPath sequence attributes
    • #4978: [core] Referenced Rulesets do not emit details on validation errors
    • #4983: [cpd] Fix CPD crashes about unicode escapes
    • #5009: [core] Kotest tests aren’t picked up by surefire
  • 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
    • #4042: [java] A false negative about the rule StringBufferInstantiationWithChar
    • #5007: [java] AvoidUsingOctalValues triggers on non-octal double literals with a leading 0
  • java-multithreading
    • #2368: [java] False positive UnsynchronizedStaticFormatter in static initializer

🚨 API Changes

Deprecated API

✨ External Contributions

  • #5020: [java] Fix AvoidUsingOctalValues false-positive - Gold856 (@Gold856)

📈 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 UnnecessaryVarargsArrayCreation reports explicit array creation when a varargs is expected. This is more heavy to read and could be simplified.
  • The new Java rule ConfusingArgumentToVarargsMethod reports 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 LambdaCanBeMethodReference reports 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

🐛 Fixed Issues

  • core
    • #494: [core] Adopt JApiCmp to enforce control over API changes
    • #4942: [core] CPD: --skip-duplicate-files has no effect (7.0.0 regression)
    • #4959: [core] Upgrade saxon to 12.4
  • cli
    • #4791: [cli] Could not find or load main class
    • #4913: [cli] cpd-gui closes immediately
  • 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
    • #4899: [java] Parsing failed in ParseLock#doParse() java.io.IOException: Stream closed
    • #4902: [java] “Bad intersection, unrelated class types” for Constable[] and Enum[]
    • #4947: [java] Broken TextBlock parser
  • 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
    • #2440: [java] FinalFieldCouldBeStatic FN when the right side of the assignment is a constant expression
    • #3694: [java] SingularField ignores static variables
    • #4873: [java] AvoidCatchingGenericException: Can no longer suppress on the exception itself
  • 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
    • #3845: [java] InsufficientStringBufferDeclaration should consider literal expression
    • #4874: [java] StringInstantiation: False-positive when using new String(charArray)
    • #4886: [java] BigIntegerInstantiation: False Positive with Java 17 and BigDecimal.TWO
  • 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

✨ 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

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:

  1. Follow the guide Upgrading PMD at Runtime
  2. 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:

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-OFF comment 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

Changed Rules

  • EmptyControlStatement: The rule has a new property to allow empty blocks when they contain a comment (allowCommentedBlocks).
  • MethodNamingConventions: The deprecated rule property skipTestMethodUnderscores has been removed. It was actually deprecated since PMD 6.15.0, but was not mentioned in the release notes back then. Use the property testPattern instead to configure valid names for test methods.
  • CommentRequired: The deprecated property headerCommentRequirement has been removed. Use the property classCommentRequirement instead.
  • NonSerializableClass: The deprecated property prefix has 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.xml
  • category/vm/bestpractices.xml ➡️ category/velocity/bestpractices.xml
  • category/vm/design.xml ➡️ category/velocity/design.xml
  • category/vm/errorprone.xml ➡️ category/velocity/errorprone.xml

Removed Rules

The following previously deprecated rules have been finally removed:

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
    • #4594: [cli] Change completion generation to runtime
    • #4685: [cli] Clarify CPD documentation, fix positional parameter handling
    • #4723: [cli] Launch fails for “bash pmd”
  • core
    • #1027: [core] Apply the new PropertyDescriptor<Pattern> type where applicable
    • #3903: [core] Consolidate n.s.pmd.reporting package
    • #3905: [core] Stabilize tree export API
    • #3917: [core] Consolidate n.s.pmd.lang.rule package
    • #4065: [core] Rename TokenMgrError to LexException, Tokenizer to CpdLexer
    • #4309: [core] Cleanups in XPath area
    • #4312: [core] Remove unnecessary property color and system property pmd.color in TextColorRenderer
    • #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-literals and --ignore-identifiers work
    • #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
    • #3766: [apex] Replace Jorje with fully open source front-end
    • #4828: [apex] Support null coalescing operator ?? (apex 60)
    • #4845: [apex] Use same ANLTR version for apex-parser
  • 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
    • #1307: [java] AccessNode API changes
    • #3751: [java] Rename some node types
    • #4628: [java] Support loading classes from java runtime images
    • #4753: [java] PMD crashes while using generics and wildcards
    • #4757: [java] Intermittent NPEs while analyzing Java code
    • #4794: [java] Support JDK 22
  • java-bestpractices
    • #4603: [java] UnusedAssignment false positive in record compact constructor
    • #4625: [java] UnusedPrivateMethod false positive: Autoboxing into Number
    • #4817: [java] UnusedPrivateMethod false-positive used in lambda
  • 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
    • #2305: [javascript] UnnecessaryBlock - false positives with destructuring assignments
    • #4673: [javascript] CPD: Added support for decorator notation
  • 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

The new official logo of PMD:

New PMD Logo

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.bat for Windows) to launch the different utilities:
    • pmd check to run PMD rules and analyze a project
    • pmd cpd to run CPD (copy paste detector)
    • pmd designer to run the PMD Rule Designer
  • Progress bar support for pmd check
  • Shell completion

Demo

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

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)

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:

PMD also supports the following preview language features:

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-OFF comment 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 minimumLanguageVersion and maximumLanguageVersion attributes.

Changed: Rule properties

  • The old deprecated classes like IntProperty and StringProperty have been removed. Please use PropertyFactory to 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 min and max attributes 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

Java

  • UnnecessaryBoxing reports boxing and unboxing conversions that may be made implicit.
  • UseExplicitTypes reports usages of var keyword, which was introduced with Java 10.

Kotlin

  • FunctionNameTooShort finds functions with a too short name.
  • OverrideBothEqualsAndHashcode finds classes with only either equals or hashCode overridden, but not both. This leads to unexpected behavior once instances of such classes are used in collections (Lists, HashMaps, …).

Swift

  • ForceCast flags all force casts, making sure you are defensively considering all types. Having the application crash shouldn’t be an option.
  • ForceTry flags all force tries, making sure you are defensively handling exceptions. Having the application crash shouldn’t be an option.
  • ProhibitedInterfaceBuilder flags 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.
  • UnavailableFunction flags any function throwing a fatalError not marked as @available(*, unavailable) to ensure no calls are actually performed in the codebase.

XML

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.

ℹ️ Release Candidates

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

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:

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
    • #4582: [dist] Download link broken
    • #4691: [CVEs] Critical and High CEVs reported on PMD and PMD dependencies
  • 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::getResource child first
  • cli
    • #4423: [cli] Fix NPE when only --file-list is specified
  • doc
    • #4294: [doc] Migration Guide for upgrading PMD 6 ➡️ 7
    • #4303: [doc] Document new property framework
    • #4521: [doc] Website is not mobile friendly
  • apex
    • #3973: [apex] Update parser to support new ‘as user’ keywords (User Mode for Database Operations)
    • #4453: [apex] [7.0-rc1] Exception while initializing Apexlink (Index 34812 out of bounds for length 34812)
  • apex-design
    • #4596: [apex] ExcessivePublicCount ignores properties
  • apex-security
    • #4646: [apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types
  • java
    • #4401: [java] PMD 7 fails to build under Java 19
    • #4583: [java] Support JDK 21 (LTS)
  • 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 IntProperty and StringProperty have been removed. Please use PropertyFactory to 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 min and max attributes 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 ➡️ use AnyTokenizer instead
    • net.sourceforge.pmd.cpd.CPD ➡️ use PmdCli from pmd-cli module for CLI support or use CpdAnalysis for programmatic API
    • net.sourceforge.pmd.cpd.GridBagHelper (now package private)
    • net.sourceforge.pmd.cpd.TokenEntry.State
    • net.sourceforge.pmd.lang.document.CpdCompat
    • net.sourceforge.pmd.properties.BooleanMultiProperty
    • net.sourceforge.pmd.properties.BooleanProperty
    • net.sourceforge.pmd.properties.CharacterMultiProperty
    • net.sourceforge.pmd.properties.CharacterProperty
    • net.sourceforge.pmd.properties.DoubleMultiProperty
    • net.sourceforge.pmd.properties.DoubleProperty
    • net.sourceforge.pmd.properties.EnumeratedMultiProperty
    • net.sourceforge.pmd.properties.EnumeratedProperty
    • net.sourceforge.pmd.properties.EnumeratedPropertyDescriptor
    • net.sourceforge.pmd.properties.FileProperty (note: without replacement)
    • net.sourceforge.pmd.properties.FloatMultiProperty
    • net.sourceforge.pmd.properties.FloatProperty
    • net.sourceforge.pmd.properties.IntegerMultiProperty
    • net.sourceforge.pmd.properties.IntegerProperty
    • net.sourceforge.pmd.properties.LongMultiProperty
    • net.sourceforge.pmd.properties.LongProperty
    • net.sourceforge.pmd.properties.MultiValuePropertyDescriptor
    • net.sourceforge.pmd.properties.NumericPropertyDescriptor
    • net.sourceforge.pmd.properties.PropertyDescriptorField
    • net.sourceforge.pmd.properties.RegexProperty
    • net.sourceforge.pmd.properties.SingleValuePropertyDescriptor
    • net.sourceforge.pmd.properties.StringMultiProperty
    • net.sourceforge.pmd.properties.StringProperty
    • net.sourceforge.pmd.properties.ValueParser
    • net.sourceforge.pmd.properties.ValueParserConstants
    • net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder
    • net.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuilder
    • net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder
    • net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilder
    • net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper
    • net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder
    • net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder
    • net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder
    • net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder
    • net.sourceforge.pmd.properties.modules.EnumeratedPropertyModule
    • net.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 ➡️ use getLocation instead
    • Match
      • #LABEL_COMPARATOR removed
      • #setMarkSet(...), #setLabel(...), #getLabel(), #addTokenEntry(...) removed
      • #getSourceCodeSlice() removed ➡️ use CPDReport#getSourceCodeSlice instead
    • TokenEntry
      • #getEOF(), #clearImages(), #getIdentifier(), #getIndex(), #setHashCode(int) removed
      • #EOF removed ➡️ use isEof instead
    • Parser.ParserTask
      • #getFileDisplayName() removed ➡️ use getFileId instead (getFileId().getAbsolutePath())

The following classes have been removed:

  • pmd-core
    • net.sourceforge.pmd.cpd.AbstractLanguage
    • net.sourceforge.pmd.cpd.AnyLanguage
    • net.sourceforge.pmd.cpd.Language
    • net.sourceforge.pmd.cpd.LanguageFactory
    • net.sourceforge.pmd.cpd.MatchAlgorithm (now package private)
    • net.sourceforge.pmd.cpd.MatchCollector (now package private)
    • net.sourceforge.pmd.cpd.SourceCode (and all inner classes like FileCodeLoader, …)
    • 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 module pmd-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
Internal APIs
Deprecated API
Experimental APIs

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-list is specified - Wener (@wener-tiobe)
  • #4665: [java] Doc: Fix references AutoClosable -> AutoCloseable - Andrey Bozhko (@AndreyBozhko)

🚀 Major Features and Enhancements

The new official logo of PMD:

New PMD Logo

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.bat for Windows) to launch the different utilities:
    • pmd check to run PMD rules and analyze a project
    • pmd cpd to run CPD (copy paste detector)
    • pmd designer to run the PMD Rule Designer
  • progress bar support for pmd check
  • shell completion

Demo

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.

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:

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 minimumLanguageVersion and maximumLanguageVersion attributes.

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 IntProperty and StringProperty have been removed. Please use PropertyFactory to 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 min and max attributes in property definitions in the XML are now optional and can appear separately or be omitted.

🌟 New and changed rules

New Rules

Apex

Java

  • UnnecessaryBoxing reports boxing and unboxing conversions that may be made implicit.

Kotlin

Swift

Changed Rules

General changes

Apex General changes

  • The properties cc_categories, cc_remediation_points_multiplier, cc_block_highlighting have 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 getReportLocation in 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 property forReassign is set to skip. 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 property checkNativeMethods has been removed. The property was deprecated since PMD 6.3.0. Use the property nativePattern to control whether native methods should be considered or not.
  • ShortVariable: This rule now also reports short enum constant names.
  • UseDiamondOperator: The property java7Compatibility has 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. With ignoreClarifying (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property ignoreBalancing (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.

Java Design

  • CyclomaticComplexity: The property reportLevel has been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using classReportLevel and methodReportLevel instead.
  • ImmutableField: The property ignoredAnnotations has been removed. The property was deprecated since PMD 6.52.0.
  • LawOfDemeter: The rule has a new property trustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.
  • NPathComplexity: The property minimum has been removed. It was deprecated since PMD 6.0.0. Use the property reportLevel instead.
  • SingularField: The properties checkInnerClasses and disallowNotAssignment have been removed. The rule is now more precise and will check these cases properly.
  • UseUtilityClass: The property ignoredAnnotations has been removed.

Java Documentation

  • CommentContent: The properties caseSensitive and disallowedTerms are removed. The new property forbiddenRegex can be used now to define the disallowed terms with a single regular expression.
  • CommentRequired:
    • Overridden methods are now detected even without the @Override annotation. This is relevant for the property methodWithOverrideCommentRequirement. 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.
  • 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 property exceptionfile has been removed. The property was deprecated since PMD 6.10.0. Use the property exceptionList instead.
  • DontImportSun: sun.misc.Signal is not special-cased anymore.
  • EmptyCatchBlock: CloneNotSupportedException and InterruptedException are not special-cased anymore. Rename the exception parameter to ignored to 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] isFindBoundary should 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::getResource child 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-list is specified
    • #4482: [cli] pmd.bat can only be executed once
    • #4484: [cli] ast-dump with no properties produce an NPE
  • doc
    • #2501: [doc] Verify ANTLR Documentation
    • #4294: [doc] Migration Guide for upgrading PMD 6 ➡️ 7
    • #4303: [doc] Document new property framework
    • #4438: [doc] Documentation links in VS Code are outdated
    • #4521: [doc] Website is not mobile friendly
  • testing
    • #2435: [test] Remove duplicated Dummy language module
    • #4234: [test] Tests that change the logging level do not work

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
    • #2667: [apex] Integrate nawforce/ApexLink to build robust Unused rule
    • #4509: [apex] ExcessivePublicCount doesn’t consider inner classes correctly
    • #4596: [apex] ExcessivePublicCount ignores properties
  • apex-security
    • #4646: [apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types
  • java
    • #520: [java] Allow @SuppressWarnings with 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 isOverridden in 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)
  • 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
    • #4369: [java] Improve CommentSize
    • #4416: [java] Fix reported line number in CommentContentRule
  • 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
  • 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
    • #419: [kotlin] Add support for Kotlin
    • #4389: [kotlin] Update grammar to version 1.8
  • swift
    • #1877: [swift] Feature/swift rules
    • #1882: [swift] UnavailableFunction Swift rule
  • 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-list is 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.

ℹ️ Release Candidates

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

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
    • #4425: [core] Replace TextFile::pathId
    • #4454: [core] “Unknown option: ‘-min’” but is referenced in documentation
  • java-bestpractices
    • #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
  • 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
    • #4434: [java] [7.0-rc1] ExceptionAsFlowControl when simply propagating
    • #4456: [java] FinalFieldCouldBeStatic: false positive with lombok’s @UtilityClass
    • #4549: [java] Make LawOfDemeter results deterministic
  • 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.PMD
      • net.sourceforge.pmd.cli.PMDCommandLineInterface
      • net.sourceforge.pmd.cli.PMDParameters
      • net.sourceforge.pmd.cli.PmdParametersParseResult
  • The asset filenames of PMD on GitHub Releases are now pmd-dist-<version>-bin.zip, pmd-dist-<version>-src.zip and pmd-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-priority was 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::getFilename with new RuleViolation#getFileId, that returns a FileId. This is an identifier for a TextFile and could represent a path name. This allows to have a separate display name, e.g. renderers use FileNameRenderer to either display the full path name or a relative path name (see Renderer#setFileNameRenderer and ConfigurableFileNameRenderer). Many places where we used a simple String for a path-like name before have been adapted to use the new FileId.

    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:

New PMD Logo

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.bat for Windows) to launch the different utilities:
    • pmd check to run PMD rules and analyze a project
    • pmd cpd to run CPD (copy paste detector)
    • pmd designer to run the PMD Rule Designer
  • progress bar support for pmd check
  • shell completion

Demo

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.

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 minimumLanguageVersion and maximumLanguageVersion attributes.

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

Java

  • UnnecessaryBoxing reports boxing and unboxing conversions that may be made implicit.

Kotlin

Swift

Changed Rules

General changes

Apex General changes

  • The properties cc_categories, cc_remediation_points_multiplier, cc_block_highlighting have 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 getReportLocation in 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 property forReassign is set to skip. 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 property checkNativeMethods has been removed. The property was deprecated since PMD 6.3.0. Use the property nativePattern to control whether native methods should be considered or not.
  • ShortVariable: This rule now also reports short enum constant names.
  • UseDiamondOperator: The property java7Compatibility has 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. With ignoreClarifying (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property ignoreBalancing (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.

Java Design

  • CyclomaticComplexity: The property reportLevel has been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using classReportLevel and methodReportLevel instead.
  • ImmutableField: The property ignoredAnnotations has been removed. The property was deprecated since PMD 6.52.0.
  • LawOfDemeter: The rule has a new property trustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.
  • NPathComplexity: The property minimum has been removed. It was deprecated since PMD 6.0.0. Use the property reportLevel instead.
  • SingularField: The properties checkInnerClasses and disallowNotAssignment have been removed. The rule is now more precise and will check these cases properly.
  • UseUtilityClass: The property ignoredAnnotations has been removed.

Java Documentation

  • CommentContent: The properties caseSensitive and disallowedTerms are removed. The new property forbiddenRegex can be used now to define the disallowed terms with a single regular expression.
  • CommentRequired:
    • Overridden methods are now detected even without the @Override annotation. This is relevant for the property methodWithOverrideCommentRequirement. 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.
  • 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 property exceptionfile has been removed. The property was deprecated since PMD 6.10.0. Use the property exceptionList instead.
  • DontImportSun: sun.misc.Signal is not special-cased anymore.
  • EmptyCatchBlock: CloneNotSupportedException and InterruptedException are not special-cased anymore. Rename the exception parameter to ignored to 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] isFindBoundary should 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
    • #2234: [core] Consolidate PMD CLI into a single command
    • #3828: [core] Progress reporting
    • #4079: [cli] Split off CLI implementation into a pmd-cli submodule
    • #4482: [cli] pmd.bat can only be executed once
    • #4484: [cli] ast-dump with no properties produce an NPE
  • doc
    • #2501: [doc] Verify ANTLR Documentation
    • #4438: [doc] Documentation links in VS Code are outdated
  • testing
    • #2435: [test] Remove duplicated Dummy language module
    • #4234: [test] Tests that change the logging level do not work

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
    • #4427: [apex] ApexBadCrypto test failing to detect inline code
  • apex-design
    • #2667: [apex] Integrate nawforce/ApexLink to build robust Unused rule
    • #4509: [apex] ExcessivePublicCount doesn’t consider inner classes correctly
  • java
    • #520: [java] Allow @SuppressWarnings with 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 isOverridden in 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
  • 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
    • #4369: [java] Improve CommentSize
    • #4416: [java] Fix reported line number in CommentContentRule
  • 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
  • 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
    • #419: [kotlin] Add support for Kotlin
    • #4389: [kotlin] Update grammar to version 1.8
  • swift
    • #1877: [swift] Feature/swift rules
    • #1882: [swift] UnavailableFunction Swift rule
  • 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.

ℹ️ Release Candidates

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

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 AntlrTokenizer and JavaCCTokenizer from internal package into package net.sourceforge.pmd.cpd.impl. These two classes are part of the API and are base classes for CPD language implementations.
  • AntlrBaseRule is gone in favor of AbstractVisitorRule.
  • The classes KotlinInnerNode and SwiftInnerNode are package-private now.
  • The parameter order of addSourceFile has 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.

  • New: CPD support for TypeScript
  • New: CPD support for Julia

Rule Changes

  • ImmutableField: the property ignoredAnnotations has been removed. The property was deprecated since PMD 6.52.0.
  • SwitchDensity: the type of the property minimum has been changed from decimal to integer for consistency with other statistical rules.

Fixed Issues

  • cli
    • #4482: [cli] pmd.bat can only be executed once
    • #4484: [cli] ast-dump with no properties produce an NPE
  • core
    • #2500: [core] Clarify API for ANTLR based languages
  • doc
    • #2501: [doc] Verify ANTLR Documentation
    • #4438: [doc] Documentation links in VS Code are outdated
  • java-codestyle
    • #4273: [java] CommentDefaultAccessModifier ignoredAnnotations should include “org.junit.jupiter.api.extension.RegisterExtension” by default
    • #4487: [java] UnnecessaryConstructor: false-positive with @Inject and @Autowired
  • java-design
    • #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-errorprone
    • #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
  • 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:

New PMD Logo

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.bat for Windows) to launch the different utilities:
    • pmd check to run PMD rules and analyze a project
    • pmd cpd to run CPD (copy paste detector)
    • pmd designer to run the PMD Rule Designer
  • progress bar support for pmd check
  • shell completion

Demo

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.

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 minimumLanguageVersion and maximumLanguageVersion attributes.

🌟 New and changed rules

New Rules

Apex

Java

  • UnnecessaryBoxing reports boxing and unboxing conversions that may be made implicit.

Kotlin

Swift

Changed Rules

General changes

Apex General changes

  • The properties cc_categories, cc_remediation_points_multiplier, cc_block_highlighting have 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 getReportLocation in 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 property forReassign is set to skip. 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 property checkNativeMethods has been removed. The property was deprecated since PMD 6.3.0. Use the property nativePattern to control whether native methods should be considered or not.
  • ShortVariable: This rule now also reports short enum constant names.
  • UseDiamondOperator: The property java7Compatibility has 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. With ignoreClarifying (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property ignoreBalancing (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions.

Java Design

  • CyclomaticComplexity: The property reportLevel has been removed. The property was deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using classReportLevel and methodReportLevel instead.
  • ImmutableField: The property ignoredAnnotations has been removed. The property was deprecated since PMD 6.52.0.
  • LawOfDemeter: The rule has a new property trustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.
  • NPathComplexity: The property minimum has been removed. It was deprecated since PMD 6.0.0. Use the property reportLevel instead.
  • SingularField: The properties checkInnerClasses and disallowNotAssignment have been removed. The rule is now more precise and will check these cases properly.
  • UseUtilityClass: The property ignoredAnnotations has been removed.

Java Documentation

  • CommentContent: The properties caseSensitive and disallowedTerms are removed. The new property forbiddenRegex can be used now to define the disallowed terms with a single regular expression.
  • CommentRequired:
    • Overridden methods are now detected even without the @Override annotation. This is relevant for the property methodWithOverrideCommentRequirement. 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.
  • 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 property exceptionfile has been removed. The property was deprecated since PMD 6.10.0. Use the property exceptionList instead.
  • DontImportSun: sun.misc.Signal is not special-cased anymore.
  • EmptyCatchBlock: CloneNotSupportedException and InterruptedException are not special-cased anymore. Rename the exception parameter to ignored to 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] isFindBoundary should 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
    • #2234: [core] Consolidate PMD CLI into a single command
    • #3828: [core] Progress reporting
    • #4079: [cli] Split off CLI implementation into a pmd-cli submodule
    • #4482: [cli] pmd.bat can only be executed once
    • #4484: [cli] ast-dump with no properties produce an NPE
  • doc
    • #2501: [doc] Verify ANTLR Documentation
    • #4438: [doc] Documentation links in VS Code are outdated
  • testing
    • #2435: [test] Remove duplicated Dummy language module
    • #4234: [test] Tests that change the logging level do not work

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
    • #4427: [apex] ApexBadCrypto test failing to detect inline code
  • apex-design
    • #2667: [apex] Integrate nawforce/ApexLink to build robust Unused rule
    • #4509: [apex] ExcessivePublicCount doesn’t consider inner classes correctly
  • java
    • #520: [java] Allow @SuppressWarnings with 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 isOverridden in 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
  • 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
    • #4369: [java] Improve CommentSize
    • #4416: [java] Fix reported line number in CommentContentRule
  • 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
  • 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
    • #419: [kotlin] Add support for Kotlin
    • #4389: [kotlin] Update grammar to version 1.8
  • swift
    • #1877: [swift] Feature/swift rules
    • #1882: [swift] UnavailableFunction Swift rule
  • 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.

ℹ️ Release Candidates

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

New official logo

The new official logo of PMD:

New PMD Logo

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.bat for Windows) to launch the different utilities:
    • pmd check to run PMD rules and analyze a project
    • pmd cpd to run CPD (copy paste detector)
    • pmd designer to run the PMD Rule Designer
  • progress bar support for pmd check
  • shell completion

Demo

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)

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 minimumLanguageVersion and maximumLanguageVersion attributes.

🌟 New and changed rules

New Rules

Apex

Java

  • UnnecessaryBoxing reports 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. With ignoreClarifying (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property ignoreBalancing (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: CloneNotSupportedException and InterruptedException are not special-cased anymore. Rename the exception parameter to ignored to ignore them.
  • DontImportSun: sun.misc.Signal is not special-cased anymore.
  • UseDiamondOperator: the property java7Compatibility is removed. The rule now handles Java 7 properly without a property.
  • SingularField: Properties checkInnerClasses and disallowNotAssignment are removed. The rule is now more precise and will check these cases properly.
  • UseUtilityClass: The property ignoredAnnotations has been removed.
  • LawOfDemeter: the rule has a new property trustRadius. This defines the maximum degree of trusted data. The default of 1 is the most restrictive.
  • CommentContent: The properties caseSensitive and disallowedTerms are removed. The new property fobiddenRegex can 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] isFindBoundary should 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
    • #2234: [core] Consolidate PMD CLI into a single command
    • #3828: [core] Progress reporting
    • #4079: [cli] Split off CLI implementation into a pmd-cli submodule
  • testing
    • #2435: [test] Remove duplicated Dummy language module
    • #4234: [test] Tests that change the logging level do not work

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
    • #4427: [apex] ApexBadCrypto test failing to detect inline code
  • apex-design
    • #2667: [apex] Integrate nawforce/ApexLink to build robust Unused rule
  • java
    • #520: [java] Allow @SuppressWarnings with 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 isOverridden in 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
  • 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
    • #4369: [java] Improve CommentSize
    • #4416: [java] Fix reported line number in CommentContentRule
  • 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
    • #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)
  • 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
  • kotlin
    • #419: [kotlin] Add support for Kotlin
    • #4389: [kotlin] Update grammar to version 1.8
  • swift
    • #1877: [swift] Feature/swift rules
    • #1882: [swift] UnavailableFunction Swift rule
  • xml
    • #1800: [xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper

✨ External Contributions

📈 Stats

  • 4416 commits
  • 464 closed tickets & PRs
  • Days since last release: 28