Table of Contents

12-September-2025 - 7.17.0

The PMD team is pleased to announce PMD 7.17.0.

This is a minor release.

πŸš€ 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