function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kaustubh LabheKaustubh Labhe 

Custom apex rules in PMD static code scanner

Hi guys, 

I have configured PMD to run with ANT, however I am struggling to write custom rules. I am working with the standard rules which sourceforge provides. Has anyone written custom rules for apex in PMD? 

Thanks for your time.
Best Answer chosen by Kaustubh Labhe
Alain CabonAlain Cabon
Have you got a "PMD rule designer" screen like below (last version of PMD) ?

//UserClass[contains(@Image,'_')]


User-added image

 
<rule name="Class name underscore forbidden"
      language="apex"
      message="Don't use underscore in class names"
      class="net.sourceforge.pmd.lang.rule.XPathRule"
      <!-- externalInfoUrl="TODO"--> >
    <description>
Don't use underscore in class names
    </description>
    <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//UserClass[contains(@Image,'_')]

]]>
            </value>
        </property>
    </properties>
    <!--<example><![CDATA[]]></example>-->
</rule>

 

All Answers

Alain CabonAlain Cabon
Hi,

What method are you using? (java or xpath ?)

XPath only could be sufficient (2min41): https://www.youtube.com/watch?v=4LwqhRj_8ek

What kind of rule are you trying? I used the integrated parser of PMD but I didn't write new rules until now.
 
Kaustubh LabheKaustubh Labhe
So, i am very new in this. I have been able to create a ruleset with standard rules which source forge provides. But how should i create a custom rule like? 
For eg. I want to create a rule where class names cannot have underscores in it. 

Thanks
Alain CabonAlain Cabon

Robert Sösemann is an active contributor on stackoverflow https://stackoverflow.com/users/1388807/robert-s%C3%B6semann
He is the developer of PMD for Apex.  https://github.com/pmd/pmd/issues/1568

Did you see the Abstract Syntax Tree (AST) of your sample of code in Apex in order to write the XPath expression ?
Alain CabonAlain Cabon
Have you got a "PMD rule designer" screen like below (last version of PMD) ?

//UserClass[contains(@Image,'_')]


User-added image

 
<rule name="Class name underscore forbidden"
      language="apex"
      message="Don't use underscore in class names"
      class="net.sourceforge.pmd.lang.rule.XPathRule"
      <!-- externalInfoUrl="TODO"--> >
    <description>
Don't use underscore in class names
    </description>
    <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//UserClass[contains(@Image,'_')]

]]>
            </value>
        </property>
    </properties>
    <!--<example><![CDATA[]]></example>-->
</rule>

 
This was selected as the best answer
Alain CabonAlain Cabon
By the way, there is not a complete "compilation" (impossible from PMD) so the method call above is incorrect (not a constructor either because of the missing parenthesis ) but the parser works nevertheless.

Below, the method is correct and method_1 is well identified.

User-added image

The XPath Expression is just a "change value" responsive field and when there is match with the "Source code" the "Matched nodes" are resolved (otherwise it is empty).
 
Kaustubh LabheKaustubh Labhe
Hi,

I am still struggling a bit here. So where is the method Xpathrule, from class="net.sourceforge.pmd.lang.rule.XPathRule"

Cheers
 
Alain CabonAlain Cabon
Hi,

This class is given directly by the generator and that is not correct indeed (??) (that seems even totally wrong).

The correct path should be (perhaps) by uncompressing pmd-apex-6.11.0.jar (rename it in pmd-apex-6.11.0.zip, if you want to see the content easily):

net.sourceforge.pmd.lang.apex.rule.ApexXPathRule

Ideally, Robert Sösemann should help us on stackoverflow.


User-added image

I am also learning PMD like you (step by step) and there are some bugs.

Alain
Kaustubh LabheKaustubh Labhe
Hi,

One of my colleagues has asked this on stackexchange. Sadly there is no way to tag Robert on it. 
https://salesforce.stackexchange.com/questions/248550/how-to-create-custom-rules-for-pmd-apex-static-code-analyzer 

I read this page https://pmd.github.io/latest/pmd_userdocs_extending_writing_pmd_rules.html ​​​​​​, and I understiood the AST part, however, I cannot understand the relation between AST and the JAVA class. 

Thanks
Alain CabonAlain Cabon
The alternative with XPath is not clear and the example for java is not practical.
I totally agree but the XPath rule is the simplest way in order to extend the existing rules.

By having a working XPath rule for Apex with some real commands and directories, we would save a lot of time and Robert Sösemann could have some examples. Robert Sösemann struggled himself with big issues in the previous version (fixed now?): https://github.com/pmd/pmd/issues/1568

The other alternative is to install a complete project on a java IDE (eclipse, intellij) and to add the new rules by duplicating an existing one but it is far more complicated.

Not sure that the following example works finally either because that is a question about a "not working rule" (as expected or totally):
https://stackoverflow.com/questions/54104090/how-to-check-for-an-apex-source-string-in-pmd-using-xpath

class="net.sourceforge.pmd.lang.rule.XPathRule" is into pdm-core jar.

and  class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule" extends "net.sourceforge.pmd.lang.rule.XPathRule"
 
Alain CabonAlain Cabon
Your question has been updated and it is what I thought.

You need to install the complete pmd-apex source code from the github project and regenerate a new jar using Maven after adding a new rule.

User-added image

You need to extend an existing jar of PMD in java in order to add a new rule. 

This technique in java has the main disadvantage to create your own version of PMD (programmatic way).

The XPath technique is independent from the version of PMD. It is just declarative but that doesn't work very well until now (it is even perhaps impossible until now).

https://github.com/rsoesemann/codeclimate-apexmetrics/wiki/add-a-new-rule-for-apex-pmd
 
Kaustubh LabheKaustubh Labhe
Hi Alain, 

the rule that you gave me:
***
<rule name="Class name underscore forbidden" message="Don't use underscore in class names" class="net.sourceforge.pmd.lang.rule.XPathRule" language = "apex">
        <description>
        Don't use underscore in class names
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
                    <![CDATA[
                        //UserClass[contains(@Image,'_')]
                    ]]>
                </value>
            </property>
        </properties>
    <!--<example><![CDATA[]]></example>-->
    </rule>
***

Believe me or not, i copied and pasted it in my existing rule set file. And it worked!! 

I run this ruleset as part of my ant build. and funny enough, the above rule is being run and it showed me erronous classes (with underscores) in its name. 
 
Alain CabonAlain Cabon
Hi Kaustubh,

If this first XPath expression helps, that is a good point and I believe you of course.

Finally, there was a solution easier than expected by using Eclipse and the java rules.

Cheers!

Alain
Alain CabonAlain Cabon
I am using very often BaseX  ( http://basex.org/ ) and I was plunged into perplexity if //UserClass[contains(@Image,'_')] would not have worked but finally, all's well that ends well

Good week-end.
Ashutosh vermaAshutosh verma
Can we write a ruleset to enforce user to fill Description value on all Standard/ Custom objects ?
Either at the time of object creation or migration of object from one Org to another Org.