Search code examples
javaeclipsexpathpmd

Using XPath for PMD, is there a way to account for the value of a variable in a method call?


For example:

String user = "Daniel";
String result = doSomething(user);

I know I can find every occurence of doSomething(user) with //MethodCall[@MethodName = "doSomething"]/ArgumentList/VariableAccess[@Name = "user"]. Is it possible to only find those occurences, where user evaluates to "Daniel" at the time the method is called?


Solution

  • Both MethodCall and VariableDeclarator are descendants of the same Block element. That can be used to match the criteria

    //Block[//AssignmentExpression[last()][VariableAccess[@AccessType="WRITE" and @Name="user"]]/StringLiteral[@ConstValue="LMC"] or //VariableDeclarator[@Name="user"]/StringLiteral[@ConstValue="LMC"]]//MethodCall[@MethodName = "detectMe"]/ArgumentList/VariableAccess[@Name = "user"]

    This expresion finds Block elements containing a variable user = "LMC" either only declared or last assigned.

    //Block[//AssignmentExpression[last()][VariableAccess[@AccessType="WRITE" and @Name="user"]]/StringLiteral[@ConstValue="LMC"] or //VariableDeclarator[@Name="user"]/StringLiteral[@ConstValue="LMC"]]

    Will match something like

    public void useIt(){
        String user = "LMC";
        String result = detectMe(user);
    }
    public void useIt(2){
        String user = "Daniel";
        
        user = "osoo";
        user = "LMC";
        String result = detectMe(user);
    }
    

    As a general method, a test class with the relevant use case can be written and dumped with pmd for later XML analysis

    pmd ast-dump --format xml --language java --file PMDSource.java > PMDSource.java.xml

    then use any XPath aware tool to test the expression

     xmllint --xpath '//Block[//AssignmentExpression[last()][VariableAccess[@AccessType="WRITE" and @Name="user"]]/StringLiteral[@ConstValue="LMC"] or //VariableDeclarator[@Name="user"]/StringLiteral[@ConstValue="LMC"]]//MethodCall[@MethodName = "detectMe"]/ArgumentList/VariableAccess[@Name = "user"]' PMDSource.java.xml 
    

    Result

    <VariableAccess AccessType="READ" CompileTimeConstant="false" Expression="true" Image="user" Name="user" ParenthesisDepth="0" Parenthesized="false"/>
    <VariableAccess AccessType="READ" CompileTimeConstant="false" Expression="true" Image="user" Name="user" ParenthesisDepth="0" Parenthesized="false"/>