[doc] [apex] Adjust externalInfoUrl properties to new site - Part 5
Note: I also took the chance to fix tab damage
This commit is contained in:
@ -20,7 +20,7 @@ import net.sourceforge.pmd.lang.apex.ast.ApexNode;
|
||||
*
|
||||
* @author a.subramanian
|
||||
*/
|
||||
public class ApexUnitTestClassShouldHaveAsserts extends AbstractApexUnitTestRule {
|
||||
public class ApexUnitTestClassShouldHaveAssertsRule extends AbstractApexUnitTestRule {
|
||||
|
||||
private static final Set<String> ASSERT_METHODS = new HashSet<>();
|
||||
|
@ -25,7 +25,7 @@ import apex.jorje.services.Version;
|
||||
*
|
||||
* @author a.subramanian
|
||||
*/
|
||||
public class ApexUnitTestShouldNotUseSeeAllDataTrue extends AbstractApexUnitTestRule {
|
||||
public class ApexUnitTestShouldNotUseSeeAllDataTrueRule extends AbstractApexUnitTestRule {
|
||||
|
||||
@Override
|
||||
public Object visit(final ASTUserClass node, final Object data) {
|
@ -11,8 +11,8 @@
|
||||
<rule name="ApexUnitTestClassShouldHaveAsserts"
|
||||
since="5.5.1"
|
||||
message="Apex unit tests should System.assert() or assertEquals() or assertNotEquals()"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestClassShouldHaveAsserts"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/apexunit.html#ApexUnitTestClassShouldHaveAsserts">
|
||||
class="net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestClassShouldHaveAssertsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_apexunit.html#apexunittestclassshouldhaveasserts">
|
||||
<description>
|
||||
Apex unit tests should include at least one assertion. This makes the tests more robust, and using assert
|
||||
with messages provide the developer a clearer idea of what the test does.
|
||||
@ -35,8 +35,8 @@ public class Foo {
|
||||
<rule name="ApexUnitTestShouldNotUseSeeAllDataTrue"
|
||||
since="5.5.1"
|
||||
message="Apex unit tests should not use @isTest(seeAllData = true)"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestShouldNotUseSeeAllDataTrue"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/apexunit.html#ApexUnitTestShouldNotUseSeeAllDataTrue">
|
||||
class="net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestShouldNotUseSeeAllDataTrueRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_apexunit.html#apexunittestshouldnotuseseealldatatrue">
|
||||
<description>
|
||||
Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests.
|
||||
</description>
|
||||
|
@ -13,7 +13,7 @@ The Braces ruleset contains rules regarding the use and placement of braces.
|
||||
since="5.6.0"
|
||||
message="Avoid using if statements without curly braces"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/braces.html#IfStmtsMustUseBraces">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_braces.html#ifstmtsmustusebraces">
|
||||
<description>
|
||||
Avoid using if statements without using braces to surround the code block. If the code
|
||||
formatting or indentation is lost then it becomes difficult to separate the code being
|
||||
@ -23,23 +23,21 @@ controlled from the rest.
|
||||
<properties>
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
//IfBlockStatement/BlockStatement[@CurlyBrace='false']
|
||||
]]>
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</properties>
|
||||
<example>
|
||||
<![CDATA[
|
||||
|
||||
if (foo) // not recommended
|
||||
x++;
|
||||
|
||||
if (foo) { // preferred approach
|
||||
x++;
|
||||
}
|
||||
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
@ -48,7 +46,7 @@ if (foo) { // preferred approach
|
||||
since="5.6.0"
|
||||
message="Avoid using 'while' statements without curly braces"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/braces.html#WhileLoopsMustUseBraces">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_braces.html#whileloopsmustusebraces">
|
||||
<description>
|
||||
Avoid using 'while' statements without using braces to surround the code block. If the code
|
||||
formatting or indentation is lost then it becomes difficult to separate the code being
|
||||
@ -81,7 +79,7 @@ while (true) { // preferred approach
|
||||
since="5.6.0"
|
||||
message="Avoid using 'if...else' statements without curly braces"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/braces.html#IfElseStmtsMustUseBraces">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_braces.html#ifelsestmtsmustusebraces">
|
||||
<description>
|
||||
Avoid using if..else statements without using surrounding braces. If the code formatting
|
||||
or indentation is lost then it becomes difficult to separate the code being controlled
|
||||
@ -95,19 +93,19 @@ from the rest.
|
||||
//IfBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]
|
||||
|
|
||||
//IfElseBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]
|
||||
]]>
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</properties>
|
||||
<example>
|
||||
<![CDATA[
|
||||
// this is OK
|
||||
// this is OK
|
||||
if (foo) x++;
|
||||
|
||||
// but this is not
|
||||
// but this is not
|
||||
if (foo)
|
||||
x = x+1;
|
||||
else
|
||||
else
|
||||
x = x-1;
|
||||
]]>
|
||||
</example>
|
||||
@ -118,7 +116,7 @@ if (foo)
|
||||
since="5.6.0"
|
||||
message="Avoid using 'for' statements without curly braces"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/braces.html#ForLoopsMustUseBraces">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_braces.html#forloopsmustusebraces">
|
||||
<description>
|
||||
Avoid using 'for' statements without using surrounding braces. If the code formatting or
|
||||
indentation is lost then it becomes difficult to separate the code being controlled
|
||||
@ -128,11 +126,11 @@ from the rest.
|
||||
<properties>
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
//ForLoopStatement/BlockStatement[@CurlyBrace='false']
|
||||
|
|
||||
//ForEachStatement/BlockStatement[@CurlyBrace='false']
|
||||
]]>
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</properties>
|
||||
|
@ -12,13 +12,14 @@ The Complexity ruleset contains rules that find problems related to code size or
|
||||
since="5.5.0"
|
||||
message="Deeply nested if..then statements are hard to read"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.AvoidDeeplyNestedIfStmtsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#AvoidDeeplyNestedIfStmts">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#avoiddeeplynestedifstmts">
|
||||
<description>
|
||||
Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void bar(Integer x, Integer y, Integer z) {
|
||||
if (x>y) {
|
||||
if (y>z) {
|
||||
@ -37,20 +38,21 @@ Avoid creating deeply nested if-then statements since they are harder to read an
|
||||
since="5.5.0"
|
||||
message="Avoid long parameter lists."
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveParameterListRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#ExcessiveParameterList">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#excessiveparameterlist">
|
||||
<description>
|
||||
Methods with numerous parameters are a challenge to maintain, especially if most of them share the
|
||||
same datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[// too many arguments liable to be mixed up
|
||||
<![CDATA[
|
||||
// too many arguments liable to be mixed up
|
||||
public void addPerson(int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
// preferred approach
|
||||
public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
@ -60,7 +62,7 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) {
|
||||
since="5.5.0"
|
||||
message="Avoid really long classes."
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveClassLengthRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#ExcessiveClassLength">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#excessiveclasslength">
|
||||
<description>
|
||||
Excessive class file lengths are usually indications that the class may be burdened with excessive
|
||||
responsibilities that could be provided by external classes or functions. In breaking these methods
|
||||
@ -68,7 +70,8 @@ apart the code becomes more managable and ripe for reuse.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void bar1() {
|
||||
// 1000 lines of code
|
||||
}
|
||||
@ -86,11 +89,11 @@ apart the code becomes more managable and ripe for reuse.
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="NcssMethodCount"
|
||||
<rule name="NcssMethodCount"
|
||||
since="5.5.0"
|
||||
message="The method ''{0}()'' has an NCSS line count of {1}"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.NcssMethodCountRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#NcssMethodCount">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#ncssmethodcount">
|
||||
<description>
|
||||
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
|
||||
of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm,
|
||||
@ -98,7 +101,8 @@ lines of code that are split are counted as one.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo extends Bar {
|
||||
<![CDATA[
|
||||
public class Foo extends Bar {
|
||||
//this method only has 1 NCSS lines
|
||||
public Integer methd() {
|
||||
super.methd();
|
||||
@ -112,11 +116,11 @@ lines of code that are split are counted as one.
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="NcssTypeCount"
|
||||
<rule name="NcssTypeCount"
|
||||
since="5.5.0"
|
||||
message="The type has an NCSS line count of {0}"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.NcssTypeCountRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#NcssTypeCount">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#ncsstypecount">
|
||||
<description>
|
||||
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
|
||||
of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm,
|
||||
@ -124,7 +128,8 @@ lines of code that are split are counted as one.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[//this class only has 6 NCSS lines
|
||||
<![CDATA[
|
||||
//this class only has 6 NCSS lines
|
||||
public class Foo extends Bar {
|
||||
public Foo() {
|
||||
super();
|
||||
@ -137,13 +142,14 @@ public class Foo extends Bar {
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example></rule>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="NcssConstructorCount"
|
||||
<rule name="NcssConstructorCount"
|
||||
since="5.5.0"
|
||||
message="The constructor has an NCSS line count of {0}"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.NcssConstructorCountRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#NcssConstructorCount">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#ncssconstructorcount">
|
||||
<description>
|
||||
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
|
||||
of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm,
|
||||
@ -151,7 +157,8 @@ lines of code that are split are counted as one.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo extends Bar {
|
||||
<![CDATA[
|
||||
public class Foo extends Bar {
|
||||
//this constructor only has 1 NCSS lines
|
||||
public Foo() {
|
||||
super();
|
||||
@ -160,29 +167,28 @@ lines of code that are split are counted as one.
|
||||
|
||||
|
||||
super.foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
</rule>
|
||||
|
||||
<rule name="StdCyclomaticComplexity"
|
||||
since="5.5.0"
|
||||
message="The {0} ''{1}'' has a Standard Cyclomatic Complexity of {2}."
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.StdCyclomaticComplexityRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#StdCyclomaticComplexity">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#stdcyclomaticcomplexity">
|
||||
<description>
|
||||
<![CDATA[
|
||||
Complexity directly affects maintenance costs is determined by the number of decision points in a method
|
||||
plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls.
|
||||
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
|
||||
high complexity, and 11+ is very high complexity.
|
||||
]]>
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[// This has a Cyclomatic Complexity = 12
|
||||
public class Foo {
|
||||
<![CDATA[
|
||||
// This has a Cyclomatic Complexity = 12
|
||||
public class Foo {
|
||||
1 public void example() {
|
||||
2 if (a == b || (c == d && e == f)) {
|
||||
3 if (a1 == b1) {
|
||||
@ -216,8 +222,7 @@ high complexity, and 11+ is very high complexity.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
@ -226,7 +231,7 @@ high complexity, and 11+ is very high complexity.
|
||||
since="5.5.0"
|
||||
message="Too many fields"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.TooManyFieldsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#TooManyFields">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#toomanyfields">
|
||||
<description>
|
||||
Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields,
|
||||
possibly through grouping related fields in new objects. For example, a class with individual
|
||||
@ -234,7 +239,8 @@ city/state/zip fields could park them within a single Address field.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Person {
|
||||
<![CDATA[
|
||||
public class Person {
|
||||
// too many separate fields
|
||||
int birthYear;
|
||||
int birthMonth;
|
||||
@ -256,7 +262,7 @@ public class Person {
|
||||
since="5.5.0"
|
||||
message="This class has a bunch of public methods and attributes"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessivePublicCountRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/complexity.html#ExcessivePublicCount">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_complexity.html#excessivepubliccount">
|
||||
<description>
|
||||
Classes with large numbers of public methods and attributes require disproportionate testing efforts
|
||||
since combinational side effects grow rapidly and increase risk. Refactoring these classes into
|
||||
@ -265,7 +271,8 @@ developed easily.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public String value;
|
||||
public Bar something;
|
||||
public Variable var;
|
||||
|
@ -14,7 +14,7 @@
|
||||
since="6.0.0"
|
||||
class="net.sourceforge.pmd.lang.apex.metrics.rule.CyclomaticComplexityRule"
|
||||
metrics="true"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/metrics.html#CyclomaticComplexity">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_metrics.html#cyclomaticcomplexity">
|
||||
<description>
|
||||
<![CDATA[
|
||||
The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic
|
||||
|
@ -12,13 +12,14 @@ The Performance ruleset contains a collection of good practices which should be
|
||||
since="5.5.0"
|
||||
message="Avoid Soql queries inside loops"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.performance.AvoidSoqlInLoopsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/performance.html#AvoidSoqlInLoops">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_performance.html#avoidsoqlinloops">
|
||||
<description>
|
||||
New objects created within loops should be checked to see if they can created outside them and reused.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class Something {
|
||||
<![CDATA[
|
||||
public class Something {
|
||||
public static void main( String as[] ) {
|
||||
for (Integer i = 0; i < 10; i++) {
|
||||
List<Account> accounts = [SELECT Id FROM Account];
|
||||
@ -33,8 +34,10 @@ New objects created within loops should be checked to see if they can created ou
|
||||
since="5.5.0"
|
||||
message="Avoid DML statements inside loops"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.performance.AvoidDmlStatementsInLoopsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/performance.html#AvoidDmlStatementsInLoops">
|
||||
<description>Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop.</description>
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_performance.html#avoiddmlstatementsinloops">
|
||||
<description>
|
||||
Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
@ -42,7 +45,7 @@ public class Something {
|
||||
public void foo() {
|
||||
for (Integer i = 0; i < 151; i++) {
|
||||
Account account;
|
||||
...
|
||||
// ...
|
||||
insert account;
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,10 @@
|
||||
# BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
#
|
||||
|
||||
rulesets.filenames=rulesets/apex/complexity.xml,rulesets/apex/performance.xml,rulesets/apex/style.xml,rulesets/apex/apexunit.xml,rulesets/apex/security.xml,rulesets/apex/braces.xml
|
||||
rulesets.filenames=\
|
||||
rulesets/apex/apexunit.xml,\
|
||||
rulesets/apex/braces.xml,\
|
||||
rulesets/apex/complexity.xml,\
|
||||
rulesets/apex/performance.xml,\
|
||||
rulesets/apex/security.xml,\
|
||||
rulesets/apex/style.xml
|
||||
|
@ -3,95 +3,99 @@
|
||||
<ruleset name="Security" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
|
||||
<description>
|
||||
These rules deal with different security problems that can occur within Apex.
|
||||
These rules deal with different security problems that can occur within Apex.
|
||||
</description>
|
||||
|
||||
<rule name="ApexSharingViolations" since="5.5.3"
|
||||
<rule name="ApexSharingViolations"
|
||||
since="5.5.3"
|
||||
message="Apex classes should declare a sharing model if DML or SOQL/SOSL is used"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexSharingViolationsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexSharingViolations">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexsharingviolations">
|
||||
<description>
|
||||
Detect classes declared without explicit sharing mode if DML methods are used. This
|
||||
forces the developer to take access restrictions into account before modifying objects.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
// DML operation here
|
||||
// DML operation here
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexOpenRedirect" since="5.5.3"
|
||||
<rule name="ApexOpenRedirect"
|
||||
since="5.5.3"
|
||||
message="Apex classes should safely redirect to a known location"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexOpenRedirectRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexOpenRedirect">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexopenredirect">
|
||||
<description>
|
||||
Checks against redirects to user-controlled locations. This prevents attackers from
|
||||
redirecting users to phishing sites.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param');
|
||||
PageReference page() {
|
||||
return new PageReference(unsafeLocation);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
|
||||
<rule name="ApexInsecureEndpoint" since="5.5.3"
|
||||
<rule name="ApexInsecureEndpoint"
|
||||
since="5.5.3"
|
||||
message="Apex callouts should use encrypted communication channels"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexInsecureEndpointRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexInsecureEndpoint">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexinsecureendpoint">
|
||||
<description>
|
||||
Checks against accessing endpoints under plain **http**. You should always use
|
||||
**https** for security.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
void foo() {
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint('http://localhost:com');
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexXSSFromURLParam" since="5.5.3"
|
||||
<rule name="ApexXSSFromURLParam"
|
||||
since="5.5.3"
|
||||
message="Apex classes should escape/sanitize Strings obtained from URL parameters"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromURLParamRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexXSSFromURLParam">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexxssfromurlparam">
|
||||
<description>
|
||||
Makes sure that all values obtained from URL parameters are properly escaped / sanitized
|
||||
to avoid XSS attacks.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param');
|
||||
String usedLater = unescapedstring;
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
|
||||
<rule name="ApexXSSFromEscapeFalse" since="5.5.3"
|
||||
<rule name="ApexXSSFromEscapeFalse"
|
||||
since="5.5.3"
|
||||
message="Apex classes should escape Strings in error messages"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromEscapeFalseRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexXSSFromEscapeFalse">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexxssfromescapefalse">
|
||||
<description>
|
||||
Reports on calls to `addError` with disabled escaping. The message passed to `addError`
|
||||
will be displayed directly to the user in the UI, making it prime ground for XSS
|
||||
@ -99,47 +103,48 @@ attacks if unescaped.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
Trigger.new[0].addError(vulnerableHTMLGoesHere, false);
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexBadCrypto" since="5.5.3"
|
||||
<rule name="ApexBadCrypto"
|
||||
since="5.5.3"
|
||||
message="Apex classes should use random IV/key"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexBadCryptoRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexBadCrypto">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexbadcrypto">
|
||||
<description>
|
||||
The rule makes sure you are using randomly generated IVs and keys for `Crypto` calls.
|
||||
Hard-wiring these values greatly compromises the security of encrypted data.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public without sharing class Foo {
|
||||
Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123');
|
||||
Blob hardCodedKey = Blob.valueOf('0000000000000000');
|
||||
Blob data = Blob.valueOf('Data to be encrypted');
|
||||
Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data);
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
|
||||
<rule name="ApexCSRF" since="5.5.3"
|
||||
<rule name="ApexCSRF"
|
||||
since="5.5.3"
|
||||
message="Avoid making DML operations in Apex class constructor/init method"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexCSRFRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexCSRF">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexcsrf">
|
||||
<description>
|
||||
Check to avoid making DML operations in Apex class constructor/init method. This prevents
|
||||
modification of the database just by accessing a page.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public init() {
|
||||
insert data;
|
||||
@ -149,33 +154,35 @@ public class Foo {
|
||||
insert data;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexSOQLInjection" since="5.5.3"
|
||||
<rule name="ApexSOQLInjection"
|
||||
since="5.5.3"
|
||||
message="Avoid untrusted/unescaped variables in DML query"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexSOQLInjectionRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexSOQLInjection">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexsoqlinjection">
|
||||
<description>
|
||||
Detects the usage of untrusted / unescaped variables in DML queries.
|
||||
Detects the usage of untrusted / unescaped variables in DML queries.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void test1(String t1) {
|
||||
Database.query('SELECT Id FROM Account' + t1);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexCRUDViolation" since="5.5.3"
|
||||
<rule name="ApexCRUDViolation"
|
||||
since="5.5.3"
|
||||
message="Validate CRUD permission before SOQL/DML operation"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexCRUDViolationRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexCRUDViolationRule">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexcrudviolation">
|
||||
<description>
|
||||
The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation.
|
||||
Since Apex runs in system mode not having proper permissions checks results in escalation of
|
||||
@ -183,7 +190,7 @@ privilege and may produce runtime errors. This check forces you to handle such s
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public Contact foo(String status, String ID) {
|
||||
Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID];
|
||||
@ -198,14 +205,15 @@ public class Foo {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexDangerousMethods" since="5.5.3"
|
||||
<rule name="ApexDangerousMethods"
|
||||
since="5.5.3"
|
||||
message="Calling potentially dangerous method"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexDangerousMethodsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexDangerousMethodsRule">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexdangerousmethods">
|
||||
<description><![CDATA[
|
||||
Checks against calling dangerous methods.
|
||||
|
||||
@ -215,23 +223,25 @@ For the time being, it reports:
|
||||
opens the door to several attacks and requires manual validation, which is unreliable.
|
||||
* Calling `System.debug` passing sensitive data as parameter, which could lead to exposure
|
||||
of private data.
|
||||
]]></description>
|
||||
]]>
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public Foo() {
|
||||
Configuration.disableTriggerCRUDSecurity();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ApexSuggestUsingNamedCred" since="5.5.3"
|
||||
<rule name="ApexSuggestUsingNamedCred"
|
||||
since="5.5.3"
|
||||
message="Suggest named credentials for authentication"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.security.ApexSuggestUsingNamedCredRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/security.html#ApexSuggestUsingNamedCredRule">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_security.html#apexsuggestusingnamedcred">
|
||||
<description><
|
||||
]]></description>
|
||||
]]>
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void foo(String username, String password) {
|
||||
Blob headerValue = Blob.valueOf(username + ':' + password);
|
||||
@ -261,5 +272,4 @@ public class Foo {
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
|
||||
</ruleset>
|
||||
|
@ -12,7 +12,7 @@ The Style Ruleset contains rules regarding preferred usage of names and identifi
|
||||
since="5.5.0"
|
||||
message="{0} variable {1} should begin with {2}"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.VariableNamingConventionsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#VariableNamingConventions">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#variablenamingconventions">
|
||||
<description>
|
||||
A variable naming conventions rule - customize this to your liking. Currently, it
|
||||
checks for final variables that should be fully capitalized and non-final variables
|
||||
@ -20,7 +20,8 @@ that should not include underscores.
|
||||
</description>
|
||||
<priority>1</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public static final Integer MY_NUM = 0;
|
||||
public String myTest = '';
|
||||
DataModule dmTest = new DataModule();
|
||||
@ -33,13 +34,14 @@ that should not include underscores.
|
||||
since="5.5.0"
|
||||
message="Method name does not begin with a lower case character."
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.MethodNamingConventionsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#MethodNamingConventions">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#methodnamingconventions">
|
||||
<description>
|
||||
Method names should always begin with a lower case character, and should not contain underscores.
|
||||
</description>
|
||||
<priority>1</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void fooStuff() {
|
||||
}
|
||||
}
|
||||
@ -51,13 +53,14 @@ Method names should always begin with a lower case character, and should not con
|
||||
since="5.5.0"
|
||||
message="Class names should begin with an uppercase character"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.ClassNamingConventionsRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#ClassNamingConventions">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#classnamingconventions">
|
||||
<description>
|
||||
Class names should always begin with an upper case character.
|
||||
</description>
|
||||
<priority>1</priority>
|
||||
<example>
|
||||
<![CDATA[public class Foo {}
|
||||
<![CDATA[
|
||||
public class Foo {}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
@ -66,13 +69,14 @@ Class names should always begin with an upper case character.
|
||||
since="5.5.0"
|
||||
message="Classes should not have non-constructor methods with the same name as the class"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.MethodWithSameNameAsEnclosingClassRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#MethodWithSameNameAsEnclosingClass">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#methodwithsamenameasenclosingclass">
|
||||
<description>
|
||||
Non-constructor methods should not have the same name as the enclosing class.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[public class MyClass {
|
||||
<![CDATA[
|
||||
public class MyClass {
|
||||
// this is OK because it is a constructor
|
||||
public MyClass() {}
|
||||
// this is bad because it is a method
|
||||
@ -86,7 +90,7 @@ Non-constructor methods should not have the same name as the enclosing class.
|
||||
since="5.5.0"
|
||||
message="Avoid logic in triggers"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.AvoidLogicInTriggerRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#AvoidLogicInTrigger">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#avoidlogicintrigger">
|
||||
<description>
|
||||
As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style.
|
||||
Therefore delegate the triggers work to a regular class (often called Trigger handler class).
|
||||
@ -95,16 +99,17 @@ See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
|
||||
<![CDATA[
|
||||
trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
|
||||
for(Account acc : Trigger.new) {
|
||||
if(Trigger.isInsert) {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
|
||||
...
|
||||
// ...
|
||||
|
||||
if(Trigger.isDelete) {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,14 +121,15 @@ See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex
|
||||
since="5.5.0"
|
||||
message="Avoid using global modifier"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.style.AvoidGlobalModifierRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/style.html#AvoidGlobalModifier">
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_style.html#avoidglobalmodifier">
|
||||
<description>
|
||||
Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global.
|
||||
Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[global class Unchangeable {
|
||||
<![CDATA[
|
||||
global class Unchangeable {
|
||||
global UndeletableType unchangable(UndeletableType param) {
|
||||
// ...
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex;
|
||||
|
||||
import net.sourceforge.pmd.AbstractRuleSetFactoryTest;
|
||||
import net.sourceforge.pmd.lang.apex.rule.ApexXPathRule;
|
||||
|
||||
public class RuleSetFactoryTest extends AbstractRuleSetFactoryTest {
|
||||
public RuleSetFactoryTest() {
|
||||
super();
|
||||
validXPathClassNames.add(ApexXPathRule.class.getName());
|
||||
}
|
||||
}
|
@ -17,10 +17,13 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
@ -49,6 +52,12 @@ public abstract class AbstractRuleSetFactoryTest {
|
||||
private static ValidateDefaultHandler validateDefaultHandlerDtd;
|
||||
private static SAXParser saxParser;
|
||||
|
||||
protected Set<String> validXPathClassNames = new HashSet<>();
|
||||
|
||||
public AbstractRuleSetFactoryTest() {
|
||||
validXPathClassNames.add(XPathRule.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the XML parser with validation.
|
||||
*
|
||||
@ -134,7 +143,7 @@ public abstract class AbstractRuleSetFactoryTest {
|
||||
String expectedClassName = "net.sourceforge.pmd.lang." + language.getTerseName() + ".rule." + group
|
||||
+ "." + rule.getName() + "Rule";
|
||||
if (!rule.getRuleClass().equals(expectedClassName)
|
||||
&& !rule.getRuleClass().equals(XPathRule.class.getName())) {
|
||||
&& !validXPathClassNames.contains(rule.getRuleClass())) {
|
||||
invalidClassName++;
|
||||
messages += "Rule " + fileName + "/" + rule.getName() + " seems to have an invalid 'class' value ("
|
||||
+ rule.getRuleClass() + "), it should be:" + expectedClassName + PMD.EOL;
|
||||
|
Reference in New Issue
Block a user