Table of Contents

31-October-2025 - 7.18.0-SNAPSHOT

The PMD team is pleased to announce PMD 7.18.0-SNAPSHOT.

This is a minor release.

🚀 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.

🌟 Rules changes

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.

Modified 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
  • apex
    • #5935: [apex] @SuppressWarnings - allow whitespace around comma when suppressing multiple rules
  • apex-design
    • #6022: [apex] ExcessiveClassLength/ExcessiveParameterList include the metric in the message
  • java
    • #4904: [java] Renderers output wrong class qualified name for nested classes
    • #6146: [java] ClassCastException: class InferenceVarSym cannot be cast to class JClassSymbol
  • java-bestpractices
    • #4122: [java] CheckResultSet false-positive with local variable
    • #6124: [java] UnusedLocalVariable: fix false negatives in pattern matching
  • 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
  • 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
  • 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)
  • #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)
  • #6130: [java] UselessParentheses: fix false positives for switch expressions - Zbynek Konecny (@zbynek)
  • #6133: [java] Fix #5042: CloseResource: fix false positive with pattern matching - Zbynek Konecny (@zbynek)
  • #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)

📦 Dependency updates

📈 Stats