-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4677 from tprouvot:feature/apex/avoidGetGlobalDes…
…cribesInLoops [apex] Add new rule: OperationWithHighCostInLoop #4677
- Loading branch information
Showing
8 changed files
with
285 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
.../java/net/sourceforge/pmd/lang/apex/rule/performance/OperationWithHighCostInLoopRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html | ||
*/ | ||
|
||
package net.sourceforge.pmd.lang.apex.rule.performance; | ||
|
||
import java.util.Locale; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
import org.checkerframework.checker.nullness.qual.NonNull; | ||
|
||
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; | ||
import net.sourceforge.pmd.lang.rule.RuleTargetSelector; | ||
import net.sourceforge.pmd.util.CollectionUtil; | ||
|
||
/** | ||
* Warn users when code that could impact performance is executing within a | ||
* looping construct. | ||
*/ | ||
public class OperationWithHighCostInLoopRule extends AbstractAvoidNodeInLoopsRule { | ||
|
||
private static final Set<String> SCHEMA_PERFORMANCE_METHODS = CollectionUtil.setOf( | ||
"System.Schema.getGlobalDescribe", | ||
"Schema.getGlobalDescribe", | ||
"System.Schema.describeSObjects", | ||
"Schema.describeSObjects") | ||
.stream().map(s -> s.toLowerCase(Locale.ROOT)).collect(Collectors.toSet()); | ||
|
||
@Override | ||
protected @NonNull RuleTargetSelector buildTargetSelector() { | ||
return RuleTargetSelector.forTypes( | ||
// performance consuming methods | ||
ASTMethodCallExpression.class); | ||
} | ||
|
||
// Begin general method invocations | ||
@Override | ||
public Object visit(ASTMethodCallExpression node, Object data) { | ||
if (checkHighCostClassMethods(node)) { | ||
return checkForViolation(node, data); | ||
} else { | ||
return data; | ||
} | ||
} | ||
|
||
private boolean checkHighCostClassMethods(ASTMethodCallExpression node) { | ||
return SCHEMA_PERFORMANCE_METHODS.contains(node.getFullMethodName().toLowerCase(Locale.ROOT)); | ||
} | ||
// End general method invocations | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
.../java/net/sourceforge/pmd/lang/apex/rule/performance/OperationWithHighCostInLoopTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html | ||
*/ | ||
|
||
package net.sourceforge.pmd.lang.apex.rule.performance; | ||
|
||
import net.sourceforge.pmd.testframework.PmdRuleTst; | ||
|
||
class OperationWithHighCostInLoopTest extends PmdRuleTst { | ||
// no additional unit tests | ||
} |
138 changes: 138 additions & 0 deletions
138
...ources/net/sourceforge/pmd/lang/apex/rule/performance/xml/OperationWithHighCostInLoop.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?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"> | ||
|
||
<!-- Begin Schema method invocations --> | ||
<test-code> | ||
<description>High cost performance getGlobalDescribe in loop (correct code) #4675</description> | ||
<expected-problems>0</expected-problems> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testGetGlobalDescribe() { | ||
Map<String, Schema.SObjectField> fieldMap = Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap(); | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (fieldMap.containsKey(fieldNameOrDefaultValue.trim())) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance getGlobalDescribe in loop #4675</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>5</expected-linenumbers> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testGetGlobalDescribe() { | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap().containsKey(fieldNameOrDefaultValue.trim() )) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance getGlobalDescribe in loop - fully qualified #4675</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>5</expected-linenumbers> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testGetGlobalDescribe() { | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (System.Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap().containsKey(fieldNameOrDefaultValue.trim() )) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance describeSObjects in loop (correct code) #4675</description> | ||
<expected-problems>0</expected-problems> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testDescribeSObjects() { | ||
Map<String, Schema.SObjectField> fieldMap = Schema.describeSObjects(new List<String> { 'Account' })[0].fields.getMap(); | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (fieldMap.containsKey(fieldNameOrDefaultValue.trim())) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance describeSObjects in loop #4675</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>6</expected-linenumbers> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testDescribeSObjects() { | ||
String sObjectType = 'Account'; | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (Schema.describeSObjects(new List<String> { sObjectType })[0].fields.getMap().containsKey(fieldNameOrDefaultValue.trim())) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance describeSObjects in loop with SObjectDescribeOptions #4675</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>6</expected-linenumbers> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testDescribeSObjects() { | ||
String sObjectType = 'Account'; | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (Schema.describeSObjects(new List<String> { sObjectType }, SObjectDescribeOptions.FULL)[0].fields.getMap().containsKey(fieldNameOrDefaultValue.trim())) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>High cost performance describeSObjects in loop - fully qualified #4675</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>6</expected-linenumbers> | ||
<code><![CDATA[ | ||
public class Foo { | ||
public void testDescribeSObjects() { | ||
String sObjectType = 'Account'; | ||
Set<String> fieldNameSet = new Set<String> {'Id'}; | ||
for (String fieldNameOrDefaultValue : fieldNameOrDefaultValueList) { | ||
if (System.Schema.describeSObjects(new List<String> { sObjectType })[0].fields.getMap().containsKey(fieldNameOrDefaultValue.trim())) { | ||
fieldNameSet.add(fieldNameOrDefaultValue); | ||
} | ||
} | ||
} | ||
} | ||
]]></code> | ||
</test-code> | ||
<!-- End Schema method invocations --> | ||
</test-data> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters