[apex] Add AvoidDirectAccessTriggerMap rule to the performance set

This commit is contained in:
Jan Aertgeerts
2017-09-20 12:42:22 +02:00
parent 8d808049f3
commit 2639b4fe66
5 changed files with 110 additions and 0 deletions

View File

@ -79,3 +79,40 @@ public class Something {
<rule ref="rulesets/apex/performance.xml/AvoidSoqlInLoops" />
```
## AvoidDirectAccessTriggerMap
**Since:** PMD 6.0.0
**Priority:** Medium (3)
Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Triggers should be bulkified and iterate through the map to handle the actions for each item separately.
```
//ArrayLoadExpression/TriggerVariableExpression
```
**Example(s):**
```
trigger AccountTrigger on Account (before insert, before update) {
Account a = Trigger.new[0]; //Bad: Accessing the trigger array directly is not recommended.
foreach ( Account a : Trigger.new ){
//Good: Iterate through the trigger.new array instead.
}
}
```
**This rule has the following properties:**
|Name|Default Value|Description|
|----|-------------|-----------|
|cc_categories|[Style]|Code Climate Categories|
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/performance.xml/AvoidDirectAccessTriggerMap" />
```

View File

@ -50,6 +50,38 @@ public class Something {
}
}
}
]]>
</example>
</rule>
<rule name="AvoidDirectAccessTriggerMap"
since="6.0.0"
message="Avoid directly accessing Trigger.old and Trigger.new"
class="net.sourceforge.pmd.lang.apex.rule.ApexXPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_performance.html#avoiddirectaccesstriggermap">
<description>
Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Triggers should be bulkified and iterate through the map to handle the actions for each item separately.
</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//ArrayLoadExpression/TriggerVariableExpression
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
trigger AccountTrigger on Account (before insert, before update) {
Account a = Trigger.new[0]; //Bad: Accessing the trigger array directly is not recommended.
foreach ( Account a : Trigger.new ){
//Good: Iterate through the trigger.new array instead.
}
}
]]>
</example>
</rule>

View File

@ -113,6 +113,15 @@
<property name="cc_block_highlighting" value="false" />
</properties>
</rule>
<rule ref="rulesets/apex/performance.xml/AvoidDirectAccessTriggerMap" message="Avoid directly accessing Trigger.old and Trigger.new">
<priority>3</priority>
<properties>
<!-- relevant for Code Climate output only -->
<property name="cc_categories" value="Performance" />
<property name="cc_remediation_points_multiplier" value="150" />
<property name="cc_block_highlighting" value="false" />
</properties>
</rule>
<rule ref="rulesets/apex/style.xml/AvoidLogicInTrigger" message="Avoid logic in triggers">
<priority>3</priority>
<properties>

View File

@ -14,5 +14,6 @@ public class PerformanceRulesTest extends SimpleAggregatorTst {
public void setUp() {
addRule(RULESET, "AvoidSoqlInLoops");
addRule(RULESET, "AvoidDmlStatementsInLoops");
addRule(RULESET, "AvoidDirectAccessTriggerMap");
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data
xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code>
<description>Directly accessing the Trigger.old map.</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
trigger AccountTrigger on Account (before insert, before update) {
Account a = Trigger.new[0]; //Bad: Accessing the trigger array directly is not recommended.
}
]]></code>
</test-code>
<test-code>
<description>Looping through map, best practice</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
trigger AccountTrigger on Account (before insert, before update) {
foreach ( Account a : Trigger.new ){
//Good: Iterate through the trigger.new array instead.
system.debug(a);
}
}
]]></code>
</test-code>
</test-data>