AST methods returning nodes or list of nodes could be made accessible from XPath as attributes, which give back a node set. Some of the advantages:
- XPath rules could delegate some of the traversal work to Java. In cases where the node(s) to fetch might be found on different paths, this logic would be nicely hidden behind an attribute name.
- Rules would be more readable, since attribute names are more semantic than an expression.
- Rules would be less dependent on the exact structure of the AST, making them more resilient to grammar changes
- Making Java rules and XPath rules depend on the same underlying methods would enhance code reuse and make the AST API more robust overall.
In practice, I found most of our rules wouldn't need it, but some would greatly benefit from it, and future rules could be implemented more easily. For example for ControlStatementBraces, one complicated expression is duplicated because we can't bind it:
|
[count(following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement) > 1 |
|
or (some $stmt (: in only the block statements until the next label :) |
|
in following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement |
|
satisfies not($stmt/Statement/Block))] |
It would make sense to hide following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement behind a @StatementsBeforeNextLabel, which could be useful for some Java rules too.
About implementation, Saxon would let us return a Node sequence, but we'd have to expose a method on SaxonXPathRuleQuery to map PMD Nodes to saxon DocumentNodes. I don't know yet if Jaxen could support it at all.
AST methods returning nodes or list of nodes could be made accessible from XPath as attributes, which give back a node set. Some of the advantages:
In practice, I found most of our rules wouldn't need it, but some would greatly benefit from it, and future rules could be implemented more easily. For example for ControlStatementBraces, one complicated expression is duplicated because we can't bind it:
pmd/pmd-java/src/main/resources/category/java/codestyle.xml
Lines 511 to 514 in 4e29b79
It would make sense to hide
following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatementbehind a@StatementsBeforeNextLabel, which could be useful for some Java rules too.About implementation, Saxon would let us return a Node sequence, but we'd have to expose a method on SaxonXPathRuleQuery to map PMD Nodes to saxon DocumentNodes. I don't know yet if Jaxen could support it at all.