I met a problem while using PMD to check my code errors. I do not know how to satisfy two requirements at the same time. For example, if I want to check a method named ABC not existing in file extends from BCD. I know how to check whether ABC exists or whether it extends from BCD separately using PMD.
Like this:
//PrimaryExpression/PrimaryPrefix/Name [@Image = "ABC"];
//ExtendsList/ClassOrInterfaceType [@Image != "BCD"];
now, is there anyway that I can check these two together. For example, I want it no ABC in class extends BCD. It seems I cannot simply use things like and to connect this two Xpath queries. Also, I noticed I can use | to get connected with them, but | works as or. I need an and here instead of or.
Edit:
I tried something like this:
//PrimaryExpression/PrimaryPrefix/Name[@Image = "ABC"]
[//ancestor::ClassOrInterfaceDeclaration/ExtendsList/
ClassOrInterfaceType[@Image != "BCD"]]
Which seems like it works for me at least. But I am still not 100% sure if this is the correct way since I just tried this out.
Your edit should work, although note that ancestor
axis will recurse all parent nodes, so it should not be introduced with '//'.
Another alternative is to base the Xpath from a common ancestor (e.g. ClassOrInterfaceDeclaration
) and then use and
to ensure the two criteria are met. Since it seems that you are merely testing for the presence of a node meeting both criteria, I guess it doesn't really matter what the resultant expression / node-set actually returns:
//ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[@Image != "BCD"]
and descendant::PrimaryExpression/PrimaryPrefix/Name[@Image = "ABC"]]
If however you do need to select a specific node upon success, just append the node's path, relative to ClassOrInterfaceDeclaration
:
//ClassOrInterfaceDeclaration[... predicate ...]/Some/Path/Here
You could also apply a function like count()
to determine the number of nodes meeting the criteria:
count(//ClassOrInterfaceDeclaration[... predicate ...])
And then evaluate the expression.
(Caveat - I'm not familiar with the PMD layout)
I've put some examples showing the effects of //ancestor::
vs ancestor::
and my alternative.