Table of Contents
25-September-2026 - 7.28.0-SNAPSHOT
The PMD team is pleased to announce PMD 7.28.0-SNAPSHOT.
This is a minor release.
🚀️ New and noteworthy
Kotlin XPath functions and type attributes
Type data is now accessible in XPath rules via new attributes and helper functions (see Kotlin XPath rule support):
- Attributes:
@TypeName,@ReturnTypeName,@AnnotationFqNames,@Modifiers,@Identifierare exposed on declaration nodes (property, function, class, parameter, catch, for-loop, delegation specifier, annotation nodes). pmd-kotlin:typeIs(typeName): matches if the node’s type istypeNameor a subtype.pmd-kotlin:typeIsExactly(typeName): matches the exact declared type only (no subtypes).pmd-kotlin:hasAnnotation(name): matches if the node has an annotation with the given simple or FQN.pmd-kotlin:modifiers(): returns the modifier keywords of a declaration as a sequence.pmd-kotlin:isNullable(): returnstrueif the node’s declared type is nullable (has?).pmd-kotlin:hasUnresolvedReference(): returnstrueif the node contains an unresolved reference.pmd-kotlin:matchesSig(signature): matches call sites by method signature pattern (supports wildcards).
🌟️ New and Changed Rules
New Rules
- The new Java rule
OnDemandImportreports on-demand imports, also known as wildcard imports. By default, static imports from JUnit and TestNG are allowed. The allowed static and type import packages can be configured withallowStaticImportsFromandallowTypeImportsFrom. - The new java rule
LongLiteralEndingWithLowercaseLfinds long literals ending with l. That helps to avoid confusion between numbers ending with 1 and l. Capital L should be used to define long literals. - The new java rule
TypeNameMismatchfinds types that are not defined in a .java file with the same name. Enforcing a match between source file name and type name makes it easier to find source code for given type. - The new Java rule
CStyleArrayDeclarationfinds C-style declarations of arrays (e.g.int numbers[]). That helps you use Java-style declarations (e.g.int[] numbers) consistently throughout the codebase. - The new Apex rule
ApexUnitTestClassShouldHaveRunRelevantTestsAnnotationfinds unit tests that do not use the new@IsTest(critical=true)or@IsTest(testFor='...')annotation parameters for tests. These parameters help to identify which tests should be executed during aRunRelevantTestsdeployment.Changed Rules
- The property
checkNonStaticMethodsof the ruleNonThreadSafeSingletonis now deprecated and no longer has any effect. Its implementation did the opposite of what the documentation described. The rule now always reports both static and non-static methods; previously it reported only static methods by default.
This may result in additional violations being reported.
If you want to suppress violations for non-static methods, you can use suppression via XPath, e.g.<property name="violationSuppressXPath" value=".[ancestor-or-self::MethodDeclaration[1][@Static = false()]]" /> - The property
statementOrderMattersof the ruleVariableCanBeInlinedis now deprecated. Setting it to false only risks false negatives, therefore, the property will be removed in PMD 8.0.0.
🐛️ Fixed Issues
- apex-bestpractices
- #6988: [apex] New rule: Detect usage of @IsTest(critical=true) / @IsTest(testFor=’…’) annotations (RunRelevantTests, Beta, API 66.0+)
- html
- #6135: [html] HtmlCpdLexer giving IndexOutOfBoundsException when script contains unescaped closing tag
- java
- #6926: [java] IllegalArgumentException (Mismatched list sizes) with inconsistent unresolved generic arity
- java-bestpractices
- #5940: [java] False positive in UnusedAssignment when assignment is in conditional statement
- java-codestyle
- java-design
- java-documentation
- #6450: [java] DanglingJavadoc: False positive on /// comments for Java < 23
- java-errorprone
- #1050: [java] NullAssignment: False positive inside if statement for first assignment
- #6693: [java] CloneMethodMustImplementCloneable fires inconsistently between inline
throw newand throw-via-local forms - #7009: [java] ReplaceJavaUtilDate is suppressed by using pattern variable
- #7068: [java] UnusedReturnValue reports calls made on Mockito.verify(mock)
- java-multithreading
- java-security
- kotlin
- #6677: [kotlin] Add XPath functions and type attributes for type-aware XPath rules
🚨️ API Changes
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.KotlinNodeTypeData.getTypeName(KotlinNode)andKotlinNodeTypeData.getReturnTypeName(KotlinNode)have been renamed togetTypeandgetReturnType, and now returnKotlinTypeNameinstead ofString. The correspondingInternalApiBridgesetterssetTypeName/setReturnTypeNamewere renamed tosetType/setReturnTypethe same way. This is a breaking change to this experimental API.HasTypeName: Marker interface for Kotlin AST nodes that expose a@TypeNameXPath attribute.- New XPath functions
pmd-kotlin:typeIs,pmd-kotlin:typeIsExactly,pmd-kotlin:hasAnnotation,pmd-kotlin:modifiers,pmd-kotlin:matchesSig,pmd-kotlin:isNullable,pmd-kotlin:hasUnresolvedReferencein packagenet.sourceforge.pmd.lang.kotlin.rule.xpath.internal. - New AST attribute view classes in package
net.sourceforge.pmd.lang.kotlin.ast:KtCatchBlockAttributes,KtDelegationSpecifierAttributes,KtForStatementAttributes,KtFunctionValueParameterAttributes,KtPropertyDeclarationAttributes,KtSingleAnnotationAttributes, andKtUnescapedAnnotationAttributes.