The property version of XPathRule is deprecated and
has been removed with PMD 7.
DOM representation of ASTs
XPath rules view the AST as an XML-like DOM, which is what the XPath language is
defined on. Concretely, this means:
Every AST node is viewed as an XML element
The element has for local name the value of getXPathNodeName
for the given node
Some Java getters are exposed as XML attributes on those elements
This means, that documentation for attributes can be found in our Javadocs. For
example, the attribute @SimpleName of the Java node EnumDeclaration is backed
by the Java getter getSimpleName.
Value conversion
To represent attributes, we must map Java values to XPath Data Model (XDM)
values. In the following table we refer to the type conversion function as conv, a function from Java types
to XDM types.
Java type T
XSD type conv(T)
int
xs:integer
long
xs:integer
double
xs:decimal
float
xs:decimal
boolean
xs:boolean
String
xs:string
Character
xs:string
Enum<E>
xs:string (uses Object::toString)
Collection<E>
conv(E)* (a sequence type)
The same conv function is used to translate rule property values to XDM values.
Additionaly, PMD’s own net.sourceforge.pmd.lang.document.Chars is also translated to a xs:string
PMD provides some language-specific XPath functions to access semantic
information from the AST.
The namespace of custom PMD functions must be explicitly mentioned.
All languages
Functions available to all languages are in the namespace pmd.
Function name
Description (click for details)
fileName
Returns the simple name of the current file
pmd:fileName() as xs:string
Returns the current simple file name, without path but including the extension.
This can be used to write rules that check file naming conventions.
Since
PMD 6.38.0
Remarks
The requires the context node to be an element
Examples
//b[pmd:fileName() = 'Foo.xml']
Matches any <b> tags in files called Foo.xml.
startLine
Returns the start line of the given node
pmd:startLine(xs:element) as xs:int
Returns the line where the node starts in the source file.
Line numbers are 1-based.
Since
PMD 6.44.0
Remarks
The function is not context-dependent, but takes a node as its first parameter.
Parameters
element as xs:element
Any element node
Examples
//b[pmd:startLine(.) > 5]
Matches any <b> node which starts after the fifth line.
endLine
Returns the end line of the given node
pmd:endLine(xs:element) as xs:int
Returns the line where the node ends in the source file.
Line numbers are 1-based.
Since
PMD 6.44.0
Remarks
The function is not context-dependent, but takes a node as its first parameter.
Parameters
element as xs:element
Any element node
Examples
//b[pmd:endLine(.) == pmd:startLine(.)]
Matches any <b> node which doesn't span more than one line.
startColumn
Returns the start column of the given node (inclusive)
pmd:startColumn(xs:element) as xs:int
Returns the column number where the node starts in the source file.
Column numbers are 1-based. The start column is inclusive.
Since
PMD 6.44.0
Remarks
The function is not context-dependent, but takes a node as its first parameter.
Parameters
element as xs:element
Any element node
Examples
//b[pmd:startColumn(.) = 1]
Matches any <b> node which starts on the first column of a line
endColumn
Returns the end column of the given node (exclusive)
pmd:endColumn(xs:element) as xs:int
Returns the column number where the node ends in the source file.
Column numbers are 1-based. The end column is exclusive.
Since
PMD 6.44.0
Remarks
The function is not context-dependent, but takes a node as its first parameter.
Parameters
element as xs:element
Any element node
Examples
//b[pmd:startLine(.) = pmd:endLine(.) and pmd:endColumn(.) - pmd:startColumn(.) = 1]
Matches any <b> node which spans exactly one character
Java
Java functions are in the namespace pmd-java.
Function name
Description (click for details)
nodeIs
Tests the runtime type of the node instance
pmd-java:nodeIs(xs:string) as xs:boolean
Returns true if the runtime type of the AST node is a subtype of the given class. Contrary to typeIs, this tests the type of the AST node. For example, the AST node for a literal (e.g. 5d) has type ASTNumericLiteral, and this function will ignore the static type of the expression (double)
Runtime error, there's no class ASTFoo in the package
typeIs
Tests a node's static type
pmd-java:typeIs(xs:string) as xs:boolean
Returns true if the context node's static Java type is a subtype of the given type. This tests for the resolved type of the Java construct, not the type of the AST node. For example, the AST node for a literal (e.g. 5d) has type ASTNumericLiteral, however this function will compare the type of the literal (eg here, double) against the argument.
Matches formal parameters of type String[] (including vararg parameters)
//VariableId[pmd-java:typeIs("java.lang.List")]
Matches variable declarators of type List or any of its subtypes (including e.g. ArrayList)
typeIsExactly
Tests a node's static type, ignoring subtypes
pmd-java:typeIsExactly(xs:string) as xs:boolean
Returns true if the context node's static type is exactly the given type. In particular, returns false if the context node's type is a subtype of the given type.
Matches variable declarators of type List (but not e.g. ArrayList)
metric
Computes and returns the value of a metric
pmd-java:metric(xs:string) as xs:decimal?
Returns the value of the metric as evaluated on the context node. If the metric cannot be computed on that node, returns an empty sequence (which is falsy).
Remarks
Parameters
metricKey as xs:string
The name of a metric in JavaMetrics (or an alias thereof).
Examples
//ClassDeclaration[metric('NCSS') > 200]
//MethodDeclaration[metric('CYCLO') > 10 and metric('NCSS') > 20]
//TypeParameter[metric('idontexist') > 50]
Error: no such metric
hasAnnotation
Tests whether an annotation is present on the node
pmd-java:hasAnnotation(xs:string) as xs:boolean
Returns true if the node has an annotation with the given qualified name
Remarks
The context node must be an Annotatable, otherwise this returns false
Matches method declarations that have a 'public' modifier, explicit or implicit. For example, this would match methods in interfaces, which implicitly have the modifier. Use the explicitModifiers function if you don't want the implicit part. Also note that @Visibility = 'public' is a better use of the API, in this particular instance.
explicitModifiers
Produce the explicit modifiers of a node
pmd-java:explicitModifiers() as xs:string*
Returns a sequence of the explicit modifiers of a node as strings. This is documented on getExplicitModifiers.
Remarks
The context node must be an ModifierOwner, otherwise this returns an empty sequence
Matches method declarations that have an explicit 'public' modifier.
matchesSig
Matches the signature called by a method or constructor call
pmd-java:matchesSig(xs:string) as xs:boolean
Uses an TypeTestUtil.InvocationMatcher to test the method signature called by the context node. The format of the parameter is described on that class.
Remarks
The context node must be an InvocationNode, otherwise this returns false