This article is based on the PMD documentation article. See the original article on the PMD site: PMD: best practices.
Best practices which enforce a specific coding style.
AssignmentInOperand #
Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime indicative of the bug where the assignment operator ‘=’ was used instead of the equality operator ‘==’.
This rule is defined by the following XPath expression://IfStatement[$allowIf = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //WhileLoop[$allowWhile = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //DoLoop[$allowWhile = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ForLoop[$allowFor = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ConditionalExpression[$allowTernary = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ConditionalExpression[$allowTernaryResults = false()]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]]
Example #
var x = 2; // Bad if ((x = getX()) == 3) { alert(‘3!’); } function getX() { return 3; }
Properties #
Name | Default Value | Description | Multivalued |
---|---|---|---|
allowIf | false | Allow assignment within the conditional expression of an if statement | no |
allowFor | false | Allow assignment within the conditional expression of a for statement | no |
allowWhile | false | Allow assignment within the conditional expression of a while statement | no |
allowTernary | false | Allow assignment within the conditional expression of a ternary operator | no |
allowTernaryResults | false | Allow assignment within the result expressions of a ternary operator | no |
allowIncrementDecrement | false | Allow increment or decrement operators within the conditional expression of an if, for, or while statement | no |
AvoidWithStatement #
Avoid using with – it’s bad news
This rule is defined by the following XPath expression://WithStatement
Example #
with (object) { property = 3; // Might be on object, might be on window: who knows. }
ClassNamingConventions #
Class names should always begin with an upper case character.
This rule is defined by the following Java class:
net.sourceforge.pmd.lang.apex.rule.codestyle.ClassNamingConventionsRule
Example #
public class Foo {}
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 |
ConsistentReturn #
ECMAScript does provide for return types on functions, and therefore there is no solid rule as to their usage. However, when a function does use returns they should all have a value, or all with no value. Mixed return usage is likely a bug, or at best poor style.
This rule is defined by the following Java class:
net.sourceforge.pmd.lang.ecmascript.rule.bestpractices.ConsistentReturnRule
Example #
// Ok function foo() { if (condition1) { return true; } return false; } // Bad function bar() { if (condition1) { return; } return false; }
Parameters #
Name | Default Value | Description | Multivalued |
---|---|---|---|
rhinoLanguageVersion | ES6 | Specifies the Rhino Language Version to use for parsing. Defaults to ES6. | no |
recordingLocalJsDocComments | true | Specifies that JsDoc comments are produced in the AST. | no |
recordingComments | true | Specifies that comments are produced in the AST. | no |
ForLoopsMustUseBraces #
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 from the rest.
//ForLoopStatement/BlockStatement[@CurlyBrace='false']
|
//ForEachStatement/BlockStatement[@CurlyBrace='false']
Example #
for (int i = 0; i < 42; i++) // not recommended foo(); for (int i = 0; i < 42; i++) { // preferred approach foo(); }
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 |
GlobalVariable #
This rule helps to avoid using accidently global variables by simply missing the “var” declaration. Global variables can lead to side-effects that are hard to debug.
This rule is defined by the following XPath expression://Assignment[Name/@GlobalName = true()]
Example #
function(arg) { notDeclaredVariable = 1; // this will create a global variable and trigger the rule var someVar = 1; // this is a local variable, that’s ok window.otherGlobal = 2; // this will not trigger the rule, although it is a global variable. }
IfElseStmtsMustUseBraces #
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 from the rest.
//IfBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]
|
//IfElseBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]
Example #
// this is OK if (foo) x++; // but this is not if (foo) x = x+1; else x = x-1;
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 |
IfStmtsMustUseBraces #
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 controlled from the rest.
//IfBlockStatement/BlockStatement[@CurlyBrace='false']
Example #
if (foo) // not recommended x++; if (foo) { // preferred approach x++; }
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 |
MethodNamingConventions #
Method names should always begin with a lower case character, and should not contain underscores.
This rule is defined by the following Java class:
net.sourceforge.pmd.lang.apex.rule.codestyle.MethodNamingConventionsRule
Example #
public class Foo { public void fooStuff() { } }
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 |
NoElseReturn #
The else block in a if-else-construct is unnecessary if the if
block contains a return. Then the content of the else block can be put outside.
See also: http://eslint.org/docs/rules/no-else-return
This rule is defined by the following XPath expression://IfStatement[@Else=true()][Scope[1]/ReturnStatement]
Example #
// Bad: if (x) { return y; } else { return z; } // Good: if (x) { return y; } return z;
UnnecessaryBlock #
An unnecessary Block is present. Such Blocks are often used in other languages to introduce a new variable scope. Blocks do not behave like this in ECMAScipt, and using them can be misleading. Considering removing this unnecessary Block.
This rule is defined by the following XPath expression://Block[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)] | //Scope[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)]
Example #
if (foo) { // Ok } if (bar) { { // Bad } }
UnnecessaryParentheses #
Unnecessary parentheses should be removed.
This rule is defined by the following XPath expression://ParenthesizedExpression/ParenthesizedExpression
Example #
var x = 1; // Ok var y = (1 + 1); // Ok var z = ((1 + 1)); // Bad
UnreachableCode #
A ‘return’, ‘break’, ‘continue’, or ‘throw’ statement should be the last in a block. Statements after these will never execute. This is a bug, or extremely poor style.
This rule is defined by the following XPath expression://ReturnStatement[following-sibling::node()] | //ContinueStatement[following-sibling::node()] | //BreakStatement[following-sibling::node()] | //ThrowStatement[following-sibling::node()]
Example #
// Ok function foo() { return 1; } // Bad function bar() { var x = 1; return x; x = 2; }
UseBaseWithParseInt #
This rule checks for usages of parseInt. While the second parameter is optional and usually defaults to 10 (base/radix is 10 for a decimal number), different implementations may behave differently. It also improves readability, if the base is given.
See also: parseInt()
This rule is defined by the following XPath expression://FunctionCall/Name[ @Image = ‘parseInt’ and count(../*) < 3 ]
Example #
parseInt(“010”); // unclear, could be interpreted as 10 or 7 (with a base of 7) parseInt(“10”, 10); // good
VariableNamingConventions #
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 that should not include underscores.
This rule is defined by the following Java class:
net.sourceforge.pmd.lang.apex.rule.codestyle.VariableNamingConventionsRule
Example #
public class Foo { public static final Integer MY_NUM = 0; public String myTest = ”; DataModule dmTest = new DataModule(); }
Properties #
Name | Default Value | Description |
---|---|---|
parameterSuffix | [] | Method parameter variable suffixes |
parameterPrefix | [] | Method parameter variable prefixes |
localSuffix | [] | Local variable suffixes |
localPrefix | [] | Local variable prefixes |
memberSuffix | [] | Member variable suffixes |
memberPrefix | [] | Member variable prefixes |
staticSuffix | [] | Static variable suffixes |
staticPrefix | [] | Static variable prefixes |
checkParameters | true | Check constructor and method parameter variables |
checkLocals | true | Check local variables |
cc_categories | [Style] | Code Climate Categories |
cc_remediation_points_multiplier | 1 | Code Climate Remediation Points multiplier |
cc_block_highlighting | false | Code Climate Block Highlighting |
checkMembers | true | Check member variables |
WhileLoopsMustUseBraces #
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 controlled from the rest.
//WhileLoopStatement/BlockStatement[@CurlyBrace='false']
Example #
while (true) // not recommended x++; while (true) { // preferred approach x++; }
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 |