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