如何检测XPath java类不声明方法

时间:2014-09-30 08:30:17

标签: xpath sonarqube

我想创建一个SonarQube XPath自定义规则,该规则检测(使用SSLR java工具包)所有未声明给定方法的类。我希望能够用[not(contains(...))]来做,但我被卡住了。

例如,如何检测所有未声明public String toString()方法的类?

//typeDeclaration//classDeclaration (that do not contain a memberDecl of type String, that has an IDENTIFIER with value "toString" and has no formal parameters)

下面是一个包含该方法的java示例类(这个类不应该与XPath表达式匹配)

public class Example {
  public String toString() {
    return "";
  }
}

下面是与示例java类的AST对应的XML代码。

<compilationUnit tokenValue="public" tokenLine="1" tokenColumn="0">
  <typeDeclaration tokenValue="public" tokenLine="1" tokenColumn="0">
    <modifier tokenValue="public" tokenLine="1" tokenColumn="0">
      <PUBLIC tokenValue="public" tokenLine="1" tokenColumn="0">
        <TOKEN tokenValue="public" tokenLine="1" tokenColumn="0"/>
      </PUBLIC>
    </modifier>
    <classDeclaration tokenValue="class" tokenLine="1" tokenColumn="7">
      <CLASS tokenValue="class" tokenLine="1" tokenColumn="7">
        <TOKEN tokenValue="class" tokenLine="1" tokenColumn="7"/>
      </CLASS>
      <IDENTIFIER tokenValue="Example" tokenLine="1" tokenColumn="13">
        <TOKEN tokenValue="Example" tokenLine="1" tokenColumn="13"/>
      </IDENTIFIER>
      <classBody tokenValue="{" tokenLine="1" tokenColumn="21">
        <LWING tokenValue="{" tokenLine="1" tokenColumn="21">
          <TOKEN tokenValue="{" tokenLine="1" tokenColumn="21"/>
        </LWING>
        <classBodyDeclaration tokenValue="public" tokenLine="2" tokenColumn="2">
          <modifier tokenValue="public" tokenLine="2" tokenColumn="2">
            <PUBLIC tokenValue="public" tokenLine="2" tokenColumn="2">
              <TOKEN tokenValue="public" tokenLine="2" tokenColumn="2"/>
            </PUBLIC>
          </modifier>
          <memberDecl tokenValue="String" tokenLine="2" tokenColumn="9">
            <type tokenValue="String" tokenLine="2" tokenColumn="9">
              <classType tokenValue="String" tokenLine="2" tokenColumn="9">
                <IDENTIFIER tokenValue="String" tokenLine="2" tokenColumn="9">
                  <TOKEN tokenValue="String" tokenLine="2" tokenColumn="9"/>
                </IDENTIFIER>
              </classType>
            </type>
            <IDENTIFIER tokenValue="toString" tokenLine="2" tokenColumn="16">
              <TOKEN tokenValue="toString" tokenLine="2" tokenColumn="16"/>
            </IDENTIFIER>
            <methodDeclaratorRest tokenValue="(" tokenLine="2" tokenColumn="24">
              <formalParameters tokenValue="(" tokenLine="2" tokenColumn="24">
                <LPAR tokenValue="(" tokenLine="2" tokenColumn="24">
                  <TOKEN tokenValue="(" tokenLine="2" tokenColumn="24"/>
                </LPAR>
                <RPAR tokenValue=")" tokenLine="2" tokenColumn="25">
                  <TOKEN tokenValue=")" tokenLine="2" tokenColumn="25"/>
                </RPAR>
              </formalParameters>
              <methodBody tokenValue="{" tokenLine="2" tokenColumn="27">
                <block tokenValue="{" tokenLine="2" tokenColumn="27">
                  <LWING tokenValue="{" tokenLine="2" tokenColumn="27">
                    <TOKEN tokenValue="{" tokenLine="2" tokenColumn="27"/>
                  </LWING>
                  <blockStatements tokenValue="return" tokenLine="3" tokenColumn="4">
                    <blockStatement tokenValue="return" tokenLine="3" tokenColumn="4">
                      <statement tokenValue="return" tokenLine="3" tokenColumn="4">
                        <returnStatement tokenValue="return" tokenLine="3" tokenColumn="4">
                          <RETURN tokenValue="return" tokenLine="3" tokenColumn="4">
                            <TOKEN tokenValue="return" tokenLine="3" tokenColumn="4"/>
                          </RETURN>
                          <expression tokenValue="""" tokenLine="3" tokenColumn="11">
                            <primary tokenValue="""" tokenLine="3" tokenColumn="11">
                              <literal tokenValue="""" tokenLine="3" tokenColumn="11">
                                <LITERAL tokenValue="""" tokenLine="3" tokenColumn="11">
                                  <TOKEN tokenValue="""" tokenLine="3" tokenColumn="11"/>
                                </LITERAL>
                              </literal>
                            </primary>
                          </expression>
                          <SEMI tokenValue=";" tokenLine="3" tokenColumn="13">
                            <TOKEN tokenValue=";" tokenLine="3" tokenColumn="13"/>
                          </SEMI>
                        </returnStatement>
                      </statement>
                    </blockStatement>
                  </blockStatements>
                  <RWING tokenValue="}" tokenLine="4" tokenColumn="2">
                    <TOKEN tokenValue="}" tokenLine="4" tokenColumn="2"/>
                  </RWING>
                </block>
              </methodBody>
            </methodDeclaratorRest>
          </memberDecl>
        </classBodyDeclaration>
        <RWING tokenValue="}" tokenLine="5" tokenColumn="0">
          <TOKEN tokenValue="}" tokenLine="5" tokenColumn="0"/>
        </RWING>
      </classBody>
    </classDeclaration>
  </typeDeclaration>
  <EOF tokenValue="" tokenLine="5" tokenColumn="1"/>
</compilationUnit>

提前谢谢。

1 个答案:

答案 0 :(得分:0)

以下是我自己问题的解决方案:

//classBody[not(//memberDecl[type[@tokenValue='String'] and IDENTIFIER[@tokenValue='toString'] and methodDeclaratorRest/formalParameters[not(formalParameterDecls)]])]