Table of Contents

2026-??-?? - 7.27.0-SNAPSHOT

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

This is a minor release.

🚀️ New and noteworthy

Updated Apex Support

The Apex language support has been bumped to version 67.0 (Summer ‘26). It supports the new Multiline String literals.

Kotlin type-aware analysis

Kotlin now supports type-aware analysis via the auxClasspath language property (see #6677). Resolved type names, return types, and annotation FQNs are available through KotlinNodeTypeData for use in Java-based rules.

Note: Type data is not yet accessible in XPath rules or the PMD Rule Designer. This will be added in the next version.

🌟️ New and Changed Rules

New Rules

  • The new java rule UnusedReturnValue finds method calls whose result is not used, although ignoring the result of these method calls is likely a mistake. The rule is referenced in the quickstart.xml ruleset for Java.

Renamed Rules

  • The rule InstantiableUtilityClass (Java Design) was renamed from UseUtilityClass to better reflect the problem. The old name still works but is deprecated.

Changed Rules

  • The rule CommentRequired (Java Documentation) has a new property packageMethodCommentRequirement. It controls whether Javadoc comments are required (or unwanted) for package-private methods and constructors. Previously, only public and protected methods could be configured (via publicMethodCommentRequirement and protectedMethodCommentRequirement). The new property defaults to Ignored, so existing rule configurations are unaffected. This was implemented in #6880.
  • The rule BooleanGetMethodName (Java Codestyle) has a new property includeWrappedType. If set to true (default), the rule treats Boolean and boolean identical. If set to false, the rule follows the bean convention and treats Boolean like any other object.

Deprecated Rules

🐛️ Fixed Issues

  • apex
    • #6478: [apex] Parser error when using CALENDAR_YEAR() in SOQL
    • #6887: [apex] ParseException on Summer ‘26 multiline string literals (‘'’…’’’)
  • apex-bestpractices
    • #5904: [apex] ApexUnitTestShouldNotUseSeeAllDataTrue violation range should only be the annotation and not the entire test method
  • chore
    • #6837: chore: Input ‘app-id’ has been deprecated with message: Use ‘client-id’ instead
  • core
    • #1995: [core] PMD should display number of rules violated or errors found
    • #4952: [doc] Improve doc around PMDConfiguration#prependAuxclasspath #setClassloader
    • #4953: [core] Deprecate PMDConfiguration#setClassloader and #getClassloader
    • #6865: [core] Include the running PMD version in the “Unable to find referenced rule” error
    • #6952: [core] Ruleset references are not resolved relative to the referencing ruleset
  • java
    • #5041: [java] Parsing failed in ParseLock#doParse(): IndexOutOfBoundsException
    • #6768: [java] Disambiguation IllegalStateException resolving a synthesized record accessor used as a call argument alongside an anonymous class
  • java-bestpractices
    • #2033: [jsp] NoClassAttribute rule is generating a false positive
    • #5514: [java] ExhaustiveSwitchHasDefault fails for non-exhaustive switch statements
    • #5670: [java] ExhaustiveSwitchHasDefault issue with final fields not initialized in constructor
    • #6200: [java] UnusedAssignment: False positive about the ++ unary operator
  • java-codestyle
    • #6958: [java] BooleanGetMethodName should have the option to treat boolean wrapper type differently
    • #6274: [java] UselessParentheses: Treat parentheses around a ternary in the else-branch as clarifying, consistent with the then-branch.
    • #6651: [java] UnnecessaryImport false-positive when Javadoc {@link} references an array type
    • #6709: [java] LambdaCanBeMethodReference: False positive with array creation containing constructor call in receiver
    • #6737: [java] TooManyStaticImports: @SuppressWarnings(“PMD.TooManyStaticImports”) has stopped working
    • #6846: [java] VariableDeclarationUsageDistance: False positive with variables grouped at the top of a block
    • #6867: [java] UnnecessaryFullyQualifiedName: ContextedAssertionError: This should be unreachable: unknown constant ScopeInfo: MODULE_IMPORT
  • java-design
    • #6714: [java] Rename UseUtilityClass to InstantiableUtilityClass
    • #6844: [java] AvoidThrowingNewInstanceOfSameException: message inconsistent with logic
    • #6881: [java] CognitiveComplexity does not count switch expressions
  • java-documentation
    • #6270: [java] CommentSize: Skip file header comments.
  • java-errorprone
    • #2840: [java] CloseResource: False positive on mocks
    • #6435: [java] UnconditionalIfStatement: False negative for negated boolean constant
    • #6547: [java] NonSerializableClass: Report non-serializable generic element/value types of collections and maps
    • #6742: [java] CloseResource: False positive when a correctly-closed resource is declared without initializer
    • #6826: [java] AssertEqualsArgumentOrder: False positive for double assertEquals
    • #6900: [java] DoubleCheckedLocking: False negative when the outer null check is written as !(x != null)
  • java-multithreading
    • #6747: [java] NonThreadSafeSingleton: False negative with ternary conditional operator
  • kotlin
    • #6795: [kotlin] Add kotlin-type-mapper infrastructure
    • #6891: [kotlin] AnnotationFqnAnnotator: @TypeName not set on UnescapedAnnotation nodes

🚨️ API Changes

Deprecations

Experimental API

  • kotlin
    • KotlinNodeTypeData: Provides the initial API to access type information on Kotlin AST nodes. It’s part of the new Kotlin type-aware analysis.

✨️ Merged pull requests

📦️ Dependency updates

📈️ Stats