如何使用 XPath 检查 PMD 中的 Apex 源字符串?

How to check for an Apex source string in PMD using XPath?

PMD 源代码分析器允许将规则编写为 XPath expressions

我正在清理 Apex 代码库,我经常发现以下错误:!someCollection.isEmpty() && someCollection != null.

正确的方法是先检查是否为 null:someCollection != null && !someCollection.isEmpty().

使用我的 trusted editor 我可以使用 RegEx 查找这些项目:&& [a-zA-Z0-9]* != null。奇迹般有效。现在我尝试为其创建自定义 PMD 规则,但我的 XPath 正则表达式在 PMD Designer 中没有 return 任何值:

<rule message="Apex code must check != null before .isEmpty()" name="NullValueCheckBeforeEmptyCheck" class="net.sourceforge.pmd.lang.rule.XPathRule">
    <description>Apex code must check != null before .isEmpty()</description>
    <priority>1</priority>
    <properties>
      <property name="xpath">
        <value>
            <![CDATA[
                //*[matches(@Image,'&& [a-zA-Z0-9]* != null')]
            ]]>
        </value>
      </property>
    </properties>
  </rule>

我尝试进行初始检查 //*[matches(@Image,'if')] 但即便如此 return 也没有结果。

我错过了什么?

应触发规则的示例 Apex:

global class caseShareBatch {

<pre><code>global void execute(List&lt;Case&gt; caseShareList){
     if(!caseShareList.isEmpty() &amp;&amp; caseShareList != null) {
            insert caseShareList;
     }
}
}

您确定 PMD 支持 XPath 2.0 吗?快速浏览一下文档,这并不明显。很多时候谈论没有版本号的 XPath 的人指的是 XPath 1.0,它当然没有 matches() 功能。

PMD 使用 Apex 解析器将源代码转换为抽象语法树 (AST)。您的 XPath 表达式应用于 AST,而不是源代码。例如。 if 语句的 AST 看起来像这样:

IfElseBlockStatement {
    IfBlockStatement {
        StandardCondition {
            BooleanExpression {
                PrefixExpression {
                    MethodCallExpression {
                        ReferenceExpression 
                    }
                }
                BooleanExpression {
                    VariableExpression 
                    LiteralExpression 
                }
            }
        }
        BlockStatement {
            DmlInsertStatement {
                VariableExpression 
            }
        }
    }
}

PMD 有一个图形 rule designer 在编写 XPath 规则时很有帮助。

对于这个 AST,XPath //BooleanExpression/BooleanExpression[position() > 0 and VariableExpression and LiteralExpression] 匹配 && caseShareList != null。但它也会匹配 || i == 42 因此您必须进一步优化查询。不幸的是,我没有看到任何可以让我区分 &&|| 的东西,但你可能运气更好。

事实证明,PMD 6.10 无法实现我需要做的事情。 latest release 6.11.0 没有像我希望的那样暴露 @Image 属性 ,而是在布尔运算符中添加了足够的新属性以形成值得 @michael-kay 的 XPath 表达式,而不需要将正则表达式添加到组合中:

//BooleanExpression[@Op="&&"][
  child::*[2][
    self::BooleanExpression[@Op="!="][
      child::*[1][self::VariableExpression] and
      child::*[2][self::LiteralExpression[@LiteralType="NULL"]]
    ]
  ]
]

YMMV