[doc] Update rule writing docs (#2511)
This commit is contained in:
parent
c6d55ca059
commit
add430b038
@ -1,6 +1,6 @@
|
||||
{% for lang in site.data.xpath_funs.langs %}
|
||||
|
||||
<!-- Generates the documentation of XPath functions. -->
|
||||
<!-- Generates the documentation of XPath functions from file docs/_data/xpath_funs.yml -->
|
||||
|
||||
### {{ lang.name }}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 168 KiB |
Binary file not shown.
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 159 KiB |
@ -2,7 +2,7 @@
|
||||
title: Introduction to writing PMD rules
|
||||
tags: [extending, userdocs, getting_started]
|
||||
summary: "Writing your own PMD rules"
|
||||
last_updated: February 2020 (6.22.0)
|
||||
last_updated: December 2023 (7.0.0)
|
||||
permalink: pmd_userdocs_extending_writing_rules_intro.html
|
||||
author: Clément Fournier <clement.fournier76@gmail.com>
|
||||
---
|
||||
@ -14,19 +14,16 @@ team.
|
||||
## How rules work: the AST
|
||||
|
||||
Before running rules, PMD parses the source file into a data structure called an
|
||||
**abstract syntax tree (AST)**. This tree represents the syntactic structure of the
|
||||
**[abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree)**.
|
||||
This tree represents the syntactic structure of the
|
||||
code, and encodes syntactic relations between source code elements. For instance,
|
||||
in Java, method declarations belong to a class: in the AST, the nodes representing
|
||||
method declarations will be descendants of a node representing the declaration of
|
||||
their enclosing class. This representation is thus much richer than the original
|
||||
source code (which, for a program, is just a chain of characters), or the token
|
||||
chain produced by a lexer (which is e.g. what Checkstyle works on). For example:
|
||||
chain produced by a lexer. For example:
|
||||
|
||||
<table>
|
||||
<colgroup>
|
||||
<col width="40%" />
|
||||
<col width="70%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th>Sample code (Java)</th>
|
||||
@ -48,11 +45,11 @@ class Foo extends Object {
|
||||
|
||||
```java
|
||||
└─ CompilationUnit
|
||||
└─ TypeDeclaration
|
||||
└─ ClassOrInterfaceDeclaration "Foo"
|
||||
├─ ExtendsList
|
||||
│ └─ ClassOrInterfaceType "Object"
|
||||
└─ ClassOrInterfaceBody
|
||||
└─ ClassOrInterfaceDeclaration "Foo"
|
||||
├─ ModifierList
|
||||
├─ ExtendsList
|
||||
│ └─ ClassOrInterfaceType "Object"
|
||||
└─ ClassOrInterfaceBody
|
||||
```
|
||||
|
||||
</td>
|
||||
@ -95,6 +92,8 @@ complicated processing, to which an XPath rule couldn't scale.
|
||||
In the end, choosing one strategy or the other depends on the difficulty of what
|
||||
your rule does. I'd advise to keep to XPath unless you have no other choice.
|
||||
|
||||
Note: Despite that fact, the Java rules are written in Java, any language that PMD supports
|
||||
can be analyzed. E.g. you can write a Java rule to analyze Apex source code.
|
||||
|
||||
## XML rule definition
|
||||
|
||||
@ -103,16 +102,18 @@ case for both XPath and Java rules. To do this, the `rule` element is used, but
|
||||
instead of mentioning the `ref` attribute, it mentions the `class` attribute,
|
||||
with the implementation class of your rule.
|
||||
|
||||
* **For Java rules:** this is the class extending AbstractRule (transitively)
|
||||
* **For XPath rules:** this is `net.sourceforge.pmd.lang.rule.XPathRule`
|
||||
* **For Java rules:** this is the concrete class extending AbstractRule (transitively)
|
||||
* **For XPath rules:** this is `net.sourceforge.pmd.lang.rule.XPathRule`.
|
||||
* **For XPath rules analyzing XML-based languages:** this is `net.sourceforge.pmd.lang.xml.rule.DomXPathRule`.
|
||||
See [XPath rules in XML](pmd_languages_xml.html#xpath-rules-in-xml) for more info.
|
||||
|
||||
Example:
|
||||
Example for Java rule:
|
||||
|
||||
```xml
|
||||
<rule name="MyJavaRule"
|
||||
language="java"
|
||||
message="Violation!"
|
||||
class="com.me.MyJavaRule" >
|
||||
class="com.me.MyJavaRule">
|
||||
<description>
|
||||
Description
|
||||
</description>
|
||||
@ -120,11 +121,31 @@ Example:
|
||||
</rule>
|
||||
```
|
||||
|
||||
{% include note.html content="In PMD 7, the `language` attribute will be required on all `rule`
|
||||
elements that declare a new rule. Some base rule classes set the language implicitly in their
|
||||
constructor, and so this is not required in all cases for the rule to work. But this
|
||||
behavior will be discontinued in PMD 7, so missing `language` attributes are
|
||||
reported beginning with PMD 6.27.0 as a forward compatibility warning." %}
|
||||
Example for XPath rule:
|
||||
|
||||
```xml
|
||||
<rule name="MyXPathRule"
|
||||
language="java"
|
||||
message="Violation!"
|
||||
class="net.sourceforge.pmd.lang.rule.XPathRule">
|
||||
<description>
|
||||
Description
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<properties>
|
||||
<property name="xpath">
|
||||
<value><![CDATA[
|
||||
//ClassOrInterfaceDeclaration
|
||||
]]></value>
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
```
|
||||
|
||||
|
||||
{% include note.html content="Since PMD 7, the `language` attribute is required on all `rule`
|
||||
elements that declare a new rule. In PMD 6, this was optional, as the base rule classes sometimes set
|
||||
the language implicitly in their constructor." %}
|
||||
|
||||
## Resource index
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Writing XPath rules
|
||||
tags: [extending, userdocs]
|
||||
summary: "This page describes XPath rule support in more details"
|
||||
last_updated: February 2020 (6.22.0)
|
||||
last_updated: December 2023 (7.0.0)
|
||||
permalink: pmd_userdocs_extending_writing_xpath_rules.html
|
||||
author: Miguel Griffa <mikkey@users.sourceforge.net>, Clément Fournier <clement.fournier76@gmail.com>
|
||||
---
|
||||
@ -15,17 +15,19 @@ author: Miguel Griffa <mikkey@users.sourceforge.net>, Clément Fournier <clement
|
||||
|
||||
|
||||
This page describes some points of XPath rule support in more details. See
|
||||
also [the tutorial about how to write an XPath rule](pmd_userdocs_extending_your_first_rule.html).
|
||||
also [the tutorial about how to write a first (XPath) rule](pmd_userdocs_extending_your_first_rule.html).
|
||||
|
||||
<!-- Later we can document the specific subset of XPath features our wrappers support -->
|
||||
|
||||
## XPath version
|
||||
|
||||
PMD uses XPath 3.1 for its XPath rules since PMD 7. Before then, the default version was XPath 1.0, with opt-in support for XPath 2.0.
|
||||
PMD uses XPath 3.1 for its XPath rules since PMD 7. Before then, the default version was XPath 1.0,
|
||||
with opt-in support for XPath 2.0.
|
||||
|
||||
See [the Saxonica documentation](https://www.saxonica.com/html/documentation/expressions/xpath31new.html) for an introduction to new features in XPath 3.1.
|
||||
See [the Saxonica documentation](https://www.saxonica.com/html/documentation/expressions/xpath31new.html)
|
||||
for an introduction to new features in XPath 3.1.
|
||||
|
||||
The property `version` of XPathRule is deprecated and will be removed.
|
||||
The property `version` of {% jdoc core::lang.rule.XPathRule %} is deprecated and will be removed.
|
||||
|
||||
|
||||
## DOM representation of ASTs
|
||||
@ -38,11 +40,13 @@ defined on. Concretely, this means:
|
||||
* 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 {% jdoc java::lang.java.ast.ASTAnyTypeDeclaration#getSimpleName() %}.
|
||||
by the Java getter {% jdoc java::lang.java.ast.AbstractAnyTypeDeclaration#getSimpleName() %}.
|
||||
|
||||
### Value conversion
|
||||
|
||||
To represent attributes, we must map Java values to [XPath Data Model (XDM)](https://www.w3.org/TR/xpath-datamodel/) values. In the following table we refer to the type conversion function as `conv`, a function from Java types to XDM types.
|
||||
To represent attributes, we must map Java values to [XPath Data Model (XDM)](https://www.w3.org/TR/xpath-datamodel/)
|
||||
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)` |
|
||||
|---------------|---------------------------------------|
|
||||
@ -73,14 +77,9 @@ The same `conv` function is used to translate rule property values to XDM values
|
||||
PMD provides some language-specific XPath functions to access semantic
|
||||
information from the AST.
|
||||
|
||||
On XPath 2.0, the namespace of custom PMD function must be explicitly mentioned.
|
||||
The namespace of custom PMD functions must be explicitly mentioned.
|
||||
|
||||
{% render %}
|
||||
{% include custom/xpath_fun_doc.html %}
|
||||
{% endrender %}
|
||||
|
||||
{% include note.html content='There is also a `typeOf` function which is
|
||||
deprecated and whose usages should be replaced with uses of `typeIs` or
|
||||
`typeIsExactly`. That one will be removed with PMD 7.0.0.' %}
|
||||
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: Your first rule XPath
|
||||
title: Your first rule
|
||||
tags: [extending, userdocs]
|
||||
summary: "Introduction to rule writing through an example."
|
||||
last_updated: February 2020 (6.22.0)
|
||||
summary: "Introduction to rule writing through an example for a XPath rule."
|
||||
last_updated: December 2023 (7.0.0)
|
||||
permalink: pmd_userdocs_extending_your_first_rule.html
|
||||
author: Miguel Griffa <mikkey@users.sourceforge.net>, Clément Fournier <clement.fournier76@gmail.com>
|
||||
---
|
||||
@ -11,7 +11,7 @@ This page is a gentle introduction to rule writing, and the Rule Designer.
|
||||
|
||||
Using the designer is useful both to write Java
|
||||
rules and XPath rules, but it's more specifically geared towards XPath rules.
|
||||
This page uses a simple XPath rule to illustrate the common workflow. We assume
|
||||
This page uses a **simple XPath rule** to illustrate the common workflow. We assume
|
||||
here that you already know what XPath is and how to read basic XPath queries. W3C
|
||||
has a good tutorial [here](https://www.w3schools.com/xml/xpath_syntax.asp) if
|
||||
you don't (in the context of XML only), and [the Saxon documentation](https://www.saxonica.com/documentation/index.html#!expressions)
|
||||
@ -35,11 +35,11 @@ The interface looks like the following:
|
||||
{% include image.html file="userdocs/designer-overview-with-nums.png" alt="Designer overview" %}
|
||||
|
||||
The zone (2) is the **main editor**. When you write a code snippet in the
|
||||
code area to the left, you'll see that the tree to the right will be updated
|
||||
automatically: it's the AST of the code.
|
||||
Note that the code snippet must be a syntactically valid compilation unit for the
|
||||
language you've chosen, e.g. for Java, a compilation unit necessarily has a top-level
|
||||
type declaration.
|
||||
code area to the left, you'll see that the tree to the right will be updated
|
||||
automatically: it's the AST of the code.
|
||||
Note that the code snippet must be a syntactically valid compilation unit for the
|
||||
language you've chosen, e.g. for Java, a compilation unit necessarily has a top-level
|
||||
type declaration.
|
||||
|
||||
If you select a node in the AST, its specific properties will also be displayed
|
||||
in the panel (1): they're the XPath attributes of the node. More on that later.
|
||||
@ -57,7 +57,7 @@ The basic development process is straightforward:
|
||||
2. Examine the AST and determine what node the violation should be reported on
|
||||
3. Write an XPath expression matching that node in the XPath editor
|
||||
4. Refine the XPath expression iteratively using different code snippets, so that
|
||||
it matches violation cases, but no other node
|
||||
it matches violation cases, but no other nodes
|
||||
5. Export your XPath expression to an XML rule element, and place it in your ruleset
|
||||
|
||||
Each time you test your rule against a different snippet, it's a good idea to
|
||||
@ -84,10 +84,10 @@ public class KeepingItSerious {
|
||||
```
|
||||
|
||||
Examining the AST, you find out that the LocalVariableDeclaration has a VariableDeclaratorId
|
||||
descendant, whose `Image` XPath attribute is exactly `bill`. You thus write your first attempt
|
||||
descendant, whose `Name` XPath attribute is exactly `bill`. You thus write your first attempt
|
||||
in the XPath editor:
|
||||
```xpath
|
||||
//VariableDeclaratorId[@Image = "bill"]
|
||||
//VariableDeclaratorId[@Name = "bill"]
|
||||
```
|
||||
|
||||
You can see the XPath result list is updated with the variable declarator.
|
||||
@ -112,13 +112,14 @@ based on your examination of the Type node of the field and local variable
|
||||
declaration nodes.
|
||||
|
||||
```xpath
|
||||
//VariableDeclaratorId[@Image = "bill" and ../../Type[@TypeImage = "short"]]
|
||||
//VariableDeclaratorId[@Image = "bill"][../../PrimitiveType[@Kind = "short"]]
|
||||
```
|
||||
|
||||
### Exporting to XML
|
||||
|
||||
You estimate that your rule is now production ready, and you'd like to use it in your ruleset.
|
||||
The `File > Export XPath to rule...` allows you to do that in a few clicks: just enter some
|
||||
The second button in the toolbar above the XPath editor (Tooltip: `Export XPath to rule...`)
|
||||
allows you to do that in a few clicks: just enter some
|
||||
additional metadata for your rule, and the popup will generate an XML element that you can
|
||||
copy-paste into your ruleset XML. The resulting element looks like so:
|
||||
|
||||
@ -126,16 +127,16 @@ copy-paste into your ruleset XML. The resulting element looks like so:
|
||||
<rule name="DontCallBossShort"
|
||||
language="java"
|
||||
message="Boss wants to talk to you."
|
||||
class="net.sourceforge.pmd.lang.rule.XPathRule" >
|
||||
class="net.sourceforge.pmd.lang.rule.XPathRule">
|
||||
<description>
|
||||
TODO
|
||||
TODO
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<properties>
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
//VariableDeclaratorId[../../Type[@TypeImage="short"] and @Image = "bill"]
|
||||
<![CDATA[
|
||||
//VariableDeclaratorId[@Image = "bill"][../../PrimitiveType[@Kind = "short"]]
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
|
@ -83,6 +83,10 @@ Once you have reviewed your ruleset(s), you can switch to PMD 7.
|
||||
Ideally, you have written good tests already for your custom rules - see [Testing your rules](pmd_userdocs_extending_testing.html).
|
||||
This helps to identify problems early on.
|
||||
|
||||
#### Ruleset XML
|
||||
The `<rule>` tag, that defines your custom rule, is required to have a `language` attribute now. This was always the
|
||||
case for XPath rules, but is now a requirement for Java rules.
|
||||
|
||||
#### XPath rules
|
||||
If you have **XPath based** rules, the first step will be to migrate to XPath 2.0 and then to XPath 3.1.
|
||||
XPath 2.0 is available in PMD 6 already and can be used right away. PMD 7 will use by default XPath 3.1 and
|
||||
@ -93,6 +97,12 @@ After you have migrated your XPath rules to XPath 2.0, remove the "version" prop
|
||||
with PMD 7. PMD 7 by default uses XPath 3.1.
|
||||
See below [XPath](#xpath-migrating-from-10-to-20) for details.
|
||||
|
||||
Additional infos:
|
||||
* The custom XPath function `typeOf` has been removed (deprecated since 6.4.0).
|
||||
Use the function `pmd-java:typeIs` or `pmd-java:typeIsExactly` instead.
|
||||
See [PMD extension functions](pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) for available
|
||||
functions.
|
||||
|
||||
#### Java rules
|
||||
If you have **Java based rules**, and you are using rulechain, this works a bit different now. The RuleChain API
|
||||
has changed, see [[core] Simplify the rulechain (#2490)](https://github.com/pmd/pmd/pull/2490) for the full details.
|
||||
|
Loading…
x
Reference in New Issue
Block a user