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

77 Views Asked by At

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?

1

There are 1 best solutions below

4
LMC On BEST ANSWER

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"/>