Search code examples
xpathpmd

PMD PrimaryPrefix issue through XPath


I spent about 4 hours on this but XPath proved to be very painful to work with when developing fairly original custom rules.

For one part of my problem, I need PMD XPath to be able to distinguish between the following lines: int var = this.nocall; int var = nocall;

From AST, I see that PrimaryPrefix:this But I am unable to select the first statement with //PrimaryPrefix['this'] or //PrimaryExpression/PrimaryPrefix['this]] or //PrimaryPrefix[@image='this']

I wonder if anyone has a hint on how to retrieve all the expression with 'this.' in assignment part through XPath.

Example code trying to parse:

class testRuleOne {
    private int nocall;
    public void myMethod() {
        int var = this.nocall;
        var = this.getNoCall();
    }
}

Here's the raw XML of AST:

<MethodDeclaration Abstract="false" BeginColumn="16" BeginLine="3" EndColumn="9" EndLine="6" Final="false" Image="" InterfaceMember="false" Label="" MethodName="myMethod" Modifiers="1" Native="false" PackagePrivate="false" Private="false" Protected="false" Public="true" Static="false" Strictfp="false" Synchronized="false" SyntacticallyAbstract="false" SyntacticallyPublic="true" Transient="false" Void="true" Volatile="false">
                    <ResultType BeginColumn="16" BeginLine="3" EndColumn="19" EndLine="3" Image="" Label="" Void="true" returnsArray="false"/>
                    <MethodDeclarator BeginColumn="21" BeginLine="3" EndColumn="30" EndLine="3" Image="myMethod" Label="" ParameterCount="0">
                        <FormalParameters BeginColumn="29" BeginLine="3" EndColumn="30" EndLine="3" Image="" Label="" ParameterCount="0"/>
                    </MethodDeclarator>
                    <Block BeginColumn="32" BeginLine="3" EndColumn="9" EndLine="6" Image="" Label="" containsComment="false">
                        <BlockStatement Allocation="false" BeginColumn="17" BeginLine="4" EndColumn="38" EndLine="4" Image="" Label="">
                            <LocalVariableDeclaration Abstract="false" Array="false" ArrayDepth="0" BeginColumn="17" BeginLine="4" EndColumn="37" EndLine="4" Final="false" Image="" Label="" Modifiers="0" Native="false" PackagePrivate="true" Private="false" Protected="false" Public="false" Static="false" Strictfp="false" Synchronized="false" Transient="false" VariableName="var" Volatile="false">
                                <Type Array="false" ArrayDepth="0" BeginColumn="17" BeginLine="4" EndColumn="19" EndLine="4" Image="" Label="" TypeImage="int">
                                    <PrimitiveType Array="false" ArrayDepth="0" BeginColumn="17" BeginLine="4" Boolean="false" EndColumn="19" EndLine="4" Image="int" Label=""/>
                                </Type>
                                <VariableDeclarator BeginColumn="21" BeginLine="4" EndColumn="37" EndLine="4" Image="" Label="">
                                    <VariableDeclaratorId Array="false" ArrayDepth="0" BeginColumn="21" BeginLine="4" EndColumn="23" EndLine="4" ExceptionBlockParameter="false" Image="var" Label=""/>
                                    <VariableInitializer BeginColumn="27" BeginLine="4" EndColumn="37" EndLine="4" Image="" Label="">
                                        <Expression BeginColumn="27" BeginLine="4" EndColumn="37" EndLine="4" Image="" Label="">
                                            <PrimaryExpression BeginColumn="27" BeginLine="4" EndColumn="37" EndLine="4" Image="" Label="">
                                                <PrimaryPrefix BeginColumn="27" BeginLine="4" EndColumn="30" EndLine="4" Image="" Label="this" SuperModifier="false" ThisModifier="true"/>
                                                <PrimarySuffix ArgumentCount="" Arguments="false" ArrayDereference="false" BeginColumn="31" BeginLine="4" EndColumn="37" EndLine="4" Image="nocall" Label=""/>
                                            </PrimaryExpression>
                                        </Expression>
                                    </VariableInitializer>
                                </VariableDeclarator>
                            </LocalVariableDeclaration>
                        </BlockStatement>
                        <BlockStatement Allocation="false" BeginColumn="17" BeginLine="5" EndColumn="39" EndLine="5" Image="" Label="">

Solution

  • Instead of Label, I would use ThisModifier - the reason is, that Label will not be available in PMD 5 anymore. Label is just a string representation (similar to toString()).

    //PrimaryExpression[PrimaryPrefix/@ThisModifier='true']
    

    This will work both with PMD 4.x and the future PMD 5 - so you won't need to fix the rule.

    See also: https://sourceforge.net/projects/pmd/forums/forum/188194/topic/4971141