From c0f1d36b05064c848b0b2cb9c3cf5e87b3daa390 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 13:02:59 +0200 Subject: [PATCH 01/33] First test passed --- .../design/ForLoopShouldBeForeachRule.java | 241 ++++++++++++++++++ .../main/resources/rulesets/java/design.xml | 22 ++ .../java/rule/design/DesignRulesTest.java | 1 + .../design/xml/ForLoopShouldBeForeach.xml | 16 ++ 4 files changed, 280 insertions(+) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java new file mode 100644 index 0000000000..02d7598a24 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java @@ -0,0 +1,241 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.design; + +import java.util.List; +import java.util.Map; + +import org.jaxen.JaxenException; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTForInit; +import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForUpdate; +import net.sourceforge.pmd.lang.java.ast.ASTName; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; +import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; +import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; +import net.sourceforge.pmd.lang.symboltable.NameOccurrence; +import net.sourceforge.pmd.lang.symboltable.Scope; + +/** + * @author Clément Fournier + */ +public class ForLoopShouldBeForeachRule extends AbstractJavaRule { + + + @Override + public Object visit(ASTForStatement node, Object data) { + + ASTForInit init = node.getFirstChildOfType(ASTForInit.class); + + if (init == null) { + return super.visit(node, data); + } + + String itName = init.getFirstDescendantOfType(ASTVariableDeclaratorId.class).getImage(); + + + ASTExpression guardCondition = node.getFirstChildOfType(ASTExpression.class); + + if (guardCondition == null || !isForUpdateSimpleEnough(node.getFirstChildOfType(ASTForUpdate.class), itName)) { + return super.visit(node, data); + } + + String iterableName = getIterableNameAndCheckGuardExpression(guardCondition, itName); + + + if (iterableName == null) { + return super.visit(node, data); + } + + List occurrences = getIteratorOccurencesAndCheckInit(init); + + if (occurrences == null) { + return super.visit(node, data); + } + + + VariableNameDeclaration iterableDeclaration = findDeclaration(iterableName, node.getScope()); + + if (iterableDeclaration == null) { + return super.visit(node, data); + } + + if (iterableDeclaration.isArray()) { + loopOverArrayCanBeReplaced(node); + } else if ("List".equals(iterableDeclaration.getTypeImage())) { + if (loopOverListCanBeReplaced(node, occurrences, iterableDeclaration)) { + addViolation(data, node); + } + } + + return super.visit(node, data); + } + + + /** + * Gets the name occurences of the iterator in the code block, and checks that the iterator is of type int + * + * @param init For init + * + * @return name occurences or null (then abort) + */ + private List getIteratorOccurencesAndCheckInit(ASTForInit init) { + Map> decls = init.getScope().getDeclarations(VariableNameDeclaration.class); + VariableNameDeclaration theIterator = null; + + + for (VariableNameDeclaration decl : decls.keySet()) { + ASTForInit declInit = decl.getNode().getFirstParentOfType(ASTForInit.class); + if (declInit == init) { + theIterator = decl; + break; + } + } + + if (theIterator == null || !"int".equals(theIterator.getTypeImage())) { + return null; + } + + return decls.get(theIterator); + } + + + /** + * @return true if there's only one update statement of the form i++ or ++i. + */ + private boolean isForUpdateSimpleEnough(ASTForUpdate update, String itName) { + return update.hasDescendantMatchingXPath("//StatementExpressionList[count(*)=1]" + + "/StatementExpression" + + "/*[self::PostfixExpression and @Image='++' or self::PreIncrementExpression]" + + "/PrimaryExpression" + + "/PrimaryPrefix" + + "/Name[@Image='" + itName + "']"); + } + + + /** + * Gets the name of the iterable array or list. + * + * @param guardCondition The guard condition + * @param itName The name of the iterator variable + * + * @return The name, or null if it couldn't be found or the guard condition is not safe to refactor (then abort) + */ + private String getIterableNameAndCheckGuardExpression(ASTExpression guardCondition, String itName) { + + + if (guardCondition.jjtGetNumChildren() > 0 + && guardCondition.jjtGetChild(0) instanceof ASTRelationalExpression) { + + ASTRelationalExpression relationalExpression = (ASTRelationalExpression) guardCondition.jjtGetChild(0); + + if (relationalExpression.hasImageEqualTo("<")) { + + try { + List left + = guardCondition.findChildNodesWithXPath( + "//RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix/Name[@Image='" + itName + + "']"); + + List right = guardCondition.findChildNodesWithXPath( + "//RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix" + + "/Name[matches(@Image,'\\w+\\.(size|length)')]" + + "|" + + "//RelationalExpression[@Image='<=']/AdditiveExpression[count(*)=2 and " + + "@Image='-' and PrimaryExpression/PrimaryPrefix/Literal[@Image='1']]" + + "/PrimaryExpression/PrimaryPrefix/Name[matches(@Image,'\\w+\\.(size|length)')]"); + + if (left.isEmpty()) { + return null; + } else if (!right.isEmpty()) { + return right.get(0).getImage().split("\\.")[0]; + } else { + return null; + } + + } catch (JaxenException e) { + e.printStackTrace(); + return null; + } + } + } + return null; + } + + + private boolean loopOverArrayCanBeReplaced(ASTForStatement node) { + // TODO + return false; + } + + + private boolean loopOverListCanBeReplaced(ASTForStatement node, List occurrences, + VariableNameDeclaration listDeclaration) { + + String listName = listDeclaration.getName(); + + + for (NameOccurrence occ : occurrences) { + + + if (occ.getLocation().getFirstParentOfType(ASTForUpdate.class) == null + && occ.getLocation().getFirstParentOfType(ASTExpression.class) != node.getFirstChildOfType(ASTExpression.class) + && !occurenceIsListGet(occ, listName)) { + return false; + } + } + + return true; + } + + + /** @return true if this occurence is as an argument to List.get on the correct list */ + private boolean occurenceIsListGet(NameOccurrence occ, String listName) { + if (occ.getLocation() instanceof ASTName) { + ASTPrimarySuffix suffix = occ.getLocation().getFirstParentOfType(ASTPrimarySuffix.class); + + if (suffix == null) { + return false; + } + + Node prefix = suffix.jjtGetParent().jjtGetChild(0); + + if (!(prefix instanceof ASTPrimaryPrefix) && prefix.jjtGetNumChildren() != 1 + && !(prefix.jjtGetChild(0) instanceof ASTName)) { + return false; + } + + String callImage = prefix.jjtGetChild(0).getImage(); + + return (listName + ".get").equals(callImage); + + } + return false; + } + + + private VariableNameDeclaration findDeclaration(String varName, Scope innermost) { + Scope currentScope = innermost; + + while (currentScope != null) { + for (VariableNameDeclaration decl : currentScope.getDeclarations(VariableNameDeclaration.class).keySet()) { + if (decl.getImage().equals(varName)) { + return decl; + } + } + currentScope = currentScope.getParent(); + } + + return null; + } + + +} diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index 56ac9b6fce..b962b5752e 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -2001,4 +2001,26 @@ public class OuterClass { ]]> + + + + TODO + + 3 + l) { + for (int i = 0; i < l.size(); i++) { + System.out.println(l.get(i)); + } + } +} + ]]> + + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java index 46355ca512..edd2731f48 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java @@ -75,5 +75,6 @@ public class DesignRulesTest extends SimpleAggregatorTst { addRule(RULESET, "UseNotifyAllInsteadOfNotify"); addRule(RULESET, "UseUtilityClass"); addRule(RULESET, "UseVarargs"); + addRule(RULESET, "ForLoopShouldBeForeach"); } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml new file mode 100644 index 0000000000..c5ef120a67 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml @@ -0,0 +1,16 @@ + + + + Simple failure case + 1 + l) { + for (int i = 0; i < l.size(); i++) { + System.out.println(l.get(i)); + } + } + } + ]]> + + From 038503677bc5b6c7c25100278f741f6c58d0a23c Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 17:49:00 +0200 Subject: [PATCH 02/33] Added more tests --- .../design/ForLoopShouldBeForeachRule.java | 114 ++++++++++-------- .../design/xml/ForLoopShouldBeForeach.xml | 95 ++++++++++++++- 2 files changed, 155 insertions(+), 54 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java index 02d7598a24..30b4d31cb7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java @@ -18,7 +18,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; @@ -29,69 +28,63 @@ import net.sourceforge.pmd.lang.symboltable.Scope; */ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { - @Override public Object visit(ASTForStatement node, Object data) { - ASTForInit init = node.getFirstChildOfType(ASTForInit.class); + final ASTForInit init = node.getFirstChildOfType(ASTForInit.class); + final ASTForUpdate update = node.getFirstChildOfType(ASTForUpdate.class); + final ASTExpression guardCondition = node.getFirstChildOfType(ASTExpression.class); - if (init == null) { + if (init == null && update == null || guardCondition == null) { // The loop may be replaced with a while return super.visit(node, data); } - String itName = init.getFirstDescendantOfType(ASTVariableDeclaratorId.class).getImage(); - - - ASTExpression guardCondition = node.getFirstChildOfType(ASTExpression.class); - - if (guardCondition == null || !isForUpdateSimpleEnough(node.getFirstChildOfType(ASTForUpdate.class), itName)) { + VariableNameDeclaration index = getIndexVarDeclaration(init, update); + if (index == null || !"int".equals(index.getTypeImage())) { return super.visit(node, data); } - String iterableName = getIterableNameAndCheckGuardExpression(guardCondition, itName); + String itName = index.getName(); + String iterableName = getIterableNameOrNullToAbort(guardCondition, itName); - if (iterableName == null) { + if (!isForUpdateSimpleEnough(update, itName) || iterableName == null) { return super.visit(node, data); } - List occurrences = getIteratorOccurencesAndCheckInit(init); + + List occurrences = guardCondition.getScope().getDeclarations(VariableNameDeclaration.class).get(index); if (occurrences == null) { return super.visit(node, data); } - VariableNameDeclaration iterableDeclaration = findDeclaration(iterableName, node.getScope()); if (iterableDeclaration == null) { return super.visit(node, data); } - if (iterableDeclaration.isArray()) { - loopOverArrayCanBeReplaced(node); - } else if ("List".equals(iterableDeclaration.getTypeImage())) { - if (loopOverListCanBeReplaced(node, occurrences, iterableDeclaration)) { - addViolation(data, node); - } + if (iterableDeclaration.isArray() && loopOverArrayCanBeReplaced(node)) { + addViolation(data, node); + } else if ("List".equals(iterableDeclaration.getTypeImage()) + && loopOverListCanBeReplaced(node, occurrences, iterableDeclaration)) { + addViolation(data, node); } return super.visit(node, data); } - /** - * Gets the name occurences of the iterator in the code block, and checks that the iterator is of type int - * - * @param init For init - * - * @return name occurences or null (then abort) - */ - private List getIteratorOccurencesAndCheckInit(ASTForInit init) { + /* Finds the declaration of the index variable to find its name occurrences */ + private VariableNameDeclaration getIndexVarDeclaration(ASTForInit init, ASTForUpdate update) { + if (init == null) { + return guessIndexVarFromUpdate(update); + } + Map> decls = init.getScope().getDeclarations(VariableNameDeclaration.class); VariableNameDeclaration theIterator = null; - for (VariableNameDeclaration decl : decls.keySet()) { ASTForInit declInit = decl.getNode().getFirstParentOfType(ASTForInit.class); if (declInit == init) { @@ -100,11 +93,26 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } } - if (theIterator == null || !"int".equals(theIterator.getTypeImage())) { + return theIterator; + + } + + + /** Does a best guess to find the index variable, gives up if the update has several statements */ + private VariableNameDeclaration guessIndexVarFromUpdate(ASTForUpdate update) { + + Node name; + try { + name = update.findChildNodesWithXPath(getSimpleForStatementXpath(null)).get(0); + } catch (JaxenException je) { + throw new RuntimeException(je); + } + + if (name == null || name.getImage() == null) { return null; } - return decls.get(theIterator); + return findDeclaration(name.getImage(), update.getScope().getParent()); } @@ -112,24 +120,29 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { * @return true if there's only one update statement of the form i++ or ++i. */ private boolean isForUpdateSimpleEnough(ASTForUpdate update, String itName) { - return update.hasDescendantMatchingXPath("//StatementExpressionList[count(*)=1]" - + "/StatementExpression" - + "/*[self::PostfixExpression and @Image='++' or self::PreIncrementExpression]" - + "/PrimaryExpression" - + "/PrimaryPrefix" - + "/Name[@Image='" + itName + "']"); + return update.hasDescendantMatchingXPath(getSimpleForStatementXpath(itName)); + } + + + private String getSimpleForStatementXpath(String itName) { + return "//StatementExpressionList[count(*)=1]" + + "/StatementExpression" + + "/*[self::PostfixExpression and @Image='++' or self::PreIncrementExpression]" + + "/PrimaryExpression" + + "/PrimaryPrefix" + + "/Name" + + (itName == null ? "" : ("[@Image='" + itName + "']")); } /** * Gets the name of the iterable array or list. * - * @param guardCondition The guard condition - * @param itName The name of the iterator variable + * @param itName The name of the iterator variable * * @return The name, or null if it couldn't be found or the guard condition is not safe to refactor (then abort) */ - private String getIterableNameAndCheckGuardExpression(ASTExpression guardCondition, String itName) { + private String getIterableNameOrNullToAbort(ASTExpression guardCondition, String itName) { if (guardCondition.jjtGetNumChildren() > 0 @@ -137,13 +150,11 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { ASTRelationalExpression relationalExpression = (ASTRelationalExpression) guardCondition.jjtGetChild(0); - if (relationalExpression.hasImageEqualTo("<")) { + if (relationalExpression.hasImageEqualTo("<") || relationalExpression.hasImageEqualTo("<=")) { try { - List left - = guardCondition.findChildNodesWithXPath( - "//RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix/Name[@Image='" + itName - + "']"); + List left = guardCondition.findChildNodesWithXPath( + "//RelationalExpression/PrimaryExpression/PrimaryPrefix/Name[@Image='" + itName + "']"); List right = guardCondition.findChildNodesWithXPath( "//RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix" @@ -161,9 +172,8 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { return null; } - } catch (JaxenException e) { - e.printStackTrace(); - return null; + } catch (JaxenException je) { + throw new RuntimeException(je); } } } @@ -177,7 +187,7 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } - private boolean loopOverListCanBeReplaced(ASTForStatement node, List occurrences, + private boolean loopOverListCanBeReplaced(ASTForStatement stmt, List occurrences, VariableNameDeclaration listDeclaration) { String listName = listDeclaration.getName(); @@ -185,9 +195,9 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { for (NameOccurrence occ : occurrences) { - if (occ.getLocation().getFirstParentOfType(ASTForUpdate.class) == null - && occ.getLocation().getFirstParentOfType(ASTExpression.class) != node.getFirstChildOfType(ASTExpression.class) + && occ.getLocation().getFirstParentOfType(ASTExpression.class) + != stmt.getFirstChildOfType(ASTExpression.class) && !occurenceIsListGet(occ, listName)) { return false; } @@ -236,6 +246,4 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { return null; } - - } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml index c5ef120a67..d35d3b17a2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml @@ -1,7 +1,7 @@ - Simple failure case + Positive with list 1 + + + Positive with lower or equal + 1 + lo) { + for (int i = 0; i <= lo.size() - 1; i++) { + System.out.println(lo.get(i)); + } + } + } + ]]> + +- + + Usage of index var outside get + 0 + l) { + for (int i = 0; i < l.size(); i++) { + System.out.println(i + ": " + l.get(i)); + + } + } + } + ]]> + + + + Subclass of List + + 0 + l) { + for (int i = 0; i < l.size(); i++) { + System.out.println(l.get(i)); + + } + } + } + ]]> + + + + Get called on another list + 0 + l) { + List l2 = new ArrayList<>(l); + for (int i = 0; i < l.size(); i++) { + System.out.println(l2.get(i)); + } + } + } + ]]> + + + + Backwards iteration + 0 + l) { + for (int i = l.size() - 1; i > 0; i--) { + System.out.println(i + ": " + l.get(i)); + } + } + } + ]]> + + + + Index var initialized outside for init + + 0 + l) { + int i = 0; + for (; i < l.size(); i++) { + System.out.println(l.get(i)); + } + } + } + ]]> + + + + From b9e71bf4e4096338a66d56ef03732897bad93355 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 18:16:31 +0200 Subject: [PATCH 03/33] Support for iteration on arrays --- .../design/ForLoopShouldBeForeachRule.java | 83 +++++++++++++------ .../design/xml/ForLoopShouldBeForeach.xml | 51 +++++++++++- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java index 30b4d31cb7..46eeaefd66 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.rule.design; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.jaxen.JaxenException; @@ -39,8 +40,12 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { return super.visit(node, data); } - VariableNameDeclaration index = getIndexVarDeclaration(init, update); - if (index == null || !"int".equals(index.getTypeImage())) { + Entry> indexDecl = getIndexVarDeclaration(init, update); + List occurrences = indexDecl.getValue(); + + + VariableNameDeclaration index = indexDecl.getKey(); + if (index == null || occurrences == null || !"int".equals(index.getTypeImage())) { return super.visit(node, data); } @@ -52,20 +57,13 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { return super.visit(node, data); } - - List occurrences = guardCondition.getScope().getDeclarations(VariableNameDeclaration.class).get(index); - - if (occurrences == null) { - return super.visit(node, data); - } - - VariableNameDeclaration iterableDeclaration = findDeclaration(iterableName, node.getScope()); + VariableNameDeclaration iterableDeclaration = findDeclaration(iterableName, node.getScope()).getKey(); if (iterableDeclaration == null) { return super.visit(node, data); } - if (iterableDeclaration.isArray() && loopOverArrayCanBeReplaced(node)) { + if (iterableDeclaration.isArray() && loopOverArrayCanBeReplaced(node, occurrences, iterableDeclaration)) { addViolation(data, node); } else if ("List".equals(iterableDeclaration.getTypeImage()) && loopOverListCanBeReplaced(node, occurrences, iterableDeclaration)) { @@ -77,29 +75,30 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { /* Finds the declaration of the index variable to find its name occurrences */ - private VariableNameDeclaration getIndexVarDeclaration(ASTForInit init, ASTForUpdate update) { + private Entry> getIndexVarDeclaration(ASTForInit init, ASTForUpdate update) { if (init == null) { return guessIndexVarFromUpdate(update); } Map> decls = init.getScope().getDeclarations(VariableNameDeclaration.class); - VariableNameDeclaration theIterator = null; + Entry> indexVarAndOccurrences = null; - for (VariableNameDeclaration decl : decls.keySet()) { - ASTForInit declInit = decl.getNode().getFirstParentOfType(ASTForInit.class); + for (Entry> e : decls.entrySet()) { + + ASTForInit declInit = e.getKey().getNode().getFirstParentOfType(ASTForInit.class); if (declInit == init) { - theIterator = decl; + indexVarAndOccurrences = e; break; } } - return theIterator; + return indexVarAndOccurrences; } /** Does a best guess to find the index variable, gives up if the update has several statements */ - private VariableNameDeclaration guessIndexVarFromUpdate(ASTForUpdate update) { + private Entry> guessIndexVarFromUpdate(ASTForUpdate update) { Node name; try { @@ -181,8 +180,44 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } - private boolean loopOverArrayCanBeReplaced(ASTForStatement node) { - // TODO + private boolean loopOverArrayCanBeReplaced(ASTForStatement stmt, List occurrences, + VariableNameDeclaration arrayDeclaration) { + String arrayName = arrayDeclaration.getName(); + + + for (NameOccurrence occ : occurrences) { + + if (occ.getLocation().getFirstParentOfType(ASTForUpdate.class) == null + && occ.getLocation().getFirstParentOfType(ASTExpression.class) + != stmt.getFirstChildOfType(ASTExpression.class) + && !occurenceIsArrayAccess(occ, arrayName)) { + return false; + } + } + return true; + } + + + private boolean occurenceIsArrayAccess(NameOccurrence occ, String arrayName) { + if (occ.getLocation() instanceof ASTName) { + ASTPrimarySuffix suffix = occ.getLocation().getFirstParentOfType(ASTPrimarySuffix.class); + + if (suffix == null || !suffix.isArrayDereference()) { + return false; + } + + Node prefix = suffix.jjtGetParent().jjtGetChild(0); + + if (!(prefix instanceof ASTPrimaryPrefix) && prefix.jjtGetNumChildren() != 1 + && !(prefix.jjtGetChild(0) instanceof ASTName)) { + return false; + } + + String varImage = prefix.jjtGetChild(0).getImage(); + + return (arrayName).equals(varImage); + + } return false; } @@ -232,13 +267,13 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } - private VariableNameDeclaration findDeclaration(String varName, Scope innermost) { + private Entry> findDeclaration(String varName, Scope innermost) { Scope currentScope = innermost; while (currentScope != null) { - for (VariableNameDeclaration decl : currentScope.getDeclarations(VariableNameDeclaration.class).keySet()) { - if (decl.getImage().equals(varName)) { - return decl; + for (Entry> e : currentScope.getDeclarations(VariableNameDeclaration.class).entrySet()) { + if (e.getKey().getName().equals(varName)) { + return e; } } currentScope = currentScope.getParent(); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml index d35d3b17a2..51d050f907 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml @@ -1,5 +1,7 @@ + + Positive with list 1 @@ -27,7 +29,7 @@ } ]]> -- + Usage of index var outside get 0 @@ -88,10 +90,10 @@ ]]> + Index var initialized outside for init - - 0 + 1 l) { @@ -105,5 +107,48 @@ + + Array positives + 2 + + + + + Consider iterators + 0 + i = path.iterator(); i.hasNext();) { + DataFlowNode inode = i.next(); + if (inode.getVariableAccess() == null) { + continue; + } + } + } + } + ]]> + From 1f6ef4a497bb41f5875baa2035cce0bead4cde0a Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 19:32:14 +0200 Subject: [PATCH 04/33] Removed false positives with start index != 0 --- .../design/ForLoopShouldBeForeachRule.java | 54 ++++++++++++++----- .../main/resources/rulesets/java/design.xml | 6 ++- .../design/xml/ForLoopShouldBeForeach.xml | 19 ++++++- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java index 46eeaefd66..9173b3cf69 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java @@ -19,6 +19,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; @@ -36,19 +38,21 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { final ASTForUpdate update = node.getFirstChildOfType(ASTForUpdate.class); final ASTExpression guardCondition = node.getFirstChildOfType(ASTExpression.class); - if (init == null && update == null || guardCondition == null) { // The loop may be replaced with a while + if (init == null && update == null || guardCondition == null) { return super.visit(node, data); } Entry> indexDecl = getIndexVarDeclaration(init, update); List occurrences = indexDecl.getValue(); - - VariableNameDeclaration index = indexDecl.getKey(); - if (index == null || occurrences == null || !"int".equals(index.getTypeImage())) { + + if (index == null || occurrences == null + || !"int".equals(index.getTypeImage()) + || !indexStartsAtZero(index)) { return super.visit(node, data); } + String itName = index.getName(); String iterableName = getIterableNameOrNullToAbort(guardCondition, itName); @@ -57,7 +61,8 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { return super.visit(node, data); } - VariableNameDeclaration iterableDeclaration = findDeclaration(iterableName, node.getScope()).getKey(); + Entry> iterableInfo = findDeclaration(iterableName, node.getScope()); + VariableNameDeclaration iterableDeclaration = iterableInfo == null ? null : iterableInfo.getKey(); if (iterableDeclaration == null) { return super.visit(node, data); @@ -102,7 +107,7 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { Node name; try { - name = update.findChildNodesWithXPath(getSimpleForStatementXpath(null)).get(0); + name = update.findChildNodesWithXPath(getSimpleForUpdateXpath(null)).get(0); } catch (JaxenException je) { throw new RuntimeException(je); } @@ -119,12 +124,12 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { * @return true if there's only one update statement of the form i++ or ++i. */ private boolean isForUpdateSimpleEnough(ASTForUpdate update, String itName) { - return update.hasDescendantMatchingXPath(getSimpleForStatementXpath(itName)); + return update.hasDescendantMatchingXPath(getSimpleForUpdateXpath(itName)); } - private String getSimpleForStatementXpath(String itName) { - return "//StatementExpressionList[count(*)=1]" + private String getSimpleForUpdateXpath(String itName) { + return "./StatementExpressionList[count(*)=1]" + "/StatementExpression" + "/*[self::PostfixExpression and @Image='++' or self::PreIncrementExpression]" + "/PrimaryExpression" @@ -134,6 +139,31 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } + /* We only report loops with int initializers starting at zero. */ + private boolean indexStartsAtZero(VariableNameDeclaration index) { + ASTVariableDeclaratorId name = (ASTVariableDeclaratorId) index.getNode(); + ASTVariableDeclarator declarator = name.getFirstParentOfType(ASTVariableDeclarator.class); + + if (declarator == null) { + return false; + } + + try { + List zeroLiteral = declarator.findChildNodesWithXPath + ("./VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image='0' and " + + "@StringLiteral='false']"); + if (!zeroLiteral.isEmpty()) { + return true; + } + } catch (JaxenException je) { + throw new RuntimeException(je); + } + + return false; + + } + + /** * Gets the name of the iterable array or list. * @@ -153,13 +183,13 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { try { List left = guardCondition.findChildNodesWithXPath( - "//RelationalExpression/PrimaryExpression/PrimaryPrefix/Name[@Image='" + itName + "']"); + "./RelationalExpression/PrimaryExpression/PrimaryPrefix/Name[@Image='" + itName + "']"); List right = guardCondition.findChildNodesWithXPath( - "//RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix" + "./RelationalExpression[@Image='<']/PrimaryExpression/PrimaryPrefix" + "/Name[matches(@Image,'\\w+\\.(size|length)')]" + "|" - + "//RelationalExpression[@Image='<=']/AdditiveExpression[count(*)=2 and " + + "./RelationalExpression[@Image='<=']/AdditiveExpression[count(*)=2 and " + "@Image='-' and PrimaryExpression/PrimaryPrefix/Literal[@Image='1']]" + "/PrimaryExpression/PrimaryPrefix/Name[matches(@Image,'\\w+\\.(size|length)')]"); diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index b962b5752e..36ab2ce2f2 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -2015,9 +2015,13 @@ public class OuterClass { l) { - for (int i = 0; i < l.size(); i++) { + for (int i = 0; i < l.size(); i++) { // pre Java 1.5 System.out.println(l.get(i)); } + + for (String s : l) { // post Java 1.5 + System.out.println(s); + } } } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml index 51d050f907..fc57ee64b6 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml @@ -135,7 +135,7 @@ - Consider iterators + TODO Consider iterators 0 + + + Index var starts after zero + 0 + l) { + for (int i = 1; i < filters.size(); i++) { + builder.append(' ').append(getOperator()).append(' '); + builder.append(filters.get(i)); + } + } + } + ]]> + + + From d749166191de6f5313ab972807c42397031735f6 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 21:35:06 +0200 Subject: [PATCH 05/33] Prefix increment works --- ...Rule.java => ForLoopCanBeForeachRule.java} | 19 +++++++++---- .../main/resources/rulesets/java/design.xml | 8 +++--- ...dBeForeach.xml => ForLoopCanBeForeach.xml} | 27 ++++++++++++++++--- 3 files changed, 42 insertions(+), 12 deletions(-) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/{ForLoopShouldBeForeachRule.java => ForLoopCanBeForeachRule.java} (95%) rename pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/{ForLoopShouldBeForeach.xml => ForLoopCanBeForeach.xml} (84%) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java similarity index 95% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java index 9173b3cf69..19ecaec292 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopShouldBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java @@ -29,7 +29,7 @@ import net.sourceforge.pmd.lang.symboltable.Scope; /** * @author Clément Fournier */ -public class ForLoopShouldBeForeachRule extends AbstractJavaRule { +public class ForLoopCanBeForeachRule extends AbstractJavaRule { @Override public Object visit(ASTForStatement node, Object data) { @@ -43,6 +43,12 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } Entry> indexDecl = getIndexVarDeclaration(init, update); + + if (indexDecl == null) { + return super.visit(node, data); + } + + List occurrences = indexDecl.getValue(); VariableNameDeclaration index = indexDecl.getKey(); @@ -79,7 +85,7 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { } - /* Finds the declaration of the index variable to find its name occurrences */ + /* Finds the declaration of the index variable and its occurrences */ private Entry> getIndexVarDeclaration(ASTForInit init, ASTForUpdate update) { if (init == null) { return guessIndexVarFromUpdate(update); @@ -105,9 +111,12 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { /** Does a best guess to find the index variable, gives up if the update has several statements */ private Entry> guessIndexVarFromUpdate(ASTForUpdate update) { - Node name; + Node name = null; try { - name = update.findChildNodesWithXPath(getSimpleForUpdateXpath(null)).get(0); + List match = update.findChildNodesWithXPath(getSimpleForUpdateXpath(null)); + if (!match.isEmpty()) { + name = match.get(0); + } } catch (JaxenException je) { throw new RuntimeException(je); } @@ -124,7 +133,7 @@ public class ForLoopShouldBeForeachRule extends AbstractJavaRule { * @return true if there's only one update statement of the form i++ or ++i. */ private boolean isForUpdateSimpleEnough(ASTForUpdate update, String itName) { - return update.hasDescendantMatchingXPath(getSimpleForUpdateXpath(itName)); + return update != null && update.hasDescendantMatchingXPath(getSimpleForUpdateXpath(itName)); } diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index 36ab2ce2f2..7ff23e802f 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -2002,12 +2002,12 @@ public class OuterClass { - + message="This 'for' loop can be replaced by a 'foreach' loop" + class="net.sourceforge.pmd.lang.java.rule.design.ForLoopCanBeForeachRule" + externalInfoUrl="${pmd.website.baseurl}/rules/java/design.html#ForLoopCanBeForeach"> TODO diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml similarity index 84% rename from pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml rename to pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml index fc57ee64b6..140ac7482e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopShouldBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml @@ -46,8 +46,7 @@ - Subclass of List - + TODO Subclass of List 0 l) { - for (int i = l.size() - 1; i > 0; i--) { + for (int i = l.size() - 1; i > 0; i-= 1) { System.out.println(i + ": " + l.get(i)); } } @@ -168,4 +167,26 @@ + + Prefix increment should work + 1 + apexNode = (ApexNode) children[i]; + apexNode.jjtAccept(visitor, data); + } + } + return data; + } + } + ]]> + + From ff89698cd288286363f320dd5068df2ef6487d00 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 23:11:23 +0200 Subject: [PATCH 06/33] Considers iterators --- .../rule/design/ForLoopCanBeForeachRule.java | 73 ++++++++++++++----- .../java/rule/design/DesignRulesTest.java | 2 +- .../rule/design/xml/ForLoopCanBeForeach.xml | 42 ++++++++++- 3 files changed, 95 insertions(+), 22 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java index 19ecaec292..c0bb66258a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java @@ -52,6 +52,11 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { List occurrences = indexDecl.getValue(); VariableNameDeclaration index = indexDecl.getKey(); + if ("Iterator".equals(index.getTypeImage()) && isReplaceableIteratorLoop(indexDecl, guardCondition, update)) { + addViolation(data, node); + } + + if (index == null || occurrences == null || !"int".equals(index.getTypeImage()) || !indexStartsAtZero(index)) { @@ -74,10 +79,10 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { return super.visit(node, data); } - if (iterableDeclaration.isArray() && loopOverArrayCanBeReplaced(node, occurrences, iterableDeclaration)) { + if (iterableDeclaration.isArray() && isReplaceableArrayLoop(node, occurrences, iterableDeclaration)) { addViolation(data, node); } else if ("List".equals(iterableDeclaration.getTypeImage()) - && loopOverListCanBeReplaced(node, occurrences, iterableDeclaration)) { + && isReplaceableListLoop(node, occurrences, iterableDeclaration)) { addViolation(data, node); } @@ -158,9 +163,9 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { } try { - List zeroLiteral = declarator.findChildNodesWithXPath - ("./VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image='0' and " - + "@StringLiteral='false']"); + List zeroLiteral = declarator.findChildNodesWithXPath( + "./VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image='0' and " + + "@StringLiteral='false']"); if (!zeroLiteral.isEmpty()) { return true; } @@ -219,8 +224,8 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { } - private boolean loopOverArrayCanBeReplaced(ASTForStatement stmt, List occurrences, - VariableNameDeclaration arrayDeclaration) { + private boolean isReplaceableArrayLoop(ASTForStatement stmt, List occurrences, + VariableNameDeclaration arrayDeclaration) { String arrayName = arrayDeclaration.getName(); @@ -245,24 +250,17 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { return false; } - Node prefix = suffix.jjtGetParent().jjtGetChild(0); - - if (!(prefix instanceof ASTPrimaryPrefix) && prefix.jjtGetNumChildren() != 1 - && !(prefix.jjtGetChild(0) instanceof ASTName)) { - return false; - } - - String varImage = prefix.jjtGetChild(0).getImage(); - - return (arrayName).equals(varImage); - + return suffix.hasDescendantMatchingXPath("./Expression/PrimaryExpression[count(*)" + + "=1]/PrimaryPrefix/Name[@Image='" + occ.getImage() + "']") + && suffix.hasDescendantMatchingXPath("../PrimaryPrefix/Name[@Image='" + arrayName + "']") + && !suffix.hasDescendantMatchingXPath("../../AssignmentOperator"); } return false; } - private boolean loopOverListCanBeReplaced(ASTForStatement stmt, List occurrences, - VariableNameDeclaration listDeclaration) { + private boolean isReplaceableListLoop(ASTForStatement stmt, List occurrences, + VariableNameDeclaration listDeclaration) { String listName = listDeclaration.getName(); @@ -320,4 +318,39 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { return null; } + + + private boolean isReplaceableIteratorLoop(Entry> indexInfo, + ASTExpression guardCondition, ASTForUpdate update) { + + String indexName = indexInfo.getKey().getName(); + + if (indexName == null) { + return false; + } + + if (!guardCondition.hasDescendantMatchingXPath( + "./PrimaryExpression/PrimaryPrefix/Name[@Image='" + indexName + ".hasNext']")) { + return false; + } + + List occurrences = indexInfo.getValue(); + + if (occurrences.size() > 2) { + return false; + } + + for (NameOccurrence occ : indexInfo.getValue()) { + String image = occ.getLocation().getImage(); + + if (occ.getLocation() instanceof ASTName + && ((indexName + ".hasNext").equals(image) || (indexName + ".next").equals(image))) { + continue; + } + return false; + } + return true; + } + + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java index edd2731f48..dc0a08f537 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java @@ -75,6 +75,6 @@ public class DesignRulesTest extends SimpleAggregatorTst { addRule(RULESET, "UseNotifyAllInsteadOfNotify"); addRule(RULESET, "UseUtilityClass"); addRule(RULESET, "UseVarargs"); - addRule(RULESET, "ForLoopShouldBeForeach"); + addRule(RULESET, "ForLoopCanBeForeach"); } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml index 140ac7482e..cdba148dce 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml @@ -135,7 +135,7 @@ TODO Consider iterators - 0 + 1 + + Index inside arithmetic expression should whitelist the loop + 0 + + + + + + Array assignment whitelists the loop + 0 + + + + + + + From c9d3c8b5aedb0ce2d849fc1a295e189000432763 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 11 Aug 2017 23:22:26 +0200 Subject: [PATCH 07/33] Moved to migrating ruleset --- .../ForLoopCanBeForeachRule.java | 2 +- .../main/resources/rulesets/java/design.xml | 26 ------------------ .../resources/rulesets/java/migrating.xml | 27 ++++++++++++++++++- .../java/rule/design/DesignRulesTest.java | 1 - .../rule/migrating/MigratingRulesTest.java | 1 + .../xml/ForLoopCanBeForeach.xml | 4 --- 6 files changed, 28 insertions(+), 33 deletions(-) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/{design => migrating}/ForLoopCanBeForeachRule.java (99%) rename pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/{design => migrating}/xml/ForLoopCanBeForeach.xml (99%) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java similarity index 99% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java index c0bb66258a..2069e0b261 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.rule.design; +package net.sourceforge.pmd.lang.java.rule.migrating; import java.util.List; import java.util.Map; diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index 7ff23e802f..56ac9b6fce 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -2001,30 +2001,4 @@ public class OuterClass { ]]> - - - - TODO - - 3 - l) { - for (int i = 0; i < l.size(); i++) { // pre Java 1.5 - System.out.println(l.get(i)); - } - - for (String s : l) { // post Java 1.5 - System.out.println(s); - } - } -} - ]]> - - diff --git a/pmd-java/src/main/resources/rulesets/java/migrating.xml b/pmd-java/src/main/resources/rulesets/java/migrating.xml index a69a5b1d00..2418f40c15 100644 --- a/pmd-java/src/main/resources/rulesets/java/migrating.xml +++ b/pmd-java/src/main/resources/rulesets/java/migrating.xml @@ -473,4 +473,29 @@ public class MyTest { - \ No newline at end of file + + + TODO + + 3 + l) { + for (int i = 0; i < l.size(); i++) { // pre Java 1.5 + System.out.println(l.get(i)); + } + + for (String s : l) { // post Java 1.5 + System.out.println(s); + } + } +} + ]]> + + + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java index dc0a08f537..46355ca512 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DesignRulesTest.java @@ -75,6 +75,5 @@ public class DesignRulesTest extends SimpleAggregatorTst { addRule(RULESET, "UseNotifyAllInsteadOfNotify"); addRule(RULESET, "UseUtilityClass"); addRule(RULESET, "UseVarargs"); - addRule(RULESET, "ForLoopCanBeForeach"); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/migrating/MigratingRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/migrating/MigratingRulesTest.java index f20dbc1485..4354dca831 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/migrating/MigratingRulesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/migrating/MigratingRulesTest.java @@ -15,6 +15,7 @@ public class MigratingRulesTest extends SimpleAggregatorTst { addRule(RULESET, "AvoidAssertAsIdentifier"); addRule(RULESET, "AvoidEnumAsIdentifier"); addRule(RULESET, "ByteInstantiation"); + addRule(RULESET, "ForLoopCanBeForeach"); addRule(RULESET, "IntegerInstantiation"); addRule(RULESET, "JUnit4SuitesShouldUseSuiteAnnotation"); addRule(RULESET, "JUnit4TestShouldUseAfterAnnotation"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/migrating/xml/ForLoopCanBeForeach.xml similarity index 99% rename from pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml rename to pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/migrating/xml/ForLoopCanBeForeach.xml index cdba148dce..7676286b73 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ForLoopCanBeForeach.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/migrating/xml/ForLoopCanBeForeach.xml @@ -225,8 +225,4 @@ ]]> - - - - From dda923fe1ef02849dce02a0dc688df20fabf716c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Aug 2017 10:33:43 +0200 Subject: [PATCH 08/33] [doc] Rework introduction page --- docs/_config.yml | 1 + docs/_data/sidebars/pmd_sidebar.yml | 3 + docs/_includes/sidebar.html | 4 ++ docs/index.md | 90 ++++++++++++++++++++++----- docs/pages/pmd/devdocs/development.md | 11 ++++ 5 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 docs/pages/pmd/devdocs/development.md diff --git a/docs/_config.yml b/docs/_config.yml index 67e10eb08d..2064c7c9d4 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -2,6 +2,7 @@ repository: pmd/pmd pmd: version: 6.0.0 + date: to-be-defined output: web # this property is useful for conditional filtering of content that is separate from the PDF. diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index d9931c56af..775cabc9d9 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -120,6 +120,9 @@ entries: - title: Developer Documentation output: web, pdf folderitems: + - title: Developer Resources + url: /pmd_devdocs_development.html + output: web, pdf - title: Code Style url: /pmd_devdocs_codestyle.html output: web, pdf diff --git a/docs/_includes/sidebar.html b/docs/_includes/sidebar.html index 30adf87229..51bfa69a32 100644 --- a/docs/_includes/sidebar.html +++ b/docs/_includes/sidebar.html @@ -6,7 +6,11 @@ {% for folder in entry.folders %} {% if folder.output contains "web" %}
  • + {% if folder.url %} + {{ folder.title }} + {% else %} {{ folder.title }} + {% endif %}
      {% for folderitem in folder.folderitems %} {% if folderitem.output contains "web" %} diff --git a/docs/index.md b/docs/index.md index 89247e9ed1..d731612063 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,38 +2,94 @@ title: PMD Introduction keywords: java tags: [getting_started] -sidebar: pmd_sidebar permalink: index.html -summary: Welcome to PMD, an extensible cross-language static code analyzer. +toc: false +summary: > + Welcome to PMD, an extensible cross-language static code analyzer. + It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, + and so forth. Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code. +last_updated: August 2017 --- {% include image.html file="pmd-logo-big.png" alt="PMD Logo" %} -# Welcome to PMD - -PMD scans source code in Java and other languages and looks for potential problems like: +**PMD** scans source code in Java and other languages and looks for potential problems like: * Possible bugs - empty try/catch/finally/switch statements * Dead code - unused local variables, parameters and private methods * Suboptimal code - wasteful String/StringBuffer usage * Overcomplicated expressions - unnecessary if statements, for loops that could be while loops -* Duplicate code - copied/pasted code means copied/pasted bugs -## Download +**CPD**, the copy-pase-detector, finds duplicated code in many languages: -You can [download everything from here](https://github.com/pmd/pmd/releases). +* Duplicate code is often just copied and pasted. This means, the bugs are also copied and pasted. Fixing + them means, fix all duplicated code locations. -You can get an overview of all the rules for e.g. Java at the [rulesets index](pmd_rules_java.html) page. +## Features -PMD is [integrated](pmd_userdocs_tools.html) with JDeveloper, Eclipse, JEdit, JBuilder, BlueJ, CodeGuide, NetBeans/Sun Java Studio Enterprise/Creator, IntelliJ IDEA, TextPad, Maven, Ant, Gel, JCreator, and Emacs. +{::options parse_block_html="true" /} + +
      +### PMD + +Features: + +* Supporting 8 languages +* Many ready-to-use built-in rules. +* Custom rules can be written in Java +* Custom rules can be written using XPath expression that query the AST of the sources +* Many output formats +* Many integrations into IDEs, build tools + +Supported Languages: + +* [Java](pmd_rules_java.html) +* [JavaScript](pmd_rules_ecmascript.html) +* [Salesforce.com Apex](pmd_rules_apex.html) and [Visualforce](pmd_rules_vf.html) +* [PLSQL](pmd_rules_plsql.html) +* [Apache Velocity](pmd_rules_vm.html) +* [XML](pmd_rules_xml.html) and [Maven POM](pmd_rules_pom.html) +* [XSL](pmd_rules_xsl.html) + +
      +### CPD + +Features: + +* Supporting 19 languages +* Simple GUI +* Fast +* Many integrations + +Supported Languages: + +* Java +* C, C++ +* C# +* Groovy +* PHP +* Ruby +* Fortran +* JavaScript +* PLSQL +* Apache Velocity +* Scala +* Objective C +* Matlab +* Python +* Go +* Swift +* Salesforce.com Apex and Visualforce + +
      + +## Download PMD {{ site.pmd.version }} + +Latest Version: {{ site.pmd.version }} ({{ site.pmd.date }}) + +* [Release Notes](pmd_release_notes.html) +* [Download](https://github.com/pmd/pmd/releases) -## Future Releases - -The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed. - -A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated daily by our continuous integration server. - -Maven packages are also generated regularly and uploaded to [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). {% include links.html %} diff --git a/docs/pages/pmd/devdocs/development.md b/docs/pages/pmd/devdocs/development.md new file mode 100644 index 0000000000..004bd26baf --- /dev/null +++ b/docs/pages/pmd/devdocs/development.md @@ -0,0 +1,11 @@ +--- +title: Developer Resources +permalink: pmd_devdocs_development.html +--- +The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed. + + + +A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated daily by our continuous integration server. + +Maven packages are also generated regularly and uploaded to [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). From fd1a3b78fa6fbcbb6e88a792946e39ab47544c52 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Aug 2017 10:47:11 +0200 Subject: [PATCH 09/33] [doc] Create developer resources --- docs/pages/pmd/devdocs/development.md | 29 +++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/pages/pmd/devdocs/development.md b/docs/pages/pmd/devdocs/development.md index 004bd26baf..d3acec6821 100644 --- a/docs/pages/pmd/devdocs/development.md +++ b/docs/pages/pmd/devdocs/development.md @@ -1,11 +1,36 @@ --- title: Developer Resources permalink: pmd_devdocs_development.html +last_updated: August 2017 --- The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed. +## Source Code +The complete source code can be found on github: -A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated daily by our continuous integration server. +* [github.com/pmd/pmd](https://github.com/pmd/pmd) - main PMD repository. Includes all the code to support all languages, including this documentation. +* [github.com/pmd/pmd.github.io](https://github.com/pmd/pmd.github.io) - Contains the landing page [https://pmd.github.io](https://pmd.github.io) +* [github.com/pmd/build-tools](https://github.com/pmd/build-tools) - Contains the checkstyle rules we use +* [github.com/pmd/pmd-eclipse-plugin](https://github.com/pmd/pmd-eclipse-plugin) - The PMD eclipse plugin +* [github.com/pmd](https://github.com/pmd) - PMD Organization at github. There are a couple of more repositories -Maven packages are also generated regularly and uploaded to [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). +## Continuous Integration + +We use [Travis CI](https://travis-ci.org/pmd) as our ci service. The main repo and the eclipse plugin are built for +every push. Each pull request is built as well. + +The maven snapshot artifacts are deployed at [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). + +Ready-to-use binary packages are uploaded to sourceforge at . + +## Documentation and Webpages + +A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated travis-ci as well. + +## Contributing + +First off, thanks for taking the time to contribute! + +Please have a look at [CONTRIBUTING.md](https://github.com/pmd/pmd/blob/master/CONTRIBUTING.md) and +[BUILDING.md](https://github.com/pmd/pmd/blob/master/BUILDING.md). From 7194328c4f2aaa637391a9cb839b318ea666b5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 17 Aug 2017 22:50:56 +0200 Subject: [PATCH 10/33] Completed doc and tests --- .../java/rule/migrating/ForLoopCanBeForeachRule.java | 8 ++++---- pmd-java/src/main/resources/rulesets/java/migrating.xml | 9 ++++++--- .../lang/java/rule/migrating/xml/ForLoopCanBeForeach.xml | 6 +++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java index 2069e0b261..e83d5012ef 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java @@ -28,6 +28,7 @@ import net.sourceforge.pmd.lang.symboltable.Scope; /** * @author Clément Fournier + * @since 6.0.0 */ public class ForLoopCanBeForeachRule extends AbstractJavaRule { @@ -57,9 +58,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { } - if (index == null || occurrences == null - || !"int".equals(index.getTypeImage()) - || !indexStartsAtZero(index)) { + if (occurrences == null || !"int".equals(index.getTypeImage()) || !indexStartsAtZero(index)) { return super.visit(node, data); } @@ -81,7 +80,8 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { if (iterableDeclaration.isArray() && isReplaceableArrayLoop(node, occurrences, iterableDeclaration)) { addViolation(data, node); - } else if ("List".equals(iterableDeclaration.getTypeImage()) + } else if (iterableDeclaration.getTypeImage() != null && iterableDeclaration.getTypeImage() + .matches("List|ArrayList|LinkedList") && isReplaceableListLoop(node, occurrences, iterableDeclaration)) { addViolation(data, node); } diff --git a/pmd-java/src/main/resources/rulesets/java/migrating.xml b/pmd-java/src/main/resources/rulesets/java/migrating.xml index ac18dfa989..59c68d4e7c 100644 --- a/pmd-java/src/main/resources/rulesets/java/migrating.xml +++ b/pmd-java/src/main/resources/rulesets/java/migrating.xml @@ -483,9 +483,12 @@ public class MyTest { message="This 'for' loop can be replaced by a 'foreach' loop" class="net.sourceforge.pmd.lang.java.rule.migrating.ForLoopCanBeForeachRule" externalInfoUrl="${pmd.website.baseurl}/rules/java/migrating.html#ForLoopCanBeForeach"> - - TODO - + 3 - TODO Subclass of List - 0 + Subclass of List + 1 l) { @@ -134,7 +134,7 @@ - TODO Consider iterators + Consider iterators 1 Date: Fri, 18 Aug 2017 13:56:31 +0200 Subject: [PATCH 11/33] Fix failed build --- pmd-java/src/main/resources/rulesets/java/migrating.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/rulesets/java/migrating.xml b/pmd-java/src/main/resources/rulesets/java/migrating.xml index 59c68d4e7c..cdaa5c26b0 100644 --- a/pmd-java/src/main/resources/rulesets/java/migrating.xml +++ b/pmd-java/src/main/resources/rulesets/java/migrating.xml @@ -482,7 +482,7 @@ public class MyTest { since="6.0" message="This 'for' loop can be replaced by a 'foreach' loop" class="net.sourceforge.pmd.lang.java.rule.migrating.ForLoopCanBeForeachRule" - externalInfoUrl="${pmd.website.baseurl}/rules/java/migrating.html#ForLoopCanBeForeach"> + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_migrating.html#forloopcanbeforeach"> Date: Fri, 18 Aug 2017 19:06:39 +0200 Subject: [PATCH 12/33] [doc] Add "Writing Documentation" --- docs/README.md | 19 +-- docs/_data/sidebars/pmd_sidebar.yml | 3 + .../pmd/devdocs/writing_documentation.md | 140 ++++++++++++++++++ 3 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 docs/pages/pmd/devdocs/writing_documentation.md diff --git a/docs/README.md b/docs/README.md index 17c8437056..a183bdfa9a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,15 +7,16 @@ This site was built using the tomjohnson1492/documentation-theme-jekyll theme A Jekyll-based theme designed for documentation and help systems. See the link for detailed instructions on setting up and configuring everything. http://idratherbewriting.com/documentation-theme-jekyll/ +## Building using Bundler -Build the site to see the instructions for using it. Or just go here: [http://idratherbewriting.com/documentation-theme-jekyll/](http://idratherbewriting.com/documentation-theme-jekyll/) - -Run `bundle exec jekyll serve --watch` to fire up Jekyll on local machine - -## Using Docker - -One time: `docker build --no-cache -t mydocs .` - -Now run the site with `docker run --rm=true -v "$PWD:/src" -p 4005:4005 mydocs serve -H 0.0.0.0` + bundle install # once + bundle exec jekyll serve + +Go to: http://localhost:4005/ + +## Building using Docker + + docker build --no-cache -t pmd-doc . # once + docker run --rm=true -v "$PWD:/src" -p 4005:4005 pmd-doc serve -H 0.0.0.0 Go to: http://localhost:4005/ diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 775cabc9d9..81dfb2ea53 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -123,6 +123,9 @@ entries: - title: Developer Resources url: /pmd_devdocs_development.html output: web, pdf + - title: Writing Documentation + url: /pmd_devdocs_writing_documentation.html + output: web, pdf - title: Code Style url: /pmd_devdocs_codestyle.html output: web, pdf diff --git a/docs/pages/pmd/devdocs/writing_documentation.md b/docs/pages/pmd/devdocs/writing_documentation.md new file mode 100644 index 0000000000..d04e991bf1 --- /dev/null +++ b/docs/pages/pmd/devdocs/writing_documentation.md @@ -0,0 +1,140 @@ +--- +title: Writing Documentation +last_update: August 2017 +permalink: pmd_devdocs_writing_documentation.html +keywords: documentation, jekyll, markdown +--- + +PMD's documentation uses [Jekyll](https://jekyllrb.com/) with +the [I'd rather be writing Jekyll Theme](http://idratherbewriting.com/documentation-theme-jekyll/index.html). + +Here are some quick tips. + +## Format + +The pages are in general in [Github Flavored Markdown](https://kramdown.gettalong.org/parser/gfm.html). + +## Structure + +All documentation is stored in the folder `docs/`. This is the folder, that github and the travis-ci scripts +use to render the site. + +New pages are stored in the different subfolders under `pages`. The folder structure resembles the sidebar structure. +Since all pages use a simple *permalink*, in the rendered html pages, all pages are flattened in one directory. +This makes it easy to view the documentation also offline. + +## Building + +There are two ways, to execute jekyll: + +1. Using [bundler](http://bundler.io/). This will install all the needed ruby packages locally and execute jekyll: + + # this is required only once, to download and install the dependencies + bundle install + # this builds the documentation under _site + bundle exec jekyll build + # this runs a local webserver as http://localhost:4005 + bundle exec jekyll serve + +2. Using [docker](https://www.docker.com/). This will create a local docker image, into which all needed ruby + packages and jekyll is installed. + + # this is required only once to create a local docker image named "pmd-doc" + docker build --no-cache -t pmd-doc . + # this builds the documentation under _site + docker run --rm=true -v "$PWD:/src" pmd-doc build -H 0.0.0.0 + # this runs a local webserver as http://localhost:4005 + docker run --rm=true -v "$PWD:/src" -p 4005:4005 pmd-doc serve -H 0.0.0.0 + +The built site is stored locally in the (git ignored) directory `_site`. You can +point your browser to `_site/index.html` to see the pmd documentation. + +Alternatively, you can start the local webserver, that will serve the documentation. +Just go to http://localhost:4005. +If a page is modified, the documentation will automatically be rendered again and +all you need to do, is refreshing the page in your browser. + + +## The sidebar + +The sidebar is stored as a YAML document under `_data/sidebars/pmd_sidebar.yml`. + +Make sure to add an entry there, whenever you create a new page. + + +## The frontmatter + +Each page in jekyll begins with a YAML section at the beginning. This section +is separated by 3 dashes (`---`). Example: + + --- + title: Writing Documentation + last_update: August 2017 + permalink: pmd_devdocs_writing_documentation.html + --- + + Some Text + + # Some header + +There are a couple of possible fields. Most important and always +required are **title** and **permalink**. + +By default, a page **toc** (table of contents) is automatically generated. +You can prevent this with "toc: false". + +You can add **keywords**, that will be used for the on-site search: "keywords: documentation, jekyll, markdown" + +It's useful to maintain a **last_update** field. This will be added at the bottom of the +page. + +A **summary** can also be provided. It will be added in a box before the content. + +For a more exhaustive list, see [Pages - Frontmatter](http://idratherbewriting.com/documentation-theme-jekyll/mydoc_pages.html#frontmatter). + + +## Alerts and Callouts + +See [Alerts](http://idratherbewriting.com/documentation-theme-jekyll/mydoc_alerts.html). + +For example, a info-box can be created like this: + + {% include note.html content="This is a note." %} + +It renders as: + +{% include note.html content="This is a note." %} + +Other available types are: + +* note.html +* tip.html +* warning.html +* important.html + + +A callout is created like this: + + {% include callout.html content="This is a callout of type default.

      There are the following types available: danger, default, primary, success, info, and warning." type="default" %} + +It renders as: + +{% include callout.html content="This is a callout of type default.

      There are the following types available: danger, default, primary, success, info, and warning." type="default" %} + +## Code samples with syntax highlighting + +This is as easy as: + + ``` java + public class Foo { + public void bar() { System.out.println("x"); } + } + ``` + +This looks as follows: + +``` java +public class Foo { + public void bar() { System.out.println("x"); } +} +``` From 2c2d62a66a54575a4602c06bae689c22e319f009 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Aug 2017 19:42:12 +0200 Subject: [PATCH 13/33] [doc] Restructure Tools + Integrations --- docs/_data/sidebars/pmd_sidebar.yml | 17 +- docs/pages/pmd/userdocs/tools.md | 155 ------------------ docs/pages/pmd/userdocs/{ => tools}/ant.md | 4 +- docs/pages/pmd/userdocs/tools/maven.md | 179 +++++++++++++++++++++ 4 files changed, 194 insertions(+), 161 deletions(-) rename docs/pages/pmd/userdocs/{ => tools}/ant.md (99%) create mode 100644 docs/pages/pmd/userdocs/tools/maven.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 81dfb2ea53..a27d09d877 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -45,9 +45,20 @@ entries: - title: Suppressing url: /pmd_userdocs_suppressing.html output: web, pdf - - title: Tools / Integrations - url: /pmd_userdocs_tools.html - output: web, pdf + subfolders: + - title: Tools / Integrations + output: web, pdf + subfolderitems: + - title: Maven PMD Plugin + output: web, pdf + url: /pmd_userdocs_tools_maven.html + - title: Ant + output: web, pdf + url: /pmd_userdocs_tools_ant.html + - title: Other Tools / Integrations + output: web, pdf + url: /pmd_userdocs_tools.html + - title: FAQ url: /pmd_userdocs_faq.html output: web, pdf diff --git a/docs/pages/pmd/userdocs/tools.md b/docs/pages/pmd/userdocs/tools.md index f4b0ff7381..ab2210e8a5 100644 --- a/docs/pages/pmd/userdocs/tools.md +++ b/docs/pages/pmd/userdocs/tools.md @@ -6,8 +6,6 @@ folder: pmd/userdocs --- * IDE plugins -* build tool plugins - * [Ant Task Usage](/pmd_userdocs_ant.html) * [Continuous Integrations plugins](/pmd_userdocs_ci.html) * GUIs @@ -123,20 +121,6 @@ folder: pmd/userdocs Jiger Patel, Dale Anson - - Maven - - N/A - N/A - - - - Maven 2 and 3 - - N/A - apache.org / maven - - NetBeans SQE @@ -385,145 +369,6 @@ Also, you can change the plugin to prompt you for a directory to check by going selecting the "Ask for Directory" checkbox. -### Maven - -This section is about the maven 1 PMD plugin. The maven 2 PMD plugin page is available -[below](#Maven_2_and_3). - -#### Running the pmd plugin - -##### report - -To include the Maven report in the project reports section add the following line under -the reports element in your project.xml: - - maven-pmd-plugin - -This will add an entry to the 'project reports' section with the PMD report. - -##### manual - -To run PMD on a Maven project without adding it as a report, simply run - - maven pmd xdoc - -The PMD plugin writes the report in XML which will then be formatted into more readable HTML. - -#### Customization - -##### Changing rulesets - -To specify a set of official, built-in rulesets to be used set them in the property -maven.pmd.rulesets. You can include this setting in your project.properties file. - -A clean strategy for customizing which rules to use for a project is to write a ruleset file. -In this file you can define which rules to use, add custom rules, and -customizing which rules to include/exclude from official rulesets. More information on -writing a ruleset can be found [here](/pmd_userdocs_understanding_rulesets.html). - -Add to the root of your Maven project a pmd.xml file which contains the ruleset mentioned in -the previous paragraph. Add the following property to your project now: - - maven.pmd.rulesetfiles = ${basedir}/pmd.xml - -#### Reference - -See the PMD plugin project page here: - - - -### Maven 2 and 3 - -#### Running the pmd plugin - -##### report - -To include the mvn report in the project reports section add the following lines under -the reports element in your pom.xml: - - - - ... - - - - org.apache.maven.plugins - maven-pmd-plugin - - - - ... - - -This will add an entry to the 'project reports' section with the PMD report. - - -##### manual - -To run PMD on a Maven project without adding it as a report, simply run - - mvn pmd:pmd - -The PMD plugin writes the report in XML which will then be formatted into more readable HTML. - -#### Customization - -##### Changing rulesets - -To specify a ruleset, simply edit the previous configuration: - - - - - - org.apache.maven.plugins - maven-pmd-plugin - - - /rulesets/java/braces.xml - /rulesets/java/naming.xml - d:\rulesets\strings.xml - http://localhost/design.xml - - - - - - -The value of the 'ruleset' value can either be a relative address, an absolute address or even an url. - -A clean strategy for customizing which rules to use for a project is to write a ruleset file. -In this file you can define which rules to use, add custom rules, and -customizing which rules to include/exclude from official rulesets. More information on -writing a ruleset can be found [here](/pmd_userdocs_understanding_rulesets.html). -Note that if you include other rulesets in your own rulesets, you have to be sure that the plugin -will be able to resolve those other ruleset references. - -##### Other configurations - -The Maven 2 PMD plugin allows you to configure CPD, targetJDK, and the use of XRef to link -the report to html source files, and the file encoding: - - - org.apache.maven.plugins - maven-pmd-plugin - - true - ISO-8859-1 - 30 - 1.4 - - - -#### Reference - -For more data, please see the well documented PMD plugin project page here: - -Also, the bug tracker for this plugin is [here](http://jira.codehaus.org/browse/MPMD). - - - - ### NetBeans The [SQE](http://kenai.com/projects/sqe/) project includes PMD integration for NetBeans. diff --git a/docs/pages/pmd/userdocs/ant.md b/docs/pages/pmd/userdocs/tools/ant.md similarity index 99% rename from docs/pages/pmd/userdocs/ant.md rename to docs/pages/pmd/userdocs/tools/ant.md index 2997527ad2..d3749454cc 100644 --- a/docs/pages/pmd/userdocs/ant.md +++ b/docs/pages/pmd/userdocs/tools/ant.md @@ -1,8 +1,6 @@ --- title: Ant Task Usage -sidebar: pmd_sidebar -permalink: pmd_userdocs_ant.html -folder: pmd/userdocs +permalink: pmd_userdocs_tools_ant.html --- ## PMD diff --git a/docs/pages/pmd/userdocs/tools/maven.md b/docs/pages/pmd/userdocs/tools/maven.md new file mode 100644 index 0000000000..f3e5eae8dc --- /dev/null +++ b/docs/pages/pmd/userdocs/tools/maven.md @@ -0,0 +1,179 @@ +--- +title: Maven PMD Plugin +permalink: /pmd_userdocs_tools_maven.html +last_updated: August 2017 +--- + +## Maven 2 and 3 + +### Running the pmd plugin + +#### report + +To include the mvn report in the project reports section add the following lines under +the reports element in your pom.xml: + +``` xml + + ... + + + + org.apache.maven.plugins + maven-pmd-plugin + + + + ... + +``` + +This will add an entry to the 'project reports' section with the PMD report when you build the maven site. + + +#### manual + +To run PMD on a Maven project without adding it as a report, simply run + + mvn pmd:pmd + +The PMD plugin writes the report in XML which will then be formatted into more readable HTML. + + +#### Integrated into the build process + +You can also run PMD automatically when building your project. You even let the build fail, if +PMD finds some violations. Therefore the `check` goal is used: + +``` xml + + ... + + + + org.apache.maven.plugins + maven-pmd-plugin + + true + true + + + + + check + + + + + + + ... + +``` + +This will run PMD automatically during the `verify` phase of the build. You can additionally run CPD, if +you add `cpd-check` as a goal. + + +### Customization + +#### Changing rulesets + +To specify a ruleset, simply edit the previous configuration: + + + + + + org.apache.maven.plugins + maven-pmd-plugin + + + /rulesets/java/braces.xml + /rulesets/java/naming.xml + d:\rulesets\strings.xml + http://localhost/design.xml + + + + + + +The value of the 'ruleset' value can either be a relative address, an absolute address or even an url. + +A clean strategy for customizing which rules to use for a project is to write a ruleset file. +In this file you can define which rules to use, add custom rules, and +customizing which rules to include/exclude from official rulesets. More information on +writing a ruleset can be found [here](pmd_userdocs_understanding_rulesets.html). +Note that if you include other rulesets in your own rulesets, you have to be sure that the plugin +will be able to resolve those other ruleset references. + +#### Other configurations + +The Maven PMD plugin allows you to configure CPD, targetJDK, and the use of XRef to link +the report to html source files, and the file encoding: + + + org.apache.maven.plugins + maven-pmd-plugin + + true + ISO-8859-1 + 30 + 1.4 + + + +### Reference + +For more information, please see the well documented PMD plugin project page here: +. +Also, the bug tracker for this plugin is [here](http://jira.codehaus.org/browse/MPMD). + + +## Maven 1 + +{% include warning.html content="Apache Maven 1.x has reached its end of life, and is no longer supported. For more information, see the [announcement](http://maven.apache.org/maven-1.x-eol.html). Users are encouraged to migrate to the current version of Apache Maven." %} + +This section is about the maven 1 PMD plugin. + +### Running the pmd plugin + +#### report + +To include the Maven report in the project reports section add the following line under +the reports element in your project.xml: + + maven-pmd-plugin + +This will add an entry to the 'project reports' section with the PMD report. + +##### manual + +To run PMD on a Maven project without adding it as a report, simply run + + maven pmd xdoc + +The PMD plugin writes the report in XML which will then be formatted into more readable HTML. + +#### Customization + +##### Changing rulesets + +To specify a set of official, built-in rulesets to be used set them in the property +maven.pmd.rulesets. You can include this setting in your project.properties file. + +A clean strategy for customizing which rules to use for a project is to write a ruleset file. +In this file you can define which rules to use, add custom rules, and +customizing which rules to include/exclude from official rulesets. More information on +writing a ruleset can be found [here](/pmd_userdocs_understanding_rulesets.html). + +Add to the root of your Maven project a pmd.xml file which contains the ruleset mentioned in +the previous paragraph. Add the following property to your project now: + + maven.pmd.rulesetfiles = ${basedir}/pmd.xml + +#### Reference + +See the PMD plugin project page here: + From f3a3af13332a8428ee16c22a330f060effb81fe3 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Aug 2017 19:55:16 +0200 Subject: [PATCH 14/33] [doc] Upgrade PMD version at runtime for Maven PMD Plugin Fixes #402 --- docs/pages/pmd/userdocs/tools/maven.md | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/pages/pmd/userdocs/tools/maven.md b/docs/pages/pmd/userdocs/tools/maven.md index f3e5eae8dc..2eb5e67bb9 100644 --- a/docs/pages/pmd/userdocs/tools/maven.md +++ b/docs/pages/pmd/userdocs/tools/maven.md @@ -124,6 +124,33 @@ the report to html source files, and the file encoding: +#### Upgrading the PMD version at runtime + +The Maven PMD plugin comes with a specific PMD version, which is documented on the +[plugin project page](https://maven.apache.org/plugins/maven-pmd-plugin/index.html). + +Given that the newer PMD version is compatible, you can override the PMD version, that the +Maven plugin will use and benefit from the latest bugfixes and enhancements: + +``` xml + + org.apache.maven.plugins + maven-pmd-plugin + + + net.sourceforge.pmd + pmd-core + ...choose your version... + + + net.sourceforge.pmd + pmd-java + ...choose your version... + + + +``` + ### Reference For more information, please see the well documented PMD plugin project page here: From 5957bc3db5ab219316d94ed0548c775f4564e3c8 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Aug 2017 20:37:35 +0200 Subject: [PATCH 15/33] [doc] Restored original author information --- docs/index.md | 1 + .../adding_metrics_support_to_language.md | 124 +++++++++--------- .../pmd/devdocs/adding_new_cpd_language.md | 3 +- docs/pages/pmd/devdocs/building.md | 3 +- docs/pages/pmd/devdocs/how_pmd_works.md | 3 +- docs/pages/pmd/devdocs/info_for_developers.md | 3 +- docs/pages/pmd/devdocs/making_rulesets.md | 3 +- docs/pages/pmd/devdocs/metrics_howto.md | 39 +++--- docs/pages/pmd/devdocs/releasing.md | 3 +- docs/pages/pmd/devdocs/roadmap.md | 5 +- docs/pages/pmd/devdocs/rule_guidelines.md | 3 +- docs/pages/pmd/devdocs/writing_pmd_rules.md | 3 +- docs/pages/pmd/devdocs/writing_xpath_rules.md | 3 +- docs/pages/pmd/languages/jsp.md | 3 +- docs/pages/pmd/userdocs/best_practices.md | 3 +- docs/pages/pmd/userdocs/ci.md | 3 +- docs/pages/pmd/userdocs/cpd.md | 3 +- docs/pages/pmd/userdocs/credits.md | 3 +- docs/pages/pmd/userdocs/getting_started.md | 3 +- docs/pages/pmd/userdocs/meaning.md | 3 +- docs/pages/pmd/userdocs/news.md | 3 +- docs/pages/pmd/userdocs/products.md | 3 +- docs/pages/pmd/userdocs/similarprojects.md | 3 +- docs/pages/pmd/userdocs/suppressing.md | 3 +- docs/pages/pmd/userdocs/tools.md | 3 +- docs/pages/pmd/userdocs/tools/ant.md | 4 + docs/pages/pmd/userdocs/tools/maven.md | 4 + 27 files changed, 113 insertions(+), 127 deletions(-) diff --git a/docs/index.md b/docs/index.md index d731612063..c79a409c72 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,6 +9,7 @@ summary: > It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code. last_updated: August 2017 +author: Jeff Jensen , Andreas Dangel --- {% include image.html file="pmd-logo-big.png" alt="PMD Logo" %} diff --git a/docs/pages/pmd/devdocs/adding_metrics_support_to_language.md b/docs/pages/pmd/devdocs/adding_metrics_support_to_language.md index 7773d1a1ee..2e14e78412 100644 --- a/docs/pages/pmd/devdocs/adding_metrics_support_to_language.md +++ b/docs/pages/pmd/devdocs/adding_metrics_support_to_language.md @@ -2,13 +2,12 @@ title: Adding support for metrics to a language short_title: Implement a metrics framework tags: [customizing] -summary: "PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers -to implement and use new code metrics very simply. Most of the functionality of this framework is abstracted in such +summary: "PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers +to implement and use new code metrics very simply. Most of the functionality of this framework is abstracted in such a way that any PMD supported language can implement such a framework without too much trouble. Here's how." last_updated: August 2017 -sidebar: pmd_sidebar permalink: pmd_devdocs_adding_metrics_support_to_language.html -folder: pmd/devdocs +author: Clément Fournier --- {% include warning.html content="WIP, unstable API" %} @@ -18,100 +17,100 @@ folder: pmd/devdocs ### Overview of the Java framework The framework has several subsystems, the two most easily identifiable being: -* A **project memoizer** (`ProjectMemoizer`). When a metric is computed, it's stored back in this structure and can be -reused later. This - reduces the overhead on the calculation of e.g. aggregate results (`ResultOption` calculations). The contents of - this data structure are indexed with fully qualified names (`JavaQualifiedName`), which must identify unambiguously +* A **project memoizer** (`ProjectMemoizer`). When a metric is computed, it's stored back in this structure and can be +reused later. This + reduces the overhead on the calculation of e.g. aggregate results (`ResultOption` calculations). The contents of + this data structure are indexed with fully qualified names (`JavaQualifiedName`), which must identify unambiguously classes and methods. -* The **façade**. The static end-user façade (`JavaMetrics`) is backed by an instance of a `JavaMetricsFaçade`. This - allows us to abstract the functionality of the façade into `pmd-core` for other frameworks to use. The façade - instance contains a project memoizer for the analysed project, and a metrics computer - (`JavaMetricsComputer`). It's this last object which really computes the metric and stores back its result in the +* The **façade**. The static end-user façade (`JavaMetrics`) is backed by an instance of a `JavaMetricsFaçade`. This + allows us to abstract the functionality of the façade into `pmd-core` for other frameworks to use. The façade + instance contains a project memoizer for the analysed project, and a metrics computer + (`JavaMetricsComputer`). It's this last object which really computes the metric and stores back its result in the project mirror, while the façade only handles parameters. -Metrics (`Metric`) plug in to this static system and only provide behaviour that's executed by the metrics computer. -Internally, metric keys (`MetricKey`) are parameterized with their version (`MetricVersion`) to index memoisation -maps (see `ParameterizedMetricKey`). This allows us to memoise several versions of the same metric without conflict. +Metrics (`Metric`) plug in to this static system and only provide behaviour that's executed by the metrics computer. +Internally, metric keys (`MetricKey`) are parameterized with their version (`MetricVersion`) to index memoisation +maps (see `ParameterizedMetricKey`). This allows us to memoise several versions of the same metric without conflict. {% include important.html content="The following will be moved when multifile analysis and metrics are separated" %} -At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize -metrics on a single file. Yet, one of the goals of the metrics framework is to allow for **multi-file analysis**, which -make it possible, for instance, to compute the coupling between two classes. This feature uses two major +At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize +metrics on a single file. Yet, one of the goals of the metrics framework is to allow for **multi-file analysis**, which +make it possible, for instance, to compute the coupling between two classes. This feature uses two major components: -* A **project mirror**. This data structure that stores info about all classes and operations (and other relevant +* A **project mirror**. This data structure that stores info about all classes and operations (and other relevant entities, such as fields, packages, etc.) of the analysed project. This is implemented by `PackageStats` in the Java framework. The role of this structure is to make info about other files available to rules. It's filled by a visitor before rules apply. - The information stored in this data structure that's accessible to metrics is mainly comprised of method and field - signatures (e.g. `JavaOperationSignature`), which describes concisely the characteristics of the method or field + The information stored in this data structure that's accessible to metrics is mainly comprised of method and field + signatures (e.g. `JavaOperationSignature`), which describes concisely the characteristics of the method or field (roughly, its modifiers). - -* Some kind of method and field **usage resolution**, i.e. some way to find the fully qualified name of a method from a + +* Some kind of method and field **usage resolution**, i.e. some way to find the fully qualified name of a method from a method call expression node. This is the trickiest part to implement. In Java it depends on type resolution. ### Abstraction layer -As you may have seen, most of the functionality of the first two components are abstracted into `pmd-core`. This -allows us to implement new metrics frameworks quite quickly. These abstract components are parameterized by the -node types of the class and operation AST nodes. Moreover, it makes the external behaviour of the framework is very +As you may have seen, most of the functionality of the first two components are abstracted into `pmd-core`. This +allows us to implement new metrics frameworks quite quickly. These abstract components are parameterized by the +node types of the class and operation AST nodes. Moreover, it makes the external behaviour of the framework is very stable across languages, yet each component can easily be customized by adding methods or overriding existing ones. -The signature matching aspect is framed by generic interfaces, but it can't really be abstracted more +The signature matching aspect is framed by generic interfaces, but it can't really be abstracted more than that. For instance, the project mirror is very language specific. Java's implementation uses the natural structure -provided by the language's package system to structure the project's content. Apex, on the other, has no package -system and thus can't use the same mechanism. That explains why the interfaces framing the project mirror are very +provided by the language's package system to structure the project's content. Apex, on the other, has no package +system and thus can't use the same mechanism. That explains why the interfaces framing the project mirror are very loose. Their main goal is to provide type safety through generics. - -Moreover, usage resolution depends on the availability of type resolution for the given language, which is only implemented in -Java. For these reasons, signature matching is considered an optional feature of the metrics framework. But despite -this limitation, signature matching still provides a elegant way to find information about the class we're in. This -feature requires no usage resolution and can be used to implement sophisticated metrics, that already give access to + +Moreover, usage resolution depends on the availability of type resolution for the given language, which is only implemented in +Java. For these reasons, signature matching is considered an optional feature of the metrics framework. But despite +this limitation, signature matching still provides a elegant way to find information about the class we're in. This +feature requires no usage resolution and can be used to implement sophisticated metrics, that already give access to detection strategies. ## Implementation of a new framework ### 1. Groundwork -* Create a class implementing `QualifiedName`. This implementation must be tailored to the target language so - that it can indentify unambiguously any class and operation in the analysed project. You +* Create a class implementing `QualifiedName`. This implementation must be tailored to the target language so + that it can indentify unambiguously any class and operation in the analysed project. You must implement `equals`, `hashCode` and `toString`. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaQualifiedName.java) -* Determine the AST nodes that correspond to class and method declaration in your language. These types are - referred hereafter as `T` and `O`, respectively. Both these types must implement the interface `QualifiableNode`, +* Determine the AST nodes that correspond to class and method declaration in your language. These types are + referred hereafter as `T` and `O`, respectively. Both these types must implement the interface `QualifiableNode`, which means they must expose a `getQualifiedName` method to give access to their qualified name. ### 2. Implement and wire the project memoizer * Create a class extending `BasicProjectMemoizer`. There's no abstract functionality to implement. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java) -* Create an AST visitor that fills the project memoizer with memoizers. For that, you use `BasicProjectMemoizer`'s - `addClassMemoizer` and `addOperationMemoizer` methods with a qualified name. +* Create an AST visitor that fills the project memoizer with memoizers. For that, you use `BasicProjectMemoizer`'s + `addClassMemoizer` and `addOperationMemoizer` methods with a qualified name. [Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsVisitor.java) -* Create a façade class for your visitor. This class extends a `*ParserVisitorAdapter` class and only overrides the - `initializeWith(Node)` method. It's supposed to make your real visitor accept the node in parameter. +* Create a façade class for your visitor. This class extends a `*ParserVisitorAdapter` class and only overrides the + `initializeWith(Node)` method. It's supposed to make your real visitor accept the node in parameter. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsVisitorFacade.java) -* Override the `getMetricsVisitorFacade()` method in your language's handler (e.g. `ApexHandler`). This method gives - back a `VisitorStarter` which initializes your façade with a `Node`. +* Override the `getMetricsVisitorFacade()` method in your language's handler (e.g. `ApexHandler`). This method gives + back a `VisitorStarter` which initializes your façade with a `Node`. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java#L100-L108) * Your project memoizer should now get filled when the `metrics` attribute is set to `true` in the rule XML. ### 3. Implement the façade -* Create a class extending `AbstractMetricsComputer`. This object will be responsible for calculating metrics - given a memoizer, a node and info about the metric. Typically, this object is stateless so you might as well make it +* Create a class extending `AbstractMetricsComputer`. This object will be responsible for calculating metrics + given a memoizer, a node and info about the metric. Typically, this object is stateless so you might as well make it a singleton. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java) -* Create a class extending `AbstractMetricsFacade`. This class needs a reference to your `ProjectMemoizer` and - your `MetricsComputer`. It backs the real end user façade, and handles user provided parameters before delegating to +* Create a class extending `AbstractMetricsFacade`. This class needs a reference to your `ProjectMemoizer` and + your `MetricsComputer`. It backs the real end user façade, and handles user provided parameters before delegating to your `MetricsComputer`. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java) -* Create the static façade of your framework. This one has an instance of your `MetricsFaçade` object and delegates +* Create the static façade of your framework. This one has an instance of your `MetricsFaçade` object and delegates static methods to that instance. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java) -* Create classes `AbstractOperationMetric` and `AbstractClassMetric`. These must implement `Metric` and - `Metric`, respectively. They typically provide defaults for the `supports` method of each metric. +* Create classes `AbstractOperationMetric` and `AbstractClassMetric`. These must implement `Metric` and + `Metric`, respectively. They typically provide defaults for the `supports` method of each metric. [Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java) * Create enums `ClassMetricKey` and `OperationMetricKey`. These must implement `MetricKey` and `MetricKey`. The enums list all available metric keys for your language. @@ -122,21 +121,20 @@ detection strategies. {% include important.html content="The following section will be moved when multifile analysis and metrics are separated" %} ### Optional: Signature matching - -You can match the signature of anything: method, field, class, package... It depends on what's useful for you. -Suppose you want to be able to match signatures for nodes of type `N`. What you have to do then is the following: - -* Create a class implementing the interface `Signature`. Signatures describe basic information about the node, -which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.). + +You can match the signature of anything: method, field, class, package... It depends on what's useful for you. +Suppose you want to be able to match signatures for nodes of type `N`. What you have to do then is the following: + +* Create a class implementing the interface `Signature`. Signatures describe basic information about the node, +which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.). It's up to you to define the right level of detail, depending on the accuracy of the pattern matching required. -* Make type `N` implement `SignedNode`. This makes the node capable of giving its signature. Factory methods to +* Make type `N` implement `SignedNode`. This makes the node capable of giving its signature. Factory methods to build a `Signature` from a `N` are a good idea. * Create signature masks. A mask is an object that matches some signatures based on their features. For example, with - the Java framework, you can build a `JavaOperationSigMask` that matches all method signatures with visibility + the Java framework, you can build a `JavaOperationSigMask` that matches all method signatures with visibility `public`. A sigmask implements `SigMask`, where `S` is the type of signature your mask handles. * Typically, the project mirror stores the signatures, so you have to implement it in a way that makes it possible to - associate a signature with the qualified name of its node. -* If you want to implement signature matching, create an `AbstractMetric` class, which gives access to a -`SignatureMatcher` to your metrics. Typically, your implementation of `ProjectMirror` implements a + associate a signature with the qualified name of its node. +* If you want to implement signature matching, create an `AbstractMetric` class, which gives access to a +`SignatureMatcher` to your metrics. Typically, your implementation of `ProjectMirror` implements a custom `SignatureMatcher` interface, and your façade can give back its instance of the project mirror. - diff --git a/docs/pages/pmd/devdocs/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/adding_new_cpd_language.md index ee89261caa..7286b5ce57 100644 --- a/docs/pages/pmd/devdocs/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/adding_new_cpd_language.md @@ -4,9 +4,8 @@ short_title: Add a New CPD Language tags: [customizing] summary: How to Add a New CPD Language last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_adding_new_cpd_language.html -folder: pmd/devdocs +author: Romain PELISSE --- # How to Add a New Language to CPD diff --git a/docs/pages/pmd/devdocs/building.md b/docs/pages/pmd/devdocs/building.md index 2e91e2837d..35b4e5e676 100644 --- a/docs/pages/pmd/devdocs/building.md +++ b/docs/pages/pmd/devdocs/building.md @@ -1,8 +1,7 @@ --- title: Building PMD from source -sidebar: pmd_sidebar permalink: pmd_devdocs_building.html -folder: pmd/devdocs +author: Tom Copeland, Xavier Le Vourch --- # Compiling PMD diff --git a/docs/pages/pmd/devdocs/how_pmd_works.md b/docs/pages/pmd/devdocs/how_pmd_works.md index c54c9e4c41..a0ea2ddb57 100644 --- a/docs/pages/pmd/devdocs/how_pmd_works.md +++ b/docs/pages/pmd/devdocs/how_pmd_works.md @@ -3,9 +3,8 @@ title: PMD How it Works tags: [customizing] summary: How PMD Works last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_how_pmd_works.html -folder: pmd/devdocs +author: Tom Copeland --- # How it works diff --git a/docs/pages/pmd/devdocs/info_for_developers.md b/docs/pages/pmd/devdocs/info_for_developers.md index 6911d0014b..425db6a2c4 100644 --- a/docs/pages/pmd/devdocs/info_for_developers.md +++ b/docs/pages/pmd/devdocs/info_for_developers.md @@ -4,9 +4,8 @@ short_title: Info for Developers tags: [customizing] summary: Info for PMD Developers last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_info_for_developers.html -folder: pmd/devdocs +author: Hooper Bloob , Romain Pelisse --- # Information for PMD Developers diff --git a/docs/pages/pmd/devdocs/making_rulesets.md b/docs/pages/pmd/devdocs/making_rulesets.md index 91b17daedc..8ee2c766d6 100644 --- a/docs/pages/pmd/devdocs/making_rulesets.md +++ b/docs/pages/pmd/devdocs/making_rulesets.md @@ -3,9 +3,8 @@ title: PMD Making Rulesets tags: [customizing] summary: Making Custom Rulesets for PMD last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_making_rulesets.html -folder: pmd/devdocs +author: Tom Copeland --- # How to make a new rule set diff --git a/docs/pages/pmd/devdocs/metrics_howto.md b/docs/pages/pmd/devdocs/metrics_howto.md index 71eedd01a4..f485110407 100644 --- a/docs/pages/pmd/devdocs/metrics_howto.md +++ b/docs/pages/pmd/devdocs/metrics_howto.md @@ -1,45 +1,44 @@ --- title: Using code metrics in custom rules tags: [customizing] -summary: "PMD was recently enhanced with the ability to compute code metrics on Java and Apex source (the so-called -Metrics Framework). This framework provides developers with a straightforward interface to use code metrics in their +summary: "PMD was recently enhanced with the ability to compute code metrics on Java and Apex source (the so-called +Metrics Framework). This framework provides developers with a straightforward interface to use code metrics in their rules, and to extend the framework with their own custom metrics." last_updated: July 20, 2017 -sidebar: pmd_sidebar permalink: pmd_devdocs_metrics_howto.html -folder: pmd/devdocs +author: Clément Fournier --- # Using code metrics in custom rules ## Using the metrics framework -{%include note.html content="Using the metrics framework is for now restricted to Java rules (with plans to support +{%include note.html content="Using the metrics framework is for now restricted to Java rules (with plans to support XPath rules later)." %} -To use the metrics framework in a custom rule, the first thing to do would be to enable metrics by adding the +To use the metrics framework in a custom rule, the first thing to do would be to enable metrics by adding the `metrics="true"` attribute to your rule's XML element. -{%include note.html content="The following explains how to use the Java metrics framework. The Apex framework +{%include note.html content="The following explains how to use the Java metrics framework. The Apex framework differs only by the name of its classes." %} -In PMD's Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces -a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and -method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric +In PMD's Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces +a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and +method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric object in the framework can only handle either types or operations, but not both. The framework provides a library of already implemented metrics. These metrics are referenced by `MetricKey` objects, which are listed in two public enums: `JavaClassMetricKey` and `JavaOperationMetricKey`. Metric keys wrap a metric, and -know which type of node their metric can be computed on. That way, you cannot compute an operation metric on a class -declaration node. Metrics that can be computed on operation and type declarations (e.g. NCSS) have one metric key in +know which type of node their metric can be computed on. That way, you cannot compute an operation metric on a class +declaration node. Metrics that can be computed on operation and type declarations (e.g. NCSS) have one metric key in each enum. - -The static façade class `JavaMetrics` is the only entry point to compute metrics in the Java framework. + +The static façade class `JavaMetrics` is the only entry point to compute metrics in the Java framework. This class provides the method `get` and its overloads. The following sections describes the interface of this class. ### Basic usage -The simplest overloads of `JavaMetrics.get` take two parameters: **a `MetricKey` and a node of the corresponding type.** -Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule's visitor, you +The simplest overloads of `JavaMetrics.get` take two parameters: **a `MetricKey` and a node of the corresponding type.** +Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule's visitor, you can get the value of Cyclo for a method node like so: ```java public Object visit(ASTMethodDeclaration node, Object data) { @@ -53,12 +52,12 @@ public Object visit(ASTMethodDeclaration node, Object data) { The same goes for class metrics: you select one among `JavaClassMetricKey`'s constants and pass it along with the node to `JavaMetrics.get`. - + ### Capability checking -Metrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on +Metrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on abstract methods. Metric keys provides a `supports(Node)` boolean method to find out if the metric can be computed on -the specified node. **If the metric cannot be computed on the given node, `JavaMetrics.get` will return `Double.NaN` .** +the specified node. **If the metric cannot be computed on the given node, `JavaMetrics.get` will return `Double.NaN` .** If you're concerned about that, you can condition your call on whether the node is supported or not: ```java public Object visit(ASTMethodDeclaration node, Object data) { @@ -74,7 +73,7 @@ public Object visit(ASTMethodDeclaration node, Object data) { ### Metric versions -{%include important.html content="Metric versions are about to be revamped into options that can be combined +{%include important.html content="Metric versions are about to be revamped into options that can be combined together." %} diff --git a/docs/pages/pmd/devdocs/releasing.md b/docs/pages/pmd/devdocs/releasing.md index ad14d84757..9f657f727a 100644 --- a/docs/pages/pmd/devdocs/releasing.md +++ b/docs/pages/pmd/devdocs/releasing.md @@ -1,8 +1,7 @@ --- title: Releasing -sidebar: pmd_sidebar permalink: pmd_devdocs_releasing.html -folder: pmd/devdocs +author: Romain Pelisse , Andreas Dangel --- This page describes the current status of the release process. diff --git a/docs/pages/pmd/devdocs/roadmap.md b/docs/pages/pmd/devdocs/roadmap.md index e963dd9069..ee08fcc41a 100644 --- a/docs/pages/pmd/devdocs/roadmap.md +++ b/docs/pages/pmd/devdocs/roadmap.md @@ -1,8 +1,9 @@ --- title: Roadmap -sidebar: pmd_sidebar permalink: pmd_devdocs_roadmap.html -folder: pmd/devdocs +author: > + Tom Copeland , Ryan Gustavson, Romain Pelisse , + Juan Martín Sotuyo Dodero , Andreas Dangel --- diff --git a/docs/pages/pmd/devdocs/rule_guidelines.md b/docs/pages/pmd/devdocs/rule_guidelines.md index 73b7bab593..c33f211477 100644 --- a/docs/pages/pmd/devdocs/rule_guidelines.md +++ b/docs/pages/pmd/devdocs/rule_guidelines.md @@ -3,9 +3,8 @@ title: PMD Rule Guidelines tags: [customizing] summary: Rule Guidelines last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_rule_guidelines.html -folder: pmd/devdocs +author: Xavier Le Vourch, Ryan Gustafson, Romain Pelisse --- # Rule Guidelines diff --git a/docs/pages/pmd/devdocs/writing_pmd_rules.md b/docs/pages/pmd/devdocs/writing_pmd_rules.md index cec80bd9b5..a6ec0ea893 100644 --- a/docs/pages/pmd/devdocs/writing_pmd_rules.md +++ b/docs/pages/pmd/devdocs/writing_pmd_rules.md @@ -3,9 +3,8 @@ title: PMD Writing a Custom Rule tags: [customizing] summary: Writing a Custom Rule for PMD last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_writing_pmd_rules.html -folder: pmd/devdocs +author: Tom Copeland --- # How to write a PMD rule diff --git a/docs/pages/pmd/devdocs/writing_xpath_rules.md b/docs/pages/pmd/devdocs/writing_xpath_rules.md index 29fabd43cb..20b6503598 100644 --- a/docs/pages/pmd/devdocs/writing_xpath_rules.md +++ b/docs/pages/pmd/devdocs/writing_xpath_rules.md @@ -3,9 +3,8 @@ title: PMD Writing XPath Rules tags: [customizing] summary: "Writing XPath rules for PMD" last_updated: July 3, 2016 -sidebar: pmd_sidebar permalink: pmd_devdocs_writing_xpath_rules.html -folder: pmd/devdocs +author: Miguel Griffa --- # XPath Rule tutorial diff --git a/docs/pages/pmd/languages/jsp.md b/docs/pages/pmd/languages/jsp.md index 6a1a589fed..771f7af06a 100644 --- a/docs/pages/pmd/languages/jsp.md +++ b/docs/pages/pmd/languages/jsp.md @@ -1,8 +1,7 @@ --- title: JSP Support -sidebar: pmd_sidebar permalink: pmd_languages_jsp.html -folder: pmd/languages +author: Pieter Vanraemdonck --- ## What is currently supported and what is not diff --git a/docs/pages/pmd/userdocs/best_practices.md b/docs/pages/pmd/userdocs/best_practices.md index 91d572688a..9f820769e8 100644 --- a/docs/pages/pmd/userdocs/best_practices.md +++ b/docs/pages/pmd/userdocs/best_practices.md @@ -1,8 +1,7 @@ --- title: Best Practices -sidebar: pmd_sidebar permalink: pmd_userdocs_best_practices.html -folder: pmd/userdocs +author: Tom Copeland --- ## Choose the rules that are right for you diff --git a/docs/pages/pmd/userdocs/ci.md b/docs/pages/pmd/userdocs/ci.md index 900ee29edc..c84cff056a 100644 --- a/docs/pages/pmd/userdocs/ci.md +++ b/docs/pages/pmd/userdocs/ci.md @@ -1,8 +1,7 @@ --- title: Continuous Integrations plugins -sidebar: pmd_sidebar permalink: pmd_userdocs_ci.html -folder: pmd/userdocs +author: Romain PELISSE --- ## Introduction diff --git a/docs/pages/pmd/userdocs/cpd.md b/docs/pages/pmd/userdocs/cpd.md index 53668d394b..e75b3e4272 100644 --- a/docs/pages/pmd/userdocs/cpd.md +++ b/docs/pages/pmd/userdocs/cpd.md @@ -1,9 +1,8 @@ --- title: Finding duplicated code summary: Or how to find copied and pasted code -sidebar: pmd_sidebar permalink: pmd_userdocs_cpd.html -folder: pmd/userdocs +author: Tom Copeland --- ## Overview diff --git a/docs/pages/pmd/userdocs/credits.md b/docs/pages/pmd/userdocs/credits.md index a3b79b056f..d53b833e7e 100644 --- a/docs/pages/pmd/userdocs/credits.md +++ b/docs/pages/pmd/userdocs/credits.md @@ -1,8 +1,7 @@ --- title: Credits -sidebar: pmd_sidebar permalink: pmd_userdocs_credits.html -folder: pmd/userdocs +author: Tom Copeland --- ## Committers diff --git a/docs/pages/pmd/userdocs/getting_started.md b/docs/pages/pmd/userdocs/getting_started.md index a291ccc68f..21398decad 100644 --- a/docs/pages/pmd/userdocs/getting_started.md +++ b/docs/pages/pmd/userdocs/getting_started.md @@ -1,8 +1,7 @@ --- title: Getting Started permalink: pmd_userdocs_getting_started.html -sidebar: pmd_sidebar -folder: pmd/userdocs +author: Tom Copeland , Xavier Le Vourch --- ## How to install PMD and CPD diff --git a/docs/pages/pmd/userdocs/meaning.md b/docs/pages/pmd/userdocs/meaning.md index ce73824c2e..b2bd1bc71f 100644 --- a/docs/pages/pmd/userdocs/meaning.md +++ b/docs/pages/pmd/userdocs/meaning.md @@ -1,8 +1,7 @@ --- title: What does 'PMD' mean? -sidebar: pmd_sidebar permalink: pmd_userdocs_meaning.html -folder: pmd/userdocs +author: David Dixon-Peugh --- We've been trying to find the meaning of the letters PMD - because frankly, we don't diff --git a/docs/pages/pmd/userdocs/news.md b/docs/pages/pmd/userdocs/news.md index 6bebfe38bb..937c1bbcf4 100644 --- a/docs/pages/pmd/userdocs/news.md +++ b/docs/pages/pmd/userdocs/news.md @@ -1,8 +1,7 @@ --- title: PMD in the press -sidebar: pmd_sidebar permalink: pmd_userdocs_news.html -folder: pmd/userdocs +author: Tom Copeland --- ## Sites/Articles about PMD diff --git a/docs/pages/pmd/userdocs/products.md b/docs/pages/pmd/userdocs/products.md index 702b10adc0..ffba09cb9f 100644 --- a/docs/pages/pmd/userdocs/products.md +++ b/docs/pages/pmd/userdocs/products.md @@ -1,8 +1,7 @@ --- title: Products/books related to PMD -sidebar: pmd_sidebar permalink: pmd_userdocs_products.html -folder: pmd/userdocs +author: Tom Copeland --- ## Open source products diff --git a/docs/pages/pmd/userdocs/similarprojects.md b/docs/pages/pmd/userdocs/similarprojects.md index 6553bf2eb0..60f574aaf3 100644 --- a/docs/pages/pmd/userdocs/similarprojects.md +++ b/docs/pages/pmd/userdocs/similarprojects.md @@ -1,8 +1,7 @@ --- title: Similar projects -sidebar: pmd_sidebar permalink: pmd_userdocs_similarprojects.html -folder: pmd/userdocs +author: Tom Copeland , David Dixon-Peugh --- ## Similar to PMD diff --git a/docs/pages/pmd/userdocs/suppressing.md b/docs/pages/pmd/userdocs/suppressing.md index b1c8f5c1be..d9de8589c7 100644 --- a/docs/pages/pmd/userdocs/suppressing.md +++ b/docs/pages/pmd/userdocs/suppressing.md @@ -1,8 +1,7 @@ --- title: Suppressing warnings -sidebar: pmd_sidebar permalink: pmd_userdocs_suppressing.html -folder: pmd/userdocs +author: Tom Copeland --- PMD provides several methods by which Rule violations can be suppressed. diff --git a/docs/pages/pmd/userdocs/tools.md b/docs/pages/pmd/userdocs/tools.md index ab2210e8a5..c76c5be90b 100644 --- a/docs/pages/pmd/userdocs/tools.md +++ b/docs/pages/pmd/userdocs/tools.md @@ -1,8 +1,7 @@ --- title: Tools / Integrations -sidebar: pmd_sidebar permalink: pmd_userdocs_tools.html -folder: pmd/userdocs +author: David Dixon-Peugh --- * IDE plugins diff --git a/docs/pages/pmd/userdocs/tools/ant.md b/docs/pages/pmd/userdocs/tools/ant.md index d3749454cc..eb2ff5f42e 100644 --- a/docs/pages/pmd/userdocs/tools/ant.md +++ b/docs/pages/pmd/userdocs/tools/ant.md @@ -1,6 +1,10 @@ --- title: Ant Task Usage permalink: pmd_userdocs_tools_ant.html +author: > + David Dixon-Peugh , + Tom Copeland , + Xavier Le Vourch --- ## PMD diff --git a/docs/pages/pmd/userdocs/tools/maven.md b/docs/pages/pmd/userdocs/tools/maven.md index 2eb5e67bb9..d95f6bc5b2 100644 --- a/docs/pages/pmd/userdocs/tools/maven.md +++ b/docs/pages/pmd/userdocs/tools/maven.md @@ -2,6 +2,10 @@ title: Maven PMD Plugin permalink: /pmd_userdocs_tools_maven.html last_updated: August 2017 +author: > + Miguel Griffa , + Romain PELISSE , + Andreas Dangel --- ## Maven 2 and 3 From e05940b24634fff2dbf376a898e4048cf2040f68 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 19 Aug 2017 10:40:33 +0200 Subject: [PATCH 16/33] [doc] Complete the maven PMD version upgrade example To be sure, that it works, all dependencies need to be referenced/overridden. Refs #402 --- docs/pages/pmd/userdocs/tools/maven.md | 56 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/docs/pages/pmd/userdocs/tools/maven.md b/docs/pages/pmd/userdocs/tools/maven.md index d95f6bc5b2..7171254c11 100644 --- a/docs/pages/pmd/userdocs/tools/maven.md +++ b/docs/pages/pmd/userdocs/tools/maven.md @@ -137,22 +137,46 @@ Given that the newer PMD version is compatible, you can override the PMD version Maven plugin will use and benefit from the latest bugfixes and enhancements: ``` xml - - org.apache.maven.plugins - maven-pmd-plugin - - - net.sourceforge.pmd - pmd-core - ...choose your version... - - - net.sourceforge.pmd - pmd-java - ...choose your version... - - - + + + ...choose your version... + +... + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.8 + + + net.sourceforge.pmd + pmd-core + ${pmdVersion} + + + net.sourceforge.pmd + pmd-java + ${pmdVersion} + + + net.sourceforge.pmd + pmd-javascript + ${pmdVersion} + + + net.sourceforge.pmd + pmd-jsp + ${pmdVersion} + + + + + + +... + ``` ### Reference From 47aa1435ad3345a87ad4156744ce7528171c22e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 20 Aug 2017 14:30:00 +0200 Subject: [PATCH 17/33] Consider ConcurrentModificationException in iterator loop --- .../migrating/ForLoopCanBeForeachRule.java | 58 ++++++++++++++++++- .../resources/rulesets/java/migrating.xml | 2 + .../migrating/xml/ForLoopCanBeForeach.xml | 39 +++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java index e83d5012ef..017ca45353 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.migrating; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -21,8 +22,10 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; +import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; import net.sourceforge.pmd.lang.symboltable.Scope; @@ -53,8 +56,13 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { List occurrences = indexDecl.getValue(); VariableNameDeclaration index = indexDecl.getKey(); - if ("Iterator".equals(index.getTypeImage()) && isReplaceableIteratorLoop(indexDecl, guardCondition, update)) { - addViolation(data, node); + if (TypeHelper.isA(index, Iterator.class)) { + Entry> iterableInfo = getIterableDeclOfIteratorLoop(index, node.getScope()); + + if (iterableInfo != null && isReplaceableIteratorLoop(indexDecl, guardCondition, iterableInfo, node)) { + addViolation(data, node); + } + return data; } @@ -224,6 +232,26 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { } + private Entry> getIterableDeclOfIteratorLoop(VariableNameDeclaration indexDecl, Scope scope) { + Node initializer = indexDecl.getNode().getFirstParentOfType(ASTVariableDeclarator.class) + .getFirstChildOfType(ASTVariableInitializer.class); + + if (initializer == null) { + return null; + } + + String name = initializer.getFirstDescendantOfType(ASTName.class) + .getImage(); + int dotIndex = name.indexOf('.'); + + if (dotIndex > 0) { + name = name.substring(0, dotIndex); + } + + return findDeclaration(name, scope); + } + + private boolean isReplaceableArrayLoop(ASTForStatement stmt, List occurrences, VariableNameDeclaration arrayDeclaration) { String arrayName = arrayDeclaration.getName(); @@ -321,7 +349,14 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { private boolean isReplaceableIteratorLoop(Entry> indexInfo, - ASTExpression guardCondition, ASTForUpdate update) { + ASTExpression guardCondition, + Entry> iterableInfo, + ASTForStatement stmt) { + + if (isIterableModifiedInsideLoop(iterableInfo, stmt)) { + return false; + } + String indexName = indexInfo.getKey().getName(); @@ -352,5 +387,22 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { return true; } + private boolean isIterableModifiedInsideLoop(Entry> iterableInfo, + ASTForStatement stmt) { + + String iterableName = iterableInfo.getKey().getName(); + for (NameOccurrence occ : iterableInfo.getValue()) { + ASTForStatement forParent = occ.getLocation().getFirstParentOfType(ASTForStatement.class); + if (forParent == stmt) { + String image = occ.getLocation().getImage(); + if (image.startsWith(iterableName + ".remove")) { + return true; + } + } + } + + return false; + } + } diff --git a/pmd-java/src/main/resources/rulesets/java/migrating.xml b/pmd-java/src/main/resources/rulesets/java/migrating.xml index cdaa5c26b0..672b92fb21 100644 --- a/pmd-java/src/main/resources/rulesets/java/migrating.xml +++ b/pmd-java/src/main/resources/rulesets/java/migrating.xml @@ -481,6 +481,8 @@ public class MyTest { language="java" since="6.0" message="This 'for' loop can be replaced by a 'foreach' loop" + typeResolution="true" + minimumLanguageVersion="1.5" class="net.sourceforge.pmd.lang.java.rule.migrating.ForLoopCanBeForeachRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_migrating.html#forloopcanbeforeach"> path = null; for (Iterator i = path.iterator(); i.hasNext();) { DataFlowNode inode = i.next(); if (inode.getVariableAccess() == null) { @@ -225,4 +226,42 @@ ]]>
      + + Consider iterators only if safe + 0 + path = null; + + for (Iterator i = path.iterator(); i.hasNext();) { + DataFlowNode inode = i.next(); + path.remove(inode); // throws ConcurrentModificationException if it were a foreach + if (inode.getVariableAccess() == null) { + continue; + } + } + } + } + ]]> + + + + Do not report iterator loop if we can't find iterator decl + 0 + i = path.iterator(); i.hasNext();) { + DataFlowNode inode = i.next(); + if (inode.getVariableAccess() == null) { + continue; + } + } + } + } + ]]> + + + From 7f87882a437c70b2c2813a364b7bacc09fa14a7e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 21 Aug 2017 22:33:20 +0200 Subject: [PATCH 18/33] [doc] Add first draft for pull request merge process refs #359 --- docs/pages/pmd/devdocs/pull_request_merge.md | 61 ++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 docs/pages/pmd/devdocs/pull_request_merge.md diff --git a/docs/pages/pmd/devdocs/pull_request_merge.md b/docs/pages/pmd/devdocs/pull_request_merge.md new file mode 100644 index 0000000000..ef04d3e6bd --- /dev/null +++ b/docs/pages/pmd/devdocs/pull_request_merge.md @@ -0,0 +1,61 @@ +--- +title: Pull-Request Merge +permalink: pmd_devdocs_pull_request_merge.html +last_updated: August 2017 +author: Andreas Dangel +--- + +## Example 1: Merging PR #123 into master + +1. Review + + * Compilation and checkstyle is checked already by travis build: PRs are automatically verified. + * If it is a bug fix, a new unit test, that reproduces the bug, is mandatory. + * Add the appropriate labels on the github issue: If the PR fixes a bug, the label "a:bug" should be used. + * Make sure, the PR is added to the appropriate milestone. + +2. The actual merge commands: + + We assume, that the PR has been created from the master branch. If this is not the case, + then we'll either need to rebase or ask for rebasing before merging. + + ``` + git checkout master && git pull origin master + git checkout -b pr-123 + git pull https://github.com/otheruser/pmd.git branchname + ``` + + Note: You can get the pull command from github. Use the "command line instructions" link. + +3. Update the [release notes](https://github.com/pmd/pmd/blob/master/docs/pages/release_notes.md): + + * Are there any API changes, that need to be documented? (Section "API Changes") + * Are there any significant changes to existing rules, that should be mentioned? + (Section "Modified Rules" / "New Rules" / "Removed Rules") + * If the PR fixes a bug, make sure, it is listed under the section "Fixed Issues". + * In any case, add the PR to the section "External Contributions" + * Commit this changes with the message: + + Update release notes, refs #123 + + Note: If the PR fixes a bug, verify, that we have a commit with the message + "Fixes #issue-number". If this doesn't exist, you can add it to the commit message when + updating the release notes: `Update release notes, refs #123, fixes #issue-number`. + +4. Just to be sure, run complete build: `./mvnw clean verify` + +5. Go back to master and merge this temporary branch and push: + + ``` + git checkout master + git merge --no-ff pr-123 + git push origin master + ``` + + Since the temporary branch is now not needed anymore, you can delete it: + `git branch -d pr-123`. + + +## Example 2: Merging PR #124 into a maintenance branch + +**TODO** From 4cf5be95cd9c15747088ff3aa5ea92381e0ff16f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 22 Aug 2017 20:45:47 +0200 Subject: [PATCH 19/33] [doc] Enhance pull request documentation, use existing page refs #359 --- docs/pages/pmd/devdocs/pull_request_merge.md | 61 ------------- docs/pages/pmd/devdocs/pull_requests.md | 90 +++++++++++++++++++- docs/pages/pmd/devdocs/releasing.md | 4 +- 3 files changed, 89 insertions(+), 66 deletions(-) delete mode 100644 docs/pages/pmd/devdocs/pull_request_merge.md diff --git a/docs/pages/pmd/devdocs/pull_request_merge.md b/docs/pages/pmd/devdocs/pull_request_merge.md deleted file mode 100644 index ef04d3e6bd..0000000000 --- a/docs/pages/pmd/devdocs/pull_request_merge.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Pull-Request Merge -permalink: pmd_devdocs_pull_request_merge.html -last_updated: August 2017 -author: Andreas Dangel ---- - -## Example 1: Merging PR #123 into master - -1. Review - - * Compilation and checkstyle is checked already by travis build: PRs are automatically verified. - * If it is a bug fix, a new unit test, that reproduces the bug, is mandatory. - * Add the appropriate labels on the github issue: If the PR fixes a bug, the label "a:bug" should be used. - * Make sure, the PR is added to the appropriate milestone. - -2. The actual merge commands: - - We assume, that the PR has been created from the master branch. If this is not the case, - then we'll either need to rebase or ask for rebasing before merging. - - ``` - git checkout master && git pull origin master - git checkout -b pr-123 - git pull https://github.com/otheruser/pmd.git branchname - ``` - - Note: You can get the pull command from github. Use the "command line instructions" link. - -3. Update the [release notes](https://github.com/pmd/pmd/blob/master/docs/pages/release_notes.md): - - * Are there any API changes, that need to be documented? (Section "API Changes") - * Are there any significant changes to existing rules, that should be mentioned? - (Section "Modified Rules" / "New Rules" / "Removed Rules") - * If the PR fixes a bug, make sure, it is listed under the section "Fixed Issues". - * In any case, add the PR to the section "External Contributions" - * Commit this changes with the message: - - Update release notes, refs #123 - - Note: If the PR fixes a bug, verify, that we have a commit with the message - "Fixes #issue-number". If this doesn't exist, you can add it to the commit message when - updating the release notes: `Update release notes, refs #123, fixes #issue-number`. - -4. Just to be sure, run complete build: `./mvnw clean verify` - -5. Go back to master and merge this temporary branch and push: - - ``` - git checkout master - git merge --no-ff pr-123 - git push origin master - ``` - - Since the temporary branch is now not needed anymore, you can delete it: - `git branch -d pr-123`. - - -## Example 2: Merging PR #124 into a maintenance branch - -**TODO** diff --git a/docs/pages/pmd/devdocs/pull_requests.md b/docs/pages/pmd/devdocs/pull_requests.md index 965a2b6267..e044de8d62 100644 --- a/docs/pages/pmd/devdocs/pull_requests.md +++ b/docs/pages/pmd/devdocs/pull_requests.md @@ -1,6 +1,90 @@ --- -title: Pull Requests -sidebar: pmd_sidebar +title: Pull-Request Merge permalink: pmd_devdocs_pull_requests.html -folder: pmd/devdocs +last_updated: August 2017 +author: Andreas Dangel --- + +## Contributing via pull requests + +**TODO:** basically what we have in . + + +## Merging pull requests + +### Example 1: Merging PR #123 into master + +1. Review the pull request + + * Compilation and checkstyle is verified already by travis build: PRs are automatically checked. + * If it is a bug fix, a new unit test, that reproduces the bug, is mandatory. Without such a test, we might accidentally reintroduce the bug again. + * Add the appropriate labels on the github issue: If the PR fixes a bug, the label "a:bug" should be used. + * Make sure, the PR is added to the appropriate milestone. If the PR fixes a bug, make sure, that the bug issue is added to the same milestone. + +2. The actual merge commands: + + We assume, that the PR has been created from the master branch. If this is not the case, + then we'll either need to rebase or ask for rebasing before merging. + + ``` + git checkout master && git pull origin master # make sure, you have the latest code + git checkout -b pr-123 # creates a new temporary branch + git pull https://github.com/otheruser/pmd.git branchname + ``` + + {% include note.html content="You can get the pull command from github. Use the \"command line instructions\" link." %} + +3. Update the [release notes](https://github.com/pmd/pmd/blob/master/docs/pages/release_notes.md): + + * Are there any API changes, that need to be documented? (Section "API Changes") + * Are there any significant changes to existing rules, that should be mentioned? + (Section "Modified Rules" / "New Rules" / "Removed Rules") + * If the PR fixes a bug, make sure, it is listed under the section "Fixed Issues". + * In any case, add the PR to the section "External Contributions" + * Commit these changes with the message: + + git add docs/pages/release_notes.md + git commit -m "Update release notes, refs #123" + + {% include note.html content="If the PR fixes a bug, verify, that we have a commit with the message + \"Fixes #issue-number\". If this doesn't exist, you can add it to the commit message when + updating the release notes: `Update release notes, refs #123, fixes #issue-number`. + This will automatically close the github issue." %} + +4. Just to be sure, run complete build: `./mvnw clean verify` + + {% include note.html content="This will execute all the unit tests and the checkstyle tests. It ensures, + that the complete project can be build and is functioning on top of the current master." %} + +5. If the build finished successful, switch back to the master branch and merge this temporary branch and push: + + ``` + git checkout master + git merge --no-ff pr-123 + git push origin master + ``` + + Since the temporary branch is now not needed anymore, you can delete it: + `git branch -d pr-123`. + + +### Example 2: Merging PR #124 into a maintenance branch + +We ask, to create every pull request against master, to make it easier to contribute. +But if a pull request is intended to fix a bug in an older version of PMD, then we need to backport this pull request. + +For older versions, we have maintenance branches, like `pmd/5.8.x`. + +**TODO:** + +* create maintenance branch, if needed +* create temp branch, pull in pr, git rebase master --onto pmd/5.8.x +* continue with step 3 above (update release notes) +* merge the maintenance branch into the next higher branch and eventually into master + +Note: not using cherry-picking, so that each fix is represented by a single commit. Cherry-picking would +duplicate the commit and you can't see in the log, on which branches the fix has been made +(e.g. gitk and github show the branches, on which the specific commit is contained). +The downside is a more complex history - the maintenance branches and master branch are "connected" and not separate. + +Note: merging maintenance branches after a release will produce merge conflicts in `pom.xml` files. diff --git a/docs/pages/pmd/devdocs/releasing.md b/docs/pages/pmd/devdocs/releasing.md index 9f657f727a..cf911cc79d 100644 --- a/docs/pages/pmd/devdocs/releasing.md +++ b/docs/pages/pmd/devdocs/releasing.md @@ -171,7 +171,7 @@ Maybe there are some milestones on sourceforge, too: and on sourceforge. From c675004a7d7eba412b6e66d4c2ac72bb8b7ba546 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 23 Aug 2017 21:08:58 +0200 Subject: [PATCH 20/33] [doc] Fixes from PR #568 --- docs/index.md | 2 ++ docs/pages/pmd/devdocs/pull_requests.md | 24 ++++++++++++------- .../pmd/devdocs/writing_documentation.md | 6 +++-- docs/pages/pmd/userdocs/tools/maven.md | 20 ++++++++-------- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/docs/index.md b/docs/index.md index c79a409c72..9590048f8e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,6 +14,8 @@ author: Jeff Jensen , Andreas Dangel + **PMD** scans source code in Java and other languages and looks for potential problems like: * Possible bugs - empty try/catch/finally/switch statements diff --git a/docs/pages/pmd/devdocs/pull_requests.md b/docs/pages/pmd/devdocs/pull_requests.md index e044de8d62..070232edfd 100644 --- a/docs/pages/pmd/devdocs/pull_requests.md +++ b/docs/pages/pmd/devdocs/pull_requests.md @@ -27,9 +27,8 @@ author: Andreas Dangel then we'll either need to rebase or ask for rebasing before merging. ``` - git checkout master && git pull origin master # make sure, you have the latest code - git checkout -b pr-123 # creates a new temporary branch - git pull https://github.com/otheruser/pmd.git branchname + git checkout master && git pull origin master # make sure, you have the latest code + git fetch origin pull/123/head:pr-123 && git checkout pr-123 # creates a new temporary branch ``` {% include note.html content="You can get the pull command from github. Use the \"command line instructions\" link." %} @@ -51,16 +50,23 @@ author: Andreas Dangel updating the release notes: `Update release notes, refs #123, fixes #issue-number`. This will automatically close the github issue." %} -4. Just to be sure, run complete build: `./mvnw clean verify` - - {% include note.html content="This will execute all the unit tests and the checkstyle tests. It ensures, - that the complete project can be build and is functioning on top of the current master." %} - -5. If the build finished successful, switch back to the master branch and merge this temporary branch and push: +4. Now merge the pull request into the master branch: ``` git checkout master git merge --no-ff pr-123 + ``` + + {%include note.html content="If there are merge conflicts, you'll need to deal with them here." %} + +5. Run the complete build: `./mvnw clean verify` + + {% include note.html content="This will execute all the unit tests and the checkstyle tests. It ensures, + that the complete project can be build and is functioning on top of the current master." %} + +6. If the build was successful, you are ready to push: + + ``` git push origin master ``` diff --git a/docs/pages/pmd/devdocs/writing_documentation.md b/docs/pages/pmd/devdocs/writing_documentation.md index d04e991bf1..e354471733 100644 --- a/docs/pages/pmd/devdocs/writing_documentation.md +++ b/docs/pages/pmd/devdocs/writing_documentation.md @@ -54,6 +54,8 @@ Just go to http://localhost:4005. If a page is modified, the documentation will automatically be rendered again and all you need to do, is refreshing the page in your browser. +See also the script [pmd-jekyll.sh](https://gist.github.com/oowekyala/ee6f8801138861072c59ce683bdf737b). +It starts the jekyll server in the background and doesn't block the current shell. ## The sidebar @@ -99,7 +101,7 @@ See [Alerts](http://idratherbewriting.com/documentation-theme-jekyll/mydoc_alert For example, a info-box can be created like this: - {% include note.html content="This is a note." %} + {%raw%}{% include note.html content="This is a note." %}{%endraw%} It renders as: @@ -115,7 +117,7 @@ Other available types are: A callout is created like this: - {% include callout.html content="This is a callout of type default.

      There are the following types available: danger, default, primary, success, info, and warning." type="default" %} + {%raw%}{% include callout.html content="This is a callout of type default.

      There are the following types available: danger, default, primary, success, info, and warning." type="default" %}{%endraw%} It renders as: diff --git a/docs/pages/pmd/userdocs/tools/maven.md b/docs/pages/pmd/userdocs/tools/maven.md index 7171254c11..06057b1b2d 100644 --- a/docs/pages/pmd/userdocs/tools/maven.md +++ b/docs/pages/pmd/userdocs/tools/maven.md @@ -12,9 +12,9 @@ author: > ### Running the pmd plugin -#### report +#### Generating a project report -To include the mvn report in the project reports section add the following lines under +To include the PMD report in the project reports section add the following lines under the reports element in your pom.xml: ``` xml @@ -35,7 +35,7 @@ the reports element in your pom.xml: This will add an entry to the 'project reports' section with the PMD report when you build the maven site. -#### manual +#### Executing PMD manually To run PMD on a Maven project without adding it as a report, simply run @@ -103,7 +103,7 @@ To specify a ruleset, simply edit the previous configuration: -The value of the 'ruleset' value can either be a relative address, an absolute address or even an url. +The value of the 'ruleset' element can either be a relative address, an absolute address or even an url. A clean strategy for customizing which rules to use for a project is to write a ruleset file. In this file you can define which rules to use, add custom rules, and @@ -194,16 +194,16 @@ This section is about the maven 1 PMD plugin. ### Running the pmd plugin -#### report +#### Generating a project report -To include the Maven report in the project reports section add the following line under +To include the PMD report in the project reports section add the following line under the reports element in your project.xml: maven-pmd-plugin This will add an entry to the 'project reports' section with the PMD report. -##### manual +#### Executing PMD manually To run PMD on a Maven project without adding it as a report, simply run @@ -211,9 +211,9 @@ To run PMD on a Maven project without adding it as a report, simply run The PMD plugin writes the report in XML which will then be formatted into more readable HTML. -#### Customization +### Customization -##### Changing rulesets +#### Changing rulesets To specify a set of official, built-in rulesets to be used set them in the property maven.pmd.rulesets. You can include this setting in your project.properties file. @@ -228,7 +228,7 @@ the previous paragraph. Add the following property to your project now: maven.pmd.rulesetfiles = ${basedir}/pmd.xml -#### Reference +### Reference See the PMD plugin project page here: From ef90a6ed4ceb3127ae66c00c06d779ed59a9c3f0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Aug 2017 21:35:08 +0200 Subject: [PATCH 21/33] [doc] Finish pull request documentation refs #359 --- docs/pages/pmd/devdocs/pull_requests.md | 105 ++++++++++++++++++++---- 1 file changed, 91 insertions(+), 14 deletions(-) diff --git a/docs/pages/pmd/devdocs/pull_requests.md b/docs/pages/pmd/devdocs/pull_requests.md index 070232edfd..3580a8d757 100644 --- a/docs/pages/pmd/devdocs/pull_requests.md +++ b/docs/pages/pmd/devdocs/pull_requests.md @@ -7,8 +7,17 @@ author: Andreas Dangel ## Contributing via pull requests -**TODO:** basically what we have in . +First off, thanks for taking the time to contribute! +* Please create your pull request against the `master` branch. We will rebase/merge it to the maintenance + branches, if necessary. Just fork the [pmd repo](https://github.com/pmd/pmd/) and + create a [pull request](https://github.com/pmd/pmd/pulls). + +* We are using [checkstyle](http://checkstyle.sourceforge.net/) to enforce a common code style. + The check is integrated into the default build - so, make sure, you can [build PMD](pmd_devdocs_building.html) + without errors. + + See [code style](pmd_devdocs_codestyle.html) for more info. ## Merging pull requests @@ -31,8 +40,6 @@ author: Andreas Dangel git fetch origin pull/123/head:pr-123 && git checkout pr-123 # creates a new temporary branch ``` - {% include note.html content="You can get the pull command from github. Use the \"command line instructions\" link." %} - 3. Update the [release notes](https://github.com/pmd/pmd/blob/master/docs/pages/release_notes.md): * Are there any API changes, that need to be documented? (Section "API Changes") @@ -79,18 +86,88 @@ author: Andreas Dangel We ask, to create every pull request against master, to make it easier to contribute. But if a pull request is intended to fix a bug in an older version of PMD, then we need to backport this pull request. -For older versions, we have maintenance branches, like `pmd/5.8.x`. +#### Creating a maintenance branch -**TODO:** +For older versions, we use maintenance branches, like `pmd/5.8.x`. If there is no maintenance branch for +the specific version, then we'll have to create it first. Let's say, we want a maintenance branch for +PMD version 5.8.0, so that we can create a bugfix release 5.8.1. -* create maintenance branch, if needed -* create temp branch, pull in pr, git rebase master --onto pmd/5.8.x -* continue with step 3 above (update release notes) -* merge the maintenance branch into the next higher branch and eventually into master +1. We'll simply create a new branch off of the release tag: + + ``` + git branch pmd/5.8.x pmd_releases/5.8.0 && git checkout pmd/5.8.x + ``` + +2. Now we'll need to adjust the version, since it's currently the same as the release version. + We'll change the version to the next patch version: "5.8.1-SNAPSHOT". + + ``` + ./mvnw versions:set -DnewVersion=5.8.1-SNAPSHOT + git add pom.xml \*/pom.xml + git commit -m "prepare next version 5.8.1-SNAPSHOT" + ``` + +#### Merging the PR + +1. As above: Review the PR + +2. Fetch the PR and rebase it onto the maintenance branch: + + ``` + git fetch origin pull/124/head:pr-124 && git checkout pr-124 # creates a new temporary branch + git rebase master --onto pmd/5.8.x + ./mvnw clean verify # make sure, everything works after the rebase + ``` + + {%include note.html content="You might need to fix conflicts / backport the commits for the older + PMD version." %} + +3. Update the release notes. See above for details. + +4. Now merge the pull request into the maintenance branch: + + ``` + git checkout pmd/5.8.x + git merge --no-ff pr-124 + ``` + +5. Just to be sure, run the complete build again: `./mvnw clean verify`. + +6. If the build was successful, you are ready to push: + + ``` + git push origin pmd/5.8.x + ``` + +7. Since we have rebased the pull request, it won't appear as merged on github. + You need to manually close the pull request. Leave a comment, that it has been + rebased onto the maintenance branch. + +#### Merging into master + +Now the PR has been merged into the maintenance branch, but it is missing in any later version of PMD. +Therefore, we merge first into the next minor version maintenance branch (if existing): + + git checkout pmd/5.9.x + git merge pmd/5.8.x + +After that, we merge the changes into the master branch: + + git checkout master + git merge pmd/5.9.x + +{%include note.html content="This ensures, that every change on the maintenance branch eventually ends +up in the master branch and therefore in any future version of PMD.
      +The downside is however, that there are inevitable merge conflicts for the maven `pom.xml` files, since +every branch changed the version number differently.
      +We could avoid this by merging only the temporary branch \"pr-124\" into each maintenance branch and +eventually into master, with the risk of missing single commits in a maintenance branch, that have been +done outside the temporary branch." %} + +#### Merging vs. Cherry-Picking + +We are not using cherry-picking, so that each fix is represented by a single commit. +Cherry-picking would duplicate the commit and you can't see in the log, on which branches the fix has been +integrated (e.g. gitk and github show the branches, from which the specific commit is reachable). -Note: not using cherry-picking, so that each fix is represented by a single commit. Cherry-picking would -duplicate the commit and you can't see in the log, on which branches the fix has been made -(e.g. gitk and github show the branches, on which the specific commit is contained). The downside is a more complex history - the maintenance branches and master branch are "connected" and not separate. - -Note: merging maintenance branches after a release will produce merge conflicts in `pom.xml` files. From b7f3032070b813433eb7fae2bf4d3c9988e7e411 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 5 Sep 2017 17:05:03 +0200 Subject: [PATCH 22/33] [doc] Update gems --- docs/Gemfile.lock | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 667a6876bd..994b58d435 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -6,8 +6,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.5.1) - public_suffix (~> 2.0, >= 2.0.2) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) coffee-script (2.4.1) coffee-script-source execjs @@ -16,21 +16,21 @@ GEM ethon (0.10.1) ffi (>= 1.3.0) execjs (2.7.0) - faraday (0.13.0) + faraday (0.13.1) multipart-post (>= 1.2, < 3) ffi (1.9.18) forwardable-extended (2.6.0) gemoji (3.0.0) - github-pages (151) + github-pages (158) activesupport (= 4.2.8) github-pages-health-check (= 1.3.5) - jekyll (= 3.5.1) + jekyll (= 3.5.2) jekyll-avatar (= 0.4.2) jekyll-coffeescript (= 1.0.1) jekyll-default-layout (= 0.1.4) jekyll-feed (= 0.9.2) jekyll-gist (= 1.4.1) - jekyll-github-metadata (= 2.6.0) + jekyll-github-metadata (= 2.9.1) jekyll-mentions (= 1.2.0) jekyll-optional-front-matter (= 0.2.0) jekyll-paginate (= 1.1.0) @@ -38,7 +38,7 @@ GEM jekyll-redirect-from (= 0.12.1) jekyll-relative-links (= 0.4.1) jekyll-sass-converter (= 1.5.0) - jekyll-seo-tag (= 2.2.3) + jekyll-seo-tag (= 2.3.0) jekyll-sitemap (= 1.0.0) jekyll-swiss (= 0.4.0) jekyll-theme-architect (= 0.1.0) @@ -50,7 +50,7 @@ GEM jekyll-theme-midnight (= 0.1.0) jekyll-theme-minimal (= 0.1.0) jekyll-theme-modernist (= 0.1.0) - jekyll-theme-primer (= 0.4.0) + jekyll-theme-primer (= 0.5.2) jekyll-theme-slate (= 0.1.0) jekyll-theme-tactile (= 0.1.0) jekyll-theme-time-machine (= 0.1.0) @@ -69,11 +69,11 @@ GEM octokit (~> 4.0) public_suffix (~> 2.0) typhoeus (~> 0.7) - html-pipeline (2.6.0) + html-pipeline (2.7.0) activesupport (>= 2) nokogiri (>= 1.4) i18n (0.8.6) - jekyll (3.5.1) + jekyll (3.5.2) addressable (~> 2.4) colorator (~> 1.0) jekyll-sass-converter (~> 1.0) @@ -94,7 +94,7 @@ GEM jekyll (~> 3.3) jekyll-gist (1.4.1) octokit (~> 4.2) - jekyll-github-metadata (2.6.0) + jekyll-github-metadata (2.9.1) jekyll (~> 3.1) octokit (~> 4.0, != 4.4.0) jekyll-mentions (1.2.0) @@ -112,7 +112,7 @@ GEM jekyll (~> 3.3) jekyll-sass-converter (1.5.0) sass (~> 3.4) - jekyll-seo-tag (2.2.3) + jekyll-seo-tag (2.3.0) jekyll (~> 3.3) jekyll-sitemap (1.0.0) jekyll (~> 3.3) @@ -144,8 +144,9 @@ GEM jekyll-theme-modernist (0.1.0) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-primer (0.4.0) + jekyll-theme-primer (0.5.2) jekyll (~> 3.5) + jekyll-github-metadata (~> 2.9) jekyll-seo-tag (~> 2.2) jekyll-theme-slate (0.1.0) jekyll (~> 3.5) @@ -214,4 +215,4 @@ DEPENDENCIES jekyll BUNDLED WITH - 1.13.6 + 1.15.1 From f4fa09bfdc3a5c8eff3084e6b5b4fec982218e53 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 5 Sep 2017 17:05:28 +0200 Subject: [PATCH 23/33] [doc] XPath rule: Add missing ruleset example --- .../pmd/devdocs/writing_documentation.md | 1 + docs/pages/pmd/devdocs/writing_xpath_rules.md | 48 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/writing_documentation.md b/docs/pages/pmd/devdocs/writing_documentation.md index e354471733..078477f278 100644 --- a/docs/pages/pmd/devdocs/writing_documentation.md +++ b/docs/pages/pmd/devdocs/writing_documentation.md @@ -3,6 +3,7 @@ title: Writing Documentation last_update: August 2017 permalink: pmd_devdocs_writing_documentation.html keywords: documentation, jekyll, markdown +author: Andreas Dangel --- PMD's documentation uses [Jekyll](https://jekyllrb.com/) with diff --git a/docs/pages/pmd/devdocs/writing_xpath_rules.md b/docs/pages/pmd/devdocs/writing_xpath_rules.md index 20b6503598..ccbc1982c1 100644 --- a/docs/pages/pmd/devdocs/writing_xpath_rules.md +++ b/docs/pages/pmd/devdocs/writing_xpath_rules.md @@ -1,5 +1,5 @@ --- -title: PMD Writing XPath Rules +title: Writing XPath Rules tags: [customizing] summary: "Writing XPath rules for PMD" last_updated: July 3, 2016 @@ -150,4 +150,50 @@ The following expression does the magic we need: We recommend at this point that you experiment with Designer putting the final modifier to the Factory and verifying that the results produced are those expected. +## Creating a new rule definition + +To actually use your new XPath rule, it needs to be in a ruleset. You can create a new custom ruleset which just +contains your new XPath rule. You can use the following template. Just make sure, to replace the `xpath` property, +the example code and give your rule a useful name and message. + +``` xml + + + + +Custom rules + + + + +Rule Description + + 3 + + + + + + + + + + +``` + + + Finally, for many more details on writing XPath rules, pick up [PMD Applied](http://pmdapplied.com/)! From b37210d8da828040e8a97c6f29fb95ba9c147eba Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 5 Sep 2017 17:28:42 +0200 Subject: [PATCH 24/33] [doc] Add "Understanding Rulesets" --- docs/pages/pmd/userdocs/best_practices.md | 8 +-- .../pmd/userdocs/understanding_rulesets.md | 68 +++++++++++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/docs/pages/pmd/userdocs/best_practices.md b/docs/pages/pmd/userdocs/best_practices.md index 9f820769e8..6e59d9391a 100644 --- a/docs/pages/pmd/userdocs/best_practices.md +++ b/docs/pages/pmd/userdocs/best_practices.md @@ -10,10 +10,10 @@ Running every ruleset will result in a huge number of rule violations, most of w Having to sort through a thousand line report to find the few you're really interested in takes all the fun out of things. -Instead, start with some of the obvious rulesets - just run [unusedcode](/pmd_rules_java.html#Unused_Code) and fix any unused locals and fields. -Then, run [empty](/pmd_rules_java.html#Empty_Code) and fix all the empty `if` statements and such-like. After that, take [unnecessary](/pmd_rules_java.html#Unnecessary) -and fix these violations. Then, run [basic](/pmd_rules_java.html#Basic) and fix the remaining violations. -Then peruse the [design](/pmd_rules_java.html#Design) and [controversial](/pmd_rules_java.html#Controversial) rulesets and use the ones +Instead, start with some of the obvious rulesets - just run [unusedcode](/pmd_rules_java.html#unused-code) and fix any unused locals and fields. +Then, run [empty](/pmd_rules_java.html#empty-code) and fix all the empty `if` statements and such-like. After that, take [unnecessary](/pmd_rules_java.html#unnecessary) +and fix these violations. Then, run [basic](/pmd_rules_java.html#basic) and fix the remaining violations. +Then peruse the [design](/pmd_rules_java.html#design) and [controversial](/pmd_rules_java.html#controversial) rulesets and use the ones you like [via a custom ruleset](/pmd_userdocs_understanding_rulesets.html). ## PMD rules are not set in stone diff --git a/docs/pages/pmd/userdocs/understanding_rulesets.md b/docs/pages/pmd/userdocs/understanding_rulesets.md index 98df3eddb8..8ba28d1a4b 100644 --- a/docs/pages/pmd/userdocs/understanding_rulesets.md +++ b/docs/pages/pmd/userdocs/understanding_rulesets.md @@ -1,9 +1,69 @@ --- title: Understanding Rulesets -sidebar: pmd_sidebar permalink: pmd_userdocs_understanding_rulesets.html -folder: pmd/userdocs +summary: Rulesets are collections of rules +last_updated: August 2017 --- -* Selecting the rules that should be executed -* adjusting rule properties +There are two major use cases: + +1. When defining a new rule, the rule needs to be defined in a ruleset. PMD's built-in rules + are defined in specific rulesets from which the rule reference documentation is generated, + see [Java Rules](pmd_rules_java.html) for an example. + + Similar rules are grouped together into the same ruleset, like the [Java Braces Ruleset](pmd_rules_java_braces.html) + which contains rules that all deal with missing braces. + +2. When executing PMD you need to tell, which rules should be executed. You could directly point to the + built-in rulesets, but then you might be overwhelmed by the found violations. As described + in [Best Practices](pmd_userdocs_best_practices.html), it's better to define an own custom ruleset. + + With an own custom ruleset, you can: + + * Select the rules, that should be executed + * Adjust the rule properties to exactly meet your needs + +## Create a custom ruleset + +You start by creating a new XML file with the following contents: + +``` xml + + + + +Custom rules + + + +``` + +Now start to add rule by **referencing** them. Let's say, you want to start with finding +[Empty Catch Blocks](pmd_rules_java_empty.html#emptycatchblock). Then you'd add the following +rule reference inside the `ruleset` elements: + +```xml + +``` + +## Adjusting rule properties + +If you want to be less strict with empty catch blocks, you could define that an exception variable name +of `ignored` will not raise a violation. Therefore you would reference the rule **and** define +the appropriate property value: + +```xml + + + + ^ignored$ + + + +``` + + +{% include note.html content="More information about rulesets can be found on [Making Rulesets](pmd_devdocs_making_rulesets.html)." %} From 7120369c12b48d44c23c0a51c17b66dacdafd1fc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 5 Sep 2017 17:37:31 +0200 Subject: [PATCH 25/33] [doc] document for each rule a sample how to reference it --- .../pmd/docs/RuleDocGenerator.java | 11 ++++++-- pmd-doc/src/test/resources/expected/sample.md | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 9a2e66551b..bde314c9cc 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -239,15 +239,16 @@ public class RuleDocGenerator { for (Map.Entry> entry : rulesets.entrySet()) { String languageTersename = entry.getKey().getTerseName(); for (RuleSet ruleset : entry.getValue()) { + String rulesetFilename = getRuleSetFilename(ruleset); String filename = RULESET_INDEX_FILENAME_PATTERN .replace("${language.tersename}", languageTersename) - .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + .replace("${ruleset.name}", rulesetFilename); Path path = getAbsoluteOutputPath(filename); String permalink = RULESET_INDEX_PERMALINK_PATTERN .replace("${language.tersename}", languageTersename) - .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + .replace("${ruleset.name}", rulesetFilename); List lines = new LinkedList<>(); lines.add("---"); @@ -350,6 +351,12 @@ public class RuleDocGenerator { } lines.add(""); } + + lines.add("**Use this rule by referencing it:**"); + lines.add("``` xml"); + lines.add(""); + lines.add("```"); + lines.add(""); } writer.write(path, lines); diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index 66f2db4ada..c1119aab3e 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -21,6 +21,11 @@ Just some description of a deprecated rule. //ForStatement ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JumbledIncrementer **Since:** PMD 1.0 @@ -58,6 +63,11 @@ public class JumbledIncrementerRule1 { |----|-------------|-----------| |sampleAdditionalProperty|the value|This is a additional property for tests| +**Use this rule by referencing it:** +``` xml + +``` + ## MovedRule Deprecated @@ -93,6 +103,11 @@ public class JumbledIncrementerRule1 { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## OverrideBothEqualsAndHashcode **Since:** PMD 0.4 @@ -132,6 +147,11 @@ public class Foo { // perfect, both methods provided } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## RenamedRule Deprecated @@ -172,3 +192,8 @@ public class JumbledIncrementerRule1 { |Name|Default Value|Description| |----|-------------|-----------| |sampleAdditionalProperty|the value|This is a additional property for tests| + +**Use this rule by referencing it:** +``` xml + +``` From 57cfbb08cc86092e923495569fc50ae9671543a4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 5 Sep 2017 17:44:22 +0200 Subject: [PATCH 26/33] [doc] fix typos --- docs/index.md | 2 +- docs/pages/pmd/userdocs/understanding_rulesets.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 9590048f8e..2f63d0f86d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,7 +23,7 @@ author: Jeff Jensen , Andreas Dangel Date: Mon, 14 Aug 2017 00:18:34 +0200 Subject: [PATCH 27/33] Fix #388 --- .../resources/rulesets/java/controversial.xml | 2 +- .../xml/AvoidLiteralsInIfCondition.xml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/rulesets/java/controversial.xml b/pmd-java/src/main/resources/rulesets/java/controversial.xml index 779217c9f0..5c59d8f486 100644 --- a/pmd-java/src/main/resources/rulesets/java/controversial.xml +++ b/pmd-java/src/main/resources/rulesets/java/controversial.xml @@ -681,7 +681,7 @@ More exceptions can be defined with the property "ignoreMagicNumbers". //IfStatement/Expression/*/PrimaryExpression/PrimaryPrefix/Literal [not(NullLiteral)] [not(BooleanLiteral)] -[empty(index-of(tokenize($ignoreMagicNumbers, ','), @Image))] +[empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))] ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/controversial/xml/AvoidLiteralsInIfCondition.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/controversial/xml/AvoidLiteralsInIfCondition.xml index 57a5ab6798..9da329bc6d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/controversial/xml/AvoidLiteralsInIfCondition.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/controversial/xml/AvoidLiteralsInIfCondition.xml @@ -74,4 +74,19 @@ public class Foo { } ]]>
      + + #388 False positive due to space in property list + 0 + + + + From 4672249157f6053fb80706e1bd607f4dae6b9faf Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 9 Sep 2017 09:54:53 +0200 Subject: [PATCH 28/33] Update release notes, refs #566 --- docs/pages/release_notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 61c3918dec..541f888994 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -102,6 +102,9 @@ and include them to such reports. and "NcssTypeCount". The new rule uses the metrics framework to achieve the same. It has two properties, to define the report level for method and class sizes separately. Constructors and methods are considered the same. +* The new rule `ForLoopCanBeForeach` (ruleset `java-migration`) helps in identifies those for-loops that can + be safely refactored into for-each-loops. + #### Modified Rules * The rule `UnnecessaryFinalModifier` (ruleset `java-unnecessarycode`) has been revamped to detect more cases. @@ -273,6 +276,7 @@ All existing rules have been updated to reflect these changes. If you have custo * [#556](https://github.com/pmd/pmd/pull/556): \[java] Fix #357: UncommentedEmptyConstructor consider annotations on Constructor - [Clément Fournier](https://github.com/oowekyala) * [#557](https://github.com/pmd/pmd/pull/557): \[java] Fix NPath metric not counting ternaries correctly - [Clément Fournier](https://github.com/oowekyala) * [#563](https://github.com/pmd/pmd/pull/563): \[java] Add support for basic method type inference for strict invocation - [Bendegúz Nagy](https://github.com/WinterGrascph) +* [#566](https://github.com/pmd/pmd/pull/566): \[java] New rule in migrating ruleset: ForLoopCanBeForeach - [Clément Fournier](https://github.com/oowekyala) * [#567](https://github.com/pmd/pmd/pull/567): \[java] Last API change for metrics (metric options) - [Clément Fournier](https://github.com/oowekyala) * [#570](https://github.com/pmd/pmd/pull/570): \[java] Model lower, upper and intersection types - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#573](https://github.com/pmd/pmd/pull/573): \[java] Data class rule - [Clément Fournier](https://github.com/oowekyala) From a50d5a82cc88f888bf861178dd62cf79dd27e2e9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 9 Sep 2017 09:56:27 +0200 Subject: [PATCH 29/33] Add new rule to internal ruleset 600.xml --- pmd-core/src/main/resources/rulesets/releases/600.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pmd-core/src/main/resources/rulesets/releases/600.xml b/pmd-core/src/main/resources/rulesets/releases/600.xml index 4c7bc8b288..cebdca8529 100644 --- a/pmd-core/src/main/resources/rulesets/releases/600.xml +++ b/pmd-core/src/main/resources/rulesets/releases/600.xml @@ -9,6 +9,7 @@ This ruleset contains links to rules that are new in PMD v6.0.0 + From 388afb96184d67428f6b04abd2a19b8f232ad696 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 9 Sep 2017 09:58:05 +0200 Subject: [PATCH 30/33] Fix typo --- docs/pages/release_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 541f888994..1b2450a8e2 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -102,8 +102,8 @@ and include them to such reports. and "NcssTypeCount". The new rule uses the metrics framework to achieve the same. It has two properties, to define the report level for method and class sizes separately. Constructors and methods are considered the same. -* The new rule `ForLoopCanBeForeach` (ruleset `java-migration`) helps in identifies those for-loops that can - be safely refactored into for-each-loops. +* The new rule `ForLoopCanBeForeach` (ruleset `java-migration`) helps to identify those for-loops that can + be safely refactored into for-each-loops available since java 1.5. #### Modified Rules From 3d18e8b36f1b838f7bdbbc44a6def06c51183a6d Mon Sep 17 00:00:00 2001 From: "Travis CI (pmd-bot)" Date: Sat, 9 Sep 2017 08:12:38 +0000 Subject: [PATCH 31/33] Update documentation --- docs/pages/pmd/rules/java.md | 1 + docs/pages/pmd/rules/java/migrating.md | 33 +++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index a2bf7348cc..92c8d37e80 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -263,6 +263,7 @@ List of rulesets and rules contained in each ruleset. * [AvoidAssertAsIdentifier](pmd_rules_java_migrating.html#avoidassertasidentifier): Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. * [AvoidEnumAsIdentifier](pmd_rules_java_migrating.html#avoidenumasidentifier): Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. * [ByteInstantiation](pmd_rules_java_migrating.html#byteinstantiation): Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf().It m... +* [ForLoopCanBeForeach](pmd_rules_java_migrating.html#forloopcanbeforeach): Reports loops that can be safely replaced with the foreach syntax. The rule considers loops over ... * [IntegerInstantiation](pmd_rules_java_migrating.html#integerinstantiation): Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(... * [JUnit4SuitesShouldUseSuiteAnnotation](pmd_rules_java_migrating.html#junit4suitesshouldusesuiteannotation): In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicatedthro... * [JUnit4TestShouldUseAfterAnnotation](pmd_rules_java_migrating.html#junit4testshoulduseafterannotation): In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.... diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md index 0f8d5ec791..9659247d24 100644 --- a/docs/pages/pmd/rules/java/migrating.md +++ b/docs/pages/pmd/rules/java/migrating.md @@ -5,7 +5,7 @@ permalink: pmd_rules_java_migrating.html folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml -keywords: Migration, ReplaceVectorWithList, ReplaceHashtableWithMap, ReplaceEnumerationWithIterator, AvoidEnumAsIdentifier, AvoidAssertAsIdentifier, IntegerInstantiation, ByteInstantiation, ShortInstantiation, LongInstantiation, JUnit4TestShouldUseBeforeAnnotation, JUnit4TestShouldUseAfterAnnotation, JUnit4TestShouldUseTestAnnotation, JUnit4SuitesShouldUseSuiteAnnotation, JUnitUseExpected +keywords: Migration, ReplaceVectorWithList, ReplaceHashtableWithMap, ReplaceEnumerationWithIterator, AvoidEnumAsIdentifier, AvoidAssertAsIdentifier, IntegerInstantiation, ByteInstantiation, ShortInstantiation, LongInstantiation, JUnit4TestShouldUseBeforeAnnotation, JUnit4TestShouldUseAfterAnnotation, JUnit4TestShouldUseTestAnnotation, JUnit4SuitesShouldUseSuiteAnnotation, JUnitUseExpected, ForLoopCanBeForeach --- ## AvoidAssertAsIdentifier @@ -75,6 +75,37 @@ public class Foo { } ``` +## ForLoopCanBeForeach + +**Since:** PMD 6.0 + +**Priority:** Medium (3) + +**Minimum Language Version:** Java 1.5 + +Reports loops that can be safely replaced with the foreach syntax. The rule considers loops over + lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to + access an element of the list or array, only has one update statement, and loops through *every* + element of the list or array left to right. + +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.migrating.ForLoopCanBeForeachRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/ForLoopCanBeForeachRule.java) + +**Example(s):** + +``` java +public class MyClass { + void loop(List l) { + for (int i = 0; i < l.size(); i++) { // pre Java 1.5 + System.out.println(l.get(i)); + } + + for (String s : l) { // post Java 1.5 + System.out.println(s); + } + } +} +``` + ## IntegerInstantiation **Since:** PMD 3.5 From 2fdb8de3f2a7b4c8f2bd582cbeb00459d363c49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Sat, 9 Sep 2017 18:55:29 -0300 Subject: [PATCH 32/33] Update changelog, refs #598 --- docs/pages/release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index d92379bfaa..b88142a5cf 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -166,6 +166,7 @@ All existing rules have been updated to reflect these changes. If you have custo * java-comments * [#536](https://github.com/pmd/pmd/issues/536): \[java] CommentDefaultAccessModifierRule ignores constructors * java-controversial + * [#388](https://github.com/pmd/pmd/issues/388): \[java] controversial.AvoidLiteralsInIfCondition 0.0 false positive * [#408](https://github.com/pmd/pmd/issues/408): \[java] DFA not analyzing asserts * [#537](https://github.com/pmd/pmd/issues/537): \[java] UnnecessaryParentheses fails to detect obvious scenario * java-design @@ -283,3 +284,4 @@ All existing rules have been updated to reflect these changes. If you have custo * [#581](https://github.com/pmd/pmd/pull/581): \[java] Relax AbstractClassWithoutAnyMethod when class is annotated by @AutoValue - [Niklas Baudy](https://github.com/vanniktech) * [#583](https://github.com/pmd/pmd/pull/583): \[java] Documentation about writing metrics - [Clément Fournier](https://github.com/oowekyala) * [#585](https://github.com/pmd/pmd/pull/585): \[java] Moved NcssCountRule to codesize.xml - [Clément Fournier](https://github.com/oowekyala) +* [#598](https://github.com/pmd/pmd/pull/598): \[java] Fix #388: controversial.AvoidLiteralsInIfCondition 0.0 false positive - [Clément Fournier](https://github.com/oowekyala) From 6d4e902a2a36df937bb445a53223485a2e16e473 Mon Sep 17 00:00:00 2001 From: "Travis CI (pmd-bot)" Date: Sat, 9 Sep 2017 22:20:05 +0000 Subject: [PATCH 33/33] Update documentation --- docs/pages/pmd/rules/apex/apexunit.md | 10 + docs/pages/pmd/rules/apex/braces.md | 20 ++ docs/pages/pmd/rules/apex/complexity.md | 45 +++ docs/pages/pmd/rules/apex/performance.md | 10 + docs/pages/pmd/rules/apex/security.md | 55 ++++ docs/pages/pmd/rules/apex/style.md | 30 ++ docs/pages/pmd/rules/ecmascript/basic.md | 45 +++ docs/pages/pmd/rules/ecmascript/braces.md | 20 ++ .../pmd/rules/ecmascript/controversial.md | 5 + .../pages/pmd/rules/ecmascript/unnecessary.md | 15 + docs/pages/pmd/rules/java/android.md | 15 + docs/pages/pmd/rules/java/basic.md | 120 ++++++++ docs/pages/pmd/rules/java/braces.md | 20 ++ docs/pages/pmd/rules/java/clone.md | 25 ++ docs/pages/pmd/rules/java/codesize.md | 70 +++++ docs/pages/pmd/rules/java/comments.md | 20 ++ docs/pages/pmd/rules/java/controversial.md | 112 ++++++- docs/pages/pmd/rules/java/coupling.md | 25 ++ docs/pages/pmd/rules/java/design.md | 285 ++++++++++++++++++ docs/pages/pmd/rules/java/empty.md | 55 ++++ docs/pages/pmd/rules/java/finalizers.md | 30 ++ docs/pages/pmd/rules/java/imports.md | 30 ++ docs/pages/pmd/rules/java/j2ee.md | 45 +++ docs/pages/pmd/rules/java/javabeans.md | 10 + docs/pages/pmd/rules/java/junit.md | 60 ++++ .../pmd/rules/java/logging-jakarta-commons.md | 20 ++ docs/pages/pmd/rules/java/logging-java.md | 30 ++ docs/pages/pmd/rules/java/migrating.md | 75 +++++ docs/pages/pmd/rules/java/naming.md | 100 ++++++ docs/pages/pmd/rules/java/optimizations.md | 60 ++++ docs/pages/pmd/rules/java/strictexception.md | 60 ++++ docs/pages/pmd/rules/java/strings.md | 80 +++++ docs/pages/pmd/rules/java/sunsecure.md | 10 + docs/pages/pmd/rules/java/unnecessary.md | 45 +++ docs/pages/pmd/rules/java/unusedcode.md | 20 ++ docs/pages/pmd/rules/jsp/basic-jsf.md | 5 + docs/pages/pmd/rules/jsp/basic.md | 55 ++++ docs/pages/pmd/rules/plsql/TomKytesDespair.md | 5 + docs/pages/pmd/rules/plsql/codesize.md | 60 ++++ docs/pages/pmd/rules/plsql/dates.md | 15 + docs/pages/pmd/rules/plsql/strictsyntax.md | 5 + docs/pages/pmd/rules/pom/basic.md | 10 + docs/pages/pmd/rules/vf/security.md | 10 + docs/pages/pmd/rules/vm/basic.md | 45 +++ docs/pages/pmd/rules/xml/basic.md | 5 + docs/pages/pmd/rules/xsl/xpath.md | 10 + 46 files changed, 1901 insertions(+), 1 deletion(-) diff --git a/docs/pages/pmd/rules/apex/apexunit.md b/docs/pages/pmd/rules/apex/apexunit.md index 64e984532c..b6b26fda98 100644 --- a/docs/pages/pmd/rules/apex/apexunit.md +++ b/docs/pages/pmd/rules/apex/apexunit.md @@ -40,6 +40,11 @@ public class Foo { |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 + +``` + ## ApexUnitTestShouldNotUseSeeAllDataTrue **Since:** PMD 5.5.1 @@ -72,3 +77,8 @@ public class Foo { |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 + +``` + diff --git a/docs/pages/pmd/rules/apex/braces.md b/docs/pages/pmd/rules/apex/braces.md index f07d7b466b..5f4b7e565a 100644 --- a/docs/pages/pmd/rules/apex/braces.md +++ b/docs/pages/pmd/rules/apex/braces.md @@ -42,6 +42,11 @@ for (int i = 0; i < 42; i++) { // preferred approach |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 + +``` + ## IfElseStmtsMustUseBraces **Since:** PMD 5.6.0 @@ -79,6 +84,11 @@ else |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 + +``` + ## IfStmtsMustUseBraces **Since:** PMD 5.6.0 @@ -112,6 +122,11 @@ if (foo) { // preferred approach |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 + +``` + ## WhileLoopsMustUseBraces **Since:** PMD 5.6.0 @@ -145,3 +160,8 @@ while (true) { // preferred approach |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 + +``` + diff --git a/docs/pages/pmd/rules/apex/complexity.md b/docs/pages/pmd/rules/apex/complexity.md index 96aab8d53b..b3832f5631 100644 --- a/docs/pages/pmd/rules/apex/complexity.md +++ b/docs/pages/pmd/rules/apex/complexity.md @@ -42,6 +42,11 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |problemDepth|3|The if statement depth reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveClassLength **Since:** PMD 5.5.0 @@ -84,6 +89,11 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveParameterList **Since:** PMD 5.5.0 @@ -119,6 +129,11 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessivePublicCount **Since:** PMD 5.5.0 @@ -159,6 +174,11 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssConstructorCount **Since:** PMD 5.5.0 @@ -198,6 +218,11 @@ public class Foo extends Bar { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssMethodCount **Since:** PMD 5.5.0 @@ -236,6 +261,11 @@ public class Foo extends Bar { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssTypeCount **Since:** PMD 5.5.0 @@ -276,6 +306,11 @@ public class Foo extends Bar { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## StdCyclomaticComplexity **Since:** PMD 5.5.0 @@ -341,6 +376,11 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |reportLevel|10|Cyclomatic Complexity reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyFields **Since:** PMD 5.5.0 @@ -381,3 +421,8 @@ public class Person { |cc_block_highlighting|false|Code Climate Block Highlighting| |maxfields|15|Max allowable fields| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md index e0615d60c8..6cf6388106 100644 --- a/docs/pages/pmd/rules/apex/performance.md +++ b/docs/pages/pmd/rules/apex/performance.md @@ -39,6 +39,11 @@ public class Something { |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 + +``` + ## AvoidSoqlInLoops **Since:** PMD 5.5.0 @@ -69,3 +74,8 @@ public class Something { |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 + +``` + diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md index 9bcb42d431..09ca5f3905 100644 --- a/docs/pages/pmd/rules/apex/security.md +++ b/docs/pages/pmd/rules/apex/security.md @@ -37,6 +37,11 @@ public without sharing class Foo { |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 + +``` + ## ApexCRUDViolation **Since:** PMD 5.5.3 @@ -76,6 +81,11 @@ public class Foo { |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 + +``` + ## ApexCSRF **Since:** PMD 5.5.3 @@ -109,6 +119,11 @@ public class Foo { |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 + +``` + ## ApexDangerousMethods **Since:** PMD 5.5.3 @@ -144,6 +159,11 @@ public class Foo { |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 + +``` + ## ApexInsecureEndpoint **Since:** PMD 5.5.3 @@ -174,6 +194,11 @@ public without sharing class Foo { |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 + +``` + ## ApexOpenRedirect **Since:** PMD 5.5.3 @@ -204,6 +229,11 @@ public without sharing class Foo { |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 + +``` + ## ApexSharingViolations **Since:** PMD 5.5.3 @@ -231,6 +261,11 @@ public without sharing class Foo { |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 + +``` + ## ApexSOQLInjection **Since:** PMD 5.5.3 @@ -259,6 +294,11 @@ public class Foo { |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 + +``` + ## ApexSuggestUsingNamedCred **Since:** PMD 5.5.3 @@ -301,6 +341,11 @@ public class Foo { |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 + +``` + ## ApexXSSFromEscapeFalse **Since:** PMD 5.5.3 @@ -329,6 +374,11 @@ public without sharing class Foo { |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 + +``` + ## ApexXSSFromURLParam **Since:** PMD 5.5.3 @@ -357,3 +407,8 @@ public without sharing class Foo { |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 + +``` + diff --git a/docs/pages/pmd/rules/apex/style.md b/docs/pages/pmd/rules/apex/style.md index 9e96f7c354..660db734fd 100644 --- a/docs/pages/pmd/rules/apex/style.md +++ b/docs/pages/pmd/rules/apex/style.md @@ -36,6 +36,11 @@ global class Unchangeable { |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 + +``` + ## AvoidLogicInTrigger **Since:** PMD 5.5.0 @@ -75,6 +80,11 @@ trigger Accounts on Account (before insert, before update, before delete, after |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 + +``` + ## ClassNamingConventions **Since:** PMD 5.5.0 @@ -99,6 +109,11 @@ public class Foo {} |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 + +``` + ## MethodNamingConventions **Since:** PMD 5.5.0 @@ -126,6 +141,11 @@ public class Foo { |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 + +``` + ## MethodWithSameNameAsEnclosingClass **Since:** PMD 5.5.0 @@ -155,6 +175,11 @@ public class MyClass { |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 + +``` + ## VariableNamingConventions **Since:** PMD 5.5.0 @@ -196,3 +221,8 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |checkMembers|true|Check member variables| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/ecmascript/basic.md b/docs/pages/pmd/rules/ecmascript/basic.md index 4276ff36e2..9663b6c9d0 100644 --- a/docs/pages/pmd/rules/ecmascript/basic.md +++ b/docs/pages/pmd/rules/ecmascript/basic.md @@ -55,6 +55,11 @@ function getX() { |allowTernaryResults|false|Allow assignment within the result expressions of a ternary operator| |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidTrailingComma **Since:** PMD 5.1 @@ -88,6 +93,11 @@ function(arg) { |allowObjectLiteral|false|Allow a trailing comma within an object literal| |allowArrayLiteral|false|Allow a trailing comma within an array literal| +**Use this rule by referencing it:** +``` xml + +``` + ## ConsistentReturn **Since:** PMD 5.0 @@ -128,6 +138,11 @@ function bar() { |recordingLocalJsDocComments|true|Specifies that JsDoc comments are produced in the AST.| |recordingComments|true|Specifies that comments are produced in the AST.| +**Use this rule by referencing it:** +``` xml + +``` + ## EqualComparison **Since:** PMD 5.0 @@ -167,6 +182,11 @@ if (someVar != 3) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## GlobalVariable **Since:** PMD 5.0 @@ -192,6 +212,11 @@ function(arg) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## InnaccurateNumericLiteral **Since:** PMD 5.0 @@ -221,6 +246,11 @@ var y = 1.1234567890123; // Ok var z = 1.12345678901234567; // Not good ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ScopeForInVariable **Since:** PMD 5.0 @@ -269,6 +299,11 @@ function bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnreachableCode **Since:** PMD 5.0 @@ -303,6 +338,11 @@ function bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseBaseWithParseInt **Since:** PMD 5.0.1 @@ -331,3 +371,8 @@ parseInt("010"); // unclear, could be interpreted as 10 or 7 (with a base of parseInt("10", 10); // good ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/ecmascript/braces.md b/docs/pages/pmd/rules/ecmascript/braces.md index 9b294698b2..5f67d6dcf7 100644 --- a/docs/pages/pmd/rules/ecmascript/braces.md +++ b/docs/pages/pmd/rules/ecmascript/braces.md @@ -34,6 +34,11 @@ for (var i = 0; i < 42; i++) foo(); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IfElseStmtsMustUseBraces **Since:** PMD 5.0 @@ -65,6 +70,11 @@ else y++; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IfStmtsMustUseBraces **Since:** PMD 5.0 @@ -90,6 +100,11 @@ if (foo) x++; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## WhileLoopsMustUseBraces **Since:** PMD 5.0 @@ -115,3 +130,8 @@ while (true) x++; ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/ecmascript/controversial.md b/docs/pages/pmd/rules/ecmascript/controversial.md index 611a49bc54..b73ea9d35b 100644 --- a/docs/pages/pmd/rules/ecmascript/controversial.md +++ b/docs/pages/pmd/rules/ecmascript/controversial.md @@ -27,3 +27,8 @@ with (object) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/ecmascript/unnecessary.md b/docs/pages/pmd/rules/ecmascript/unnecessary.md index a88dd7df01..6c5c0f5ec0 100644 --- a/docs/pages/pmd/rules/ecmascript/unnecessary.md +++ b/docs/pages/pmd/rules/ecmascript/unnecessary.md @@ -39,6 +39,11 @@ if (x) { return z; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryBlock **Since:** PMD 5.0 @@ -70,6 +75,11 @@ if (bar) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryParentheses **Since:** PMD 5.0 @@ -90,3 +100,8 @@ var y = (1 + 1); // Ok var z = ((1 + 1)); // Bad ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/android.md b/docs/pages/pmd/rules/java/android.md index c62a608e96..a2ae5d4ed4 100644 --- a/docs/pages/pmd/rules/java/android.md +++ b/docs/pages/pmd/rules/java/android.md @@ -46,6 +46,11 @@ public class DummyActivity extends Activity { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CallSuperLast **Since:** PMD 4.2.5 @@ -83,6 +88,11 @@ public class DummyActivity extends Activity { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoNotHardCodeSDCard **Since:** PMD 4.2.6 @@ -107,3 +117,8 @@ public class MyActivity extends Activity { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md index b465d2f469..70130b5879 100644 --- a/docs/pages/pmd/rules/java/basic.md +++ b/docs/pages/pmd/rules/java/basic.md @@ -45,6 +45,11 @@ for (int i = 0; i < 10; i++) { |checkContinueLoopTypes|[for, do, while]|Check for continue statements in loop types| |checkBreakLoopTypes|[for, do, while]|Check for break statements in loop types| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidDecimalLiteralsInBigDecimalConstructor **Since:** PMD 3.4 @@ -93,6 +98,11 @@ BigDecimal bd = new BigDecimal("1.123"); // preferred approach BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer values ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidMultipleUnaryOperators **Since:** PMD 4.2 @@ -126,6 +136,11 @@ int i = ~-2; int j = -~7; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidThreadGroup **Since:** PMD 3.6 @@ -153,6 +168,11 @@ public class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidUsingHardCodedIP **Since:** PMD 4.1 @@ -179,6 +199,11 @@ public class Foo { |checkAddressTypes|[IPv4, IPv6, IPv4 mapped IPv6]|Check for IP address types.| |pattern|^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$|Regular Expression| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidUsingOctalValues **Since:** PMD 3.9 @@ -204,6 +229,11 @@ k = i * j; // set k with 80 not 120 |----|-------------|-----------| |strict|false|Detect violations between 00 and 07| +**Use this rule by referencing it:** +``` xml + +``` + ## BigIntegerInstantiation **Since:** PMD 3.9 @@ -225,6 +255,11 @@ BigInteger bi4; bi4 = new BigInteger(0); // reference BigInteger.ZERO instead ``` +**Use this rule by referencing it:** +``` xml + +``` + ## BooleanInstantiation **Since:** PMD 1.2 @@ -242,6 +277,11 @@ Boolean bar = new Boolean("true"); // unnecessary creation, just referenc Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## BrokenNullCheck **Since:** PMD 3.8 @@ -266,6 +306,11 @@ public String bar(String string) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CheckResultSet **Since:** PMD 4.1 @@ -294,6 +339,11 @@ if (rst.next()) { // result is properly examined and used } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CheckSkipResult **Since:** PMD 5.0 @@ -325,6 +375,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ClassCastExceptionWithToArray **Since:** PMD 3.4 @@ -361,6 +416,11 @@ Integer[] a = (Integer [])c.toArray(); Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CollapsibleIfStatements **Since:** PMD 3.1 @@ -396,6 +456,11 @@ void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DontCallThreadRun **Since:** PMD 4.3 @@ -427,6 +492,11 @@ t.run(); // use t.start() instead new Thread().run(); // same violation ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DontUseFloatTypeForLoopIndices **Since:** PMD 4.3 @@ -458,6 +528,11 @@ public class Count { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoubleCheckedLocking **Since:** PMD 1.04 @@ -493,6 +568,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ExtendsObject **Since:** PMD 5.0 @@ -512,6 +592,11 @@ public class Foo extends Object { // not required } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ForLoopShouldBeWhileLoop **Since:** PMD 1.02 @@ -539,6 +624,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JumbledIncrementer **Since:** PMD 1.0 @@ -570,6 +660,11 @@ public class JumbledIncrementerRule1 { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MisplacedNullCheck **Since:** PMD 3.5 @@ -617,6 +712,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## OverrideBothEqualsAndHashcode **Since:** PMD 0.4 @@ -652,6 +752,11 @@ public class Foo { // perfect, both methods provided } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ReturnFromFinallyBlock **Since:** PMD 1.05 @@ -680,6 +785,11 @@ public class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifiedTernary **Since:** PMD 5.4.0 @@ -724,6 +834,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnconditionalIfStatement **Since:** PMD 1.5 @@ -750,3 +865,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/braces.md b/docs/pages/pmd/rules/java/braces.md index 86aef41add..a2ea2bab6b 100644 --- a/docs/pages/pmd/rules/java/braces.md +++ b/docs/pages/pmd/rules/java/braces.md @@ -28,6 +28,11 @@ for (int i = 0; i < 42; i++) foo(); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IfElseStmtsMustUseBraces **Since:** PMD 0.2 @@ -58,6 +63,11 @@ if (foo) x = x-1; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IfStmtsMustUseBraces **Since:** PMD 1.0 @@ -83,6 +93,11 @@ if (foo) { // preferred approach } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## WhileLoopsMustUseBraces **Since:** PMD 0.7 @@ -108,3 +123,8 @@ while (true) { // preferred approach } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md index af33883b92..7091400db3 100644 --- a/docs/pages/pmd/rules/java/clone.md +++ b/docs/pages/pmd/rules/java/clone.md @@ -43,6 +43,11 @@ public class Foo implements Cloneable { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CloneMethodMustImplementCloneable **Since:** PMD 1.9 @@ -76,6 +81,11 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CloneMethodReturnTypeMustMatchClassName **Since:** PMD 5.4.0 @@ -114,6 +124,11 @@ public class Foo implements Cloneable { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CloneThrowsCloneNotSupportedException **Since:** PMD 1.9 @@ -146,6 +161,11 @@ public class MyClass implements Cloneable{ } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ProperCloneImplementation **Since:** PMD 1.4 @@ -176,3 +196,8 @@ class Foo{ } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md index bad1edbc14..de62bd2e1d 100644 --- a/docs/pages/pmd/rules/java/codesize.md +++ b/docs/pages/pmd/rules/java/codesize.md @@ -71,6 +71,11 @@ public class Foo { // This has a Cyclomatic Complexity = 12 |showClassesComplexity|true|Add class average violations to the report| |reportLevel|10|Cyclomatic Complexity reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveClassLength **Since:** PMD 0.6 @@ -111,6 +116,11 @@ public class Foo { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveMethodLength **Since:** PMD 0.6 @@ -142,6 +152,11 @@ public void doSomething() { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveParameterList **Since:** PMD 0.9 @@ -177,6 +192,11 @@ public void addPerson( // preferred approach |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessivePublicCount **Since:** PMD 1.04 @@ -214,6 +234,11 @@ public class Foo { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ModifiedCyclomaticComplexity Deprecated @@ -279,6 +304,11 @@ public class Foo { // This has a Cyclomatic Complexity = 9 |showClassesComplexity|true|Add class average violations to the report| |reportLevel|10|Cyclomatic Complexity reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssConstructorCount Deprecated @@ -318,6 +348,11 @@ public class Foo extends Bar { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssCount **Since:** PMD 6.0 @@ -369,6 +404,11 @@ class Foo { // +1, total Ncss = 12 |methodReportLevel|12|Metric reporting threshold for methods| |classReportLevel|250|Metric reporting threshold for classes| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssMethodCount Deprecated @@ -407,6 +447,11 @@ public class Foo extends Bar { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssTypeCount Deprecated @@ -446,6 +491,11 @@ public class Foo extends Bar { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NPathComplexity **Since:** PMD 3.9 @@ -498,6 +548,11 @@ void bar() { // this is something more complex than it needs to be, |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## StdCyclomaticComplexity Deprecated @@ -562,6 +617,11 @@ public class Foo { // This has a Cyclomatic Complexity = 12 |showClassesComplexity|true|Add class average violations to the report| |reportLevel|10|Cyclomatic Complexity reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyFields **Since:** PMD 3.0 @@ -597,6 +657,11 @@ public class Person { // this is more manageable |----|-------------|-----------| |maxfields|15|Max allowable fields| +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyMethods **Since:** PMD 4.2 @@ -627,3 +692,8 @@ complexity and find a way to have more fine grained objects. |----|-------------|-----------| |maxmethods|10|The method count reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/comments.md b/docs/pages/pmd/rules/java/comments.md index fc3a75425d..ac237f75f6 100644 --- a/docs/pages/pmd/rules/java/comments.md +++ b/docs/pages/pmd/rules/java/comments.md @@ -31,6 +31,11 @@ A rule for the politically correct... we don't want to offend anyone. |caseSensitive|false|Case sensitive| |wordsAreRegex|false|Use regular expressions| +**Use this rule by referencing it:** +``` xml + +``` + ## CommentDefaultAccessModifier **Since:** PMD 5.4.0 @@ -74,6 +79,11 @@ public class Foo { |----|-------------|-----------| |regex||Regular expression| +**Use this rule by referencing it:** +``` xml + +``` + ## CommentRequired **Since:** PMD 5.1 @@ -105,6 +115,11 @@ Denotes whether comments are required (or unwanted) for specific language elemen |fieldCommentRequirement|Required|Field comments. Possible values: [Required, Ignored, Unwanted]| |headerCommentRequirement|Required|Header comments. Possible values: [Required, Ignored, Unwanted]| +**Use this rule by referencing it:** +``` xml + +``` + ## CommentSize **Since:** PMD 5.0 @@ -143,3 +158,8 @@ Determines whether the dimensions of non-header comments found are within the sp |maxLines|6|Maximum lines| |maxLineLength|80|Maximum line length| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/controversial.md b/docs/pages/pmd/rules/java/controversial.md index e403df606c..ec1ec4e7f6 100644 --- a/docs/pages/pmd/rules/java/controversial.md +++ b/docs/pages/pmd/rules/java/controversial.md @@ -37,6 +37,11 @@ public void bar() { |allowFor|false|Allow assignment within the conditional expression of a for statement| |allowIf|false|Allow assignment within the conditional expression of an if statement| +**Use this rule by referencing it:** +``` xml + +``` + ## AtLeastOneConstructor **Since:** PMD 1.04 @@ -66,6 +71,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidAccessibilityAlteration **Since:** PMD 4.1 @@ -133,6 +143,11 @@ public class Violation { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidFinalLocalVariable **Since:** PMD 4.1 @@ -164,6 +179,11 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidLiteralsInIfCondition **Since:** PMD 4.2.6 @@ -178,7 +198,7 @@ More exceptions can be defined with the property "ignoreMagicNumbers". //IfStatement/Expression/*/PrimaryExpression/PrimaryPrefix/Literal [not(NullLiteral)] [not(BooleanLiteral)] -[empty(index-of(tokenize($ignoreMagicNumbers, ','), @Image))] +[empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))] ``` **Example(s):** @@ -210,6 +230,11 @@ public void checkRequests() { |----|-------------|-----------| |ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidPrefixingMethodParameters **Since:** PMD 5.0 @@ -255,6 +280,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidUsingNativeCode **Since:** PMD 4.1 @@ -287,6 +317,11 @@ public class SomeJNIClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidUsingShortType **Since:** PMD 4.1 @@ -315,6 +350,11 @@ public class UsingShort { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidUsingVolatile **Since:** PMD 4.1 @@ -338,6 +378,11 @@ public class ThrDeux { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CallSuperInConstructor **Since:** PMD 3.0 @@ -370,6 +415,11 @@ public class Foo extends Bar{ } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DataflowAnomalyAnalysis **Since:** PMD 3.9 @@ -403,6 +453,11 @@ public void foo() { |maxViolations|100|Maximum number of anomalies per class| |maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.| +**Use this rule by referencing it:** +``` xml + +``` + ## DefaultPackage **Since:** PMD 3.4 @@ -423,6 +478,11 @@ or MethodDeclaration[@PackagePrivate='true'] ] ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoNotCallGarbageCollectionExplicitly **Since:** PMD 4.2 @@ -472,6 +532,11 @@ public class GCCall { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DontImportSun **Since:** PMD 1.5 @@ -489,6 +554,11 @@ import sun.misc.foo; public class Foo {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NullAssignment **Since:** PMD 1.02 @@ -514,6 +584,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## OneDeclarationPerLine **Since:** PMD 5.0 @@ -548,6 +623,11 @@ String name, |----|-------------|-----------| |strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.| +**Use this rule by referencing it:** +``` xml + +``` + ## OnlyOneReturn **Since:** PMD 1.0 @@ -571,6 +651,11 @@ public class OneReturnOnly1 { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SuspiciousOctalEscape **Since:** PMD 1.5 @@ -599,6 +684,11 @@ public void foo() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryConstructor **Since:** PMD 1.0 @@ -626,6 +716,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryParentheses Deprecated @@ -711,6 +806,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseConcurrentHashMap **Since:** PMD 4.2.6 @@ -739,6 +839,11 @@ public class ConcurrentApp { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseObjectForClearerAPI **Since:** PMD 4.2.6 @@ -776,3 +881,8 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/coupling.md b/docs/pages/pmd/rules/java/coupling.md index 40fdfa9e0a..2139ff4786 100644 --- a/docs/pages/pmd/rules/java/coupling.md +++ b/docs/pages/pmd/rules/java/coupling.md @@ -45,6 +45,11 @@ public class Foo { |----|-------------|-----------| |threshold|20|Unique type reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveImports **Since:** PMD 1.04 @@ -76,6 +81,11 @@ public class Foo { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## LawOfDemeter **Since:** PMD 5.0 @@ -120,6 +130,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LooseCoupling **Since:** PMD 0.7 @@ -150,6 +165,11 @@ public Set getFoo() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LoosePackageCoupling **Since:** PMD 5.0 @@ -180,3 +200,8 @@ public class Bar { |classes|[]|Allowed classes| |packages|[]|Restricted packages| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index 881af2b79a..a7f58258a6 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -37,6 +37,11 @@ public abstract class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AbstractClassWithoutAnyMethod **Since:** PMD 4.2 @@ -63,6 +68,11 @@ public class abstract Example { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AccessorClassGeneration **Since:** PMD 1.04 @@ -90,6 +100,11 @@ public class Outer { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AccessorMethodGeneration **Since:** PMD 5.5.4 @@ -121,6 +136,11 @@ public class OuterClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AssignmentToNonFinalStatic **Since:** PMD 2.2 @@ -142,6 +162,11 @@ public class StaticField { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidDeeplyNestedIfStmts **Since:** PMD 1.0 @@ -174,6 +199,11 @@ public class Foo { |----|-------------|-----------| |problemDepth|3|The if statement depth reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidInstanceofChecksInCatchClause **Since:** PMD 3.0 @@ -209,6 +239,11 @@ try { // Prefer this: } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidProtectedFieldInFinalClass **Since:** PMD 2.1 @@ -234,6 +269,11 @@ public final class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidProtectedMethodInFinalClassNotExtending **Since:** PMD 5.1 @@ -259,6 +299,11 @@ public final class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidReassigningParameters **Since:** PMD 1.0 @@ -279,6 +324,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidSynchronizedAtMethodLevel **Since:** PMD 3.0 @@ -318,6 +368,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## BadComparison **Since:** PMD 1.8 @@ -339,6 +394,11 @@ precision when comparing floating point numbers these are likely to cause logic boolean x = (y == Double.NaN); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ClassWithOnlyPrivateConstructorsShouldBeFinal **Since:** PMD 4.1 @@ -364,6 +424,11 @@ public class Foo { //Should be final } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## CloseResource **Since:** PMD 1.2.2 @@ -400,6 +465,11 @@ public class Bar { |types|[java.sql.Connection, java.sql.Statement, java.sql.ResultSet]|Affected types| |closeTargets|[]|Methods which may close this resource| +**Use this rule by referencing it:** +``` xml + +``` + ## CompareObjectsWithEquals **Since:** PMD 3.2 @@ -420,6 +490,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ConfusingTernary **Since:** PMD 1.9 @@ -449,6 +524,11 @@ boolean bar(int x, int y) { |----|-------------|-----------| |ignoreElseIf|false|Ignore conditions with an else-if case| +**Use this rule by referencing it:** +``` xml + +``` + ## ConstantsInInterface **Since:** PMD 5.5 @@ -493,6 +573,11 @@ public interface YetAnotherConstantInterface { |----|-------------|-----------| |ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods| +**Use this rule by referencing it:** +``` xml + +``` + ## ConstructorCallsOverridableMethod **Since:** PMD 1.04 @@ -532,6 +617,11 @@ public class JuniorClass extends SeniorClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DefaultLabelNotLastInSwitchStmt **Since:** PMD 1.5 @@ -563,6 +653,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyMethodInAbstractClassShouldBeAbstract **Since:** PMD 4.1 @@ -604,6 +699,11 @@ public abstract class ShouldBeAbstract { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EqualsNull **Since:** PMD 1.9 @@ -642,6 +742,11 @@ if (x == null) { // preferred } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## FieldDeclarationsShouldBeAtStartOfClass **Since:** PMD 5.0 @@ -677,6 +782,11 @@ public class HelloWorldBean { |ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations| |ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.| +**Use this rule by referencing it:** +``` xml + +``` + ## FinalFieldCouldBeStatic **Since:** PMD 1.1 @@ -701,6 +811,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## GodClass **Since:** PMD 5.0 @@ -720,6 +835,11 @@ of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.GodClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## IdempotentOperations **Since:** PMD 2.0 @@ -741,6 +861,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ImmutableField **Since:** PMD 2.0 @@ -766,6 +891,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## InstantiationToGetClass **Since:** PMD 2.0 @@ -793,6 +923,11 @@ Class c = new String().getClass(); Class c = String.class; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LogicInversion **Since:** PMD 5.0 @@ -822,6 +957,11 @@ public boolean bar(int a, int b) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MissingBreakInSwitch **Since:** PMD 3.0 @@ -865,6 +1005,11 @@ public void bar(int status) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MissingStaticMethodInNonInstantiatableClass **Since:** PMD 3.0 @@ -913,6 +1058,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NonCaseLabelInSwitchStatement **Since:** PMD 1.5 @@ -944,6 +1094,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NonStaticInitializer **Since:** PMD 1.5 @@ -969,6 +1124,11 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NonThreadSafeSingleton **Since:** PMD 3.4 @@ -1010,6 +1170,11 @@ public static Foo getFoo() { |checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.| |checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.| +**Use this rule by referencing it:** +``` xml + +``` + ## OptimizableToArrayCall **Since:** PMD 1.8 @@ -1043,6 +1208,11 @@ Foo[] fooArray = foos.toArray(new Foo[0]); Foo[] fooArray = foos.toArray(new Foo[foos.size()]); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## PositionLiteralsFirstInCaseInsensitiveComparisons **Since:** PMD 5.1 @@ -1079,6 +1249,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## PositionLiteralsFirstInComparisons **Since:** PMD 3.3 @@ -1111,6 +1286,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## PreserveStackTrace **Since:** PMD 3.7 @@ -1149,6 +1329,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ReturnEmptyArrayRatherThanNull **Since:** PMD 4.2 @@ -1186,6 +1371,11 @@ public class Example { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimpleDateFormatNeedsLocale **Since:** PMD 2.0 @@ -1210,6 +1400,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifyBooleanExpressions **Since:** PMD 1.05 @@ -1235,6 +1430,11 @@ public class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifyBooleanReturns **Since:** PMD 0.9 @@ -1262,6 +1462,11 @@ public boolean isBarEqualTo(int x) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifyConditional **Since:** PMD 3.1 @@ -1309,6 +1514,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SingleMethodSingleton **Since:** PMD 5.4 @@ -1341,6 +1551,11 @@ public class Singleton { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SingletonClassReturningNewInstance **Since:** PMD 5.4 @@ -1366,6 +1581,11 @@ class Singleton { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SingularField **Since:** PMD 3.1 @@ -1397,6 +1617,11 @@ public class Foo { |disallowNotAssignment|false|Disallow violations where the first usage is not an assignment| |checkInnerClasses|false|Check inner classes| +**Use this rule by referencing it:** +``` xml + +``` + ## SwitchDensity **Since:** PMD 1.02 @@ -1435,6 +1660,11 @@ public class Foo { |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## SwitchStmtsShouldHaveDefault **Since:** PMD 1.0 @@ -1460,6 +1690,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## TooFewBranchesForASwitchStatement **Since:** PMD 4.2 @@ -1499,6 +1734,11 @@ public class Foo { |----|-------------|-----------| |minimumNumberCaseForASwitch|3|Minimum number of branches for a switch| +**Use this rule by referencing it:** +``` xml + +``` + ## UncommentedEmptyConstructor **Since:** PMD 3.4 @@ -1530,6 +1770,11 @@ public Foo() { |----|-------------|-----------| |ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not| +**Use this rule by referencing it:** +``` xml + +``` + ## UncommentedEmptyMethodBody **Since:** PMD 3.4 @@ -1552,6 +1797,11 @@ public void doSomething() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryLocalBeforeReturn **Since:** PMD 3.3 @@ -1579,6 +1829,11 @@ public class Foo { |----|-------------|-----------| |statementOrderMatters|true|If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.| +**Use this rule by referencing it:** +``` xml + +``` + ## UnsynchronizedStaticDateFormatter **Since:** PMD 3.6 @@ -1605,6 +1860,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseCollectionIsEmpty **Since:** PMD 3.9 @@ -1636,6 +1896,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseLocaleWithCaseConversions **Since:** PMD 2.0 @@ -1680,6 +1945,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseNotifyAllInsteadOfNotify **Since:** PMD 3.0 @@ -1712,6 +1982,11 @@ void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseUtilityClass **Since:** PMD 0.3 @@ -1735,6 +2010,11 @@ public class MaybeAUtility { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseVarargs **Since:** PMD 5.0 @@ -1780,3 +2060,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/empty.md b/docs/pages/pmd/rules/java/empty.md index 279456ca7f..818df1c477 100644 --- a/docs/pages/pmd/rules/java/empty.md +++ b/docs/pages/pmd/rules/java/empty.md @@ -45,6 +45,11 @@ public void doSomething() { |allowCommentedBlocks|false|Empty blocks containing comments will be skipped| |allowExceptionNameRegex|^$|Empty blocks catching exceptions with names matching this regular expression will be skipped| +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyFinallyBlock **Since:** PMD 0.4 @@ -71,6 +76,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyIfStmt **Since:** PMD 0.1 @@ -96,6 +106,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyInitializer **Since:** PMD 5.0 @@ -120,6 +135,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyStatementBlock **Since:** PMD 5.0 @@ -147,6 +167,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyStatementNotInLoop **Since:** PMD 1.5 @@ -181,6 +206,11 @@ public void doit() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyStaticInitializer **Since:** PMD 1.5 @@ -203,6 +233,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptySwitchStatements **Since:** PMD 1.0 @@ -227,6 +262,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptySynchronizedBlock **Since:** PMD 1.3 @@ -251,6 +291,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyTryBlock **Since:** PMD 0.4 @@ -276,6 +321,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyWhileStmt **Since:** PMD 0.2 @@ -300,3 +350,8 @@ void bar(int a, int b) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/finalizers.md b/docs/pages/pmd/rules/java/finalizers.md index f74be2739d..019fe9e051 100644 --- a/docs/pages/pmd/rules/java/finalizers.md +++ b/docs/pages/pmd/rules/java/finalizers.md @@ -27,6 +27,11 @@ void foo() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyFinalizer **Since:** PMD 1.5 @@ -48,6 +53,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## FinalizeDoesNotCallSuperFinalize **Since:** PMD 1.5 @@ -82,6 +92,11 @@ protected void finalize() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## FinalizeOnlyCallsSuperFinalize **Since:** PMD 1.5 @@ -108,6 +123,11 @@ protected void finalize() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## FinalizeOverloaded **Since:** PMD 1.5 @@ -132,6 +152,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## FinalizeShouldBeProtected **Since:** PMD 1.1 @@ -155,3 +180,8 @@ public void finalize() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/imports.md b/docs/pages/pmd/rules/java/imports.md index f927469235..d9fb36d2ef 100644 --- a/docs/pages/pmd/rules/java/imports.md +++ b/docs/pages/pmd/rules/java/imports.md @@ -31,6 +31,11 @@ import java.lang.*; // this is bad public class Foo {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DuplicateImports **Since:** PMD 0.5 @@ -49,6 +54,11 @@ import java.lang.*; public class Foo {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ImportFromSamePackage **Since:** PMD 1.02 @@ -70,6 +80,11 @@ import foo.*; // or this public class Bar{} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyStaticImports **Since:** PMD 4.1 @@ -101,6 +116,11 @@ import static Yoko; // Too much ! |----|-------------|-----------| |maximumStaticImports|4|All static imports can be disallowed by setting this to 0| +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryFullyQualifiedName **Since:** PMD 5.0 @@ -123,6 +143,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedImports **Since:** PMD 1.0 @@ -141,3 +166,8 @@ import java.io.File; public class Foo {} ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/j2ee.md b/docs/pages/pmd/rules/java/j2ee.md index 6e460f5561..b9a697099f 100644 --- a/docs/pages/pmd/rules/java/j2ee.md +++ b/docs/pages/pmd/rules/java/j2ee.md @@ -35,6 +35,11 @@ public void foo() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoNotUseThreads **Since:** PMD 4.1 @@ -64,6 +69,11 @@ public class OtherThread implements Runnable { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LocalHomeNamingConvention **Since:** PMD 4.0 @@ -94,6 +104,11 @@ public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {} // prope public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-standard name ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LocalInterfaceSessionNamingConvention **Since:** PMD 4.0 @@ -124,6 +139,11 @@ public interface MyLocal extends javax.ejb.EJBLocalObject {} // p public interface MissingProperSuffix extends javax.ejb.EJBLocalObject {} // non-standard name ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MDBAndSessionBeanNamingConvention **Since:** PMD 4.0 @@ -156,6 +176,11 @@ public class SomeBean implements SessionBean{} // proper name public class MissingTheProperSuffix implements SessionBean {} // non-standard name ``` +**Use this rule by referencing it:** +``` xml + +``` + ## RemoteInterfaceNamingConvention **Since:** PMD 4.0 @@ -194,6 +219,11 @@ public interface BadSuffixEJB extends javax.ejb.EJBObject {} public interface BadSuffixBean extends javax.ejb.EJBObject {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## RemoteSessionInterfaceNamingConvention **Since:** PMD 4.0 @@ -224,6 +254,11 @@ public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper na public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standard name ``` +**Use this rule by referencing it:** +``` xml + +``` + ## StaticEJBFieldShouldBeFinal **Since:** PMD 4.1 @@ -267,6 +302,11 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseProperClassLoader **Since:** PMD 3.7 @@ -288,3 +328,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/javabeans.md b/docs/pages/pmd/rules/java/javabeans.md index 1bb0aa7403..8a8a05afd6 100644 --- a/docs/pages/pmd/rules/java/javabeans.md +++ b/docs/pages/pmd/rules/java/javabeans.md @@ -43,6 +43,11 @@ private int getMoreFoo(){ |----|-------------|-----------| |prefix||A variable prefix to skip, i.e., m_| +**Use this rule by referencing it:** +``` xml + +``` + ## MissingSerialVersionUID **Since:** PMD 3.0 @@ -75,3 +80,8 @@ public class Foo implements java.io.Serializable { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/junit.md b/docs/pages/pmd/rules/java/junit.md index 8750d98195..b3d9bc0f40 100644 --- a/docs/pages/pmd/rules/java/junit.md +++ b/docs/pages/pmd/rules/java/junit.md @@ -31,6 +31,11 @@ public class Foo extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnitSpelling **Since:** PMD 1.0 @@ -59,6 +64,11 @@ public class Foo extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnitStaticSuite **Since:** PMD 1.0 @@ -85,6 +95,11 @@ public class Foo extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnitTestContainsTooManyAsserts **Since:** PMD 5.0 @@ -124,6 +139,11 @@ public class MyTestCase extends TestCase { |----|-------------|-----------| |maximumAsserts|1|Maximum number of Asserts in a test method| +**Use this rule by referencing it:** +``` xml + +``` + ## JUnitTestsShouldIncludeAssert **Since:** PMD 2.0 @@ -148,6 +168,11 @@ public class Foo extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifyBooleanAssertion **Since:** PMD 3.6 @@ -187,6 +212,11 @@ public class SimpleTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## TestClassWithoutTestCases **Since:** PMD 3.0 @@ -211,6 +241,11 @@ public class CarTest { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryBooleanAssertion **Since:** PMD 3.0 @@ -246,6 +281,11 @@ public class SimpleTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseAssertEqualsInsteadOfAssertTrue **Since:** PMD 3.1 @@ -276,6 +316,11 @@ public class FooTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseAssertNullInsteadOfAssertTrue **Since:** PMD 3.5 @@ -310,6 +355,11 @@ public class FooTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseAssertSameInsteadOfAssertTrue **Since:** PMD 3.1 @@ -342,6 +392,11 @@ public class FooTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseAssertTrueInsteadOfAssertEquals **Since:** PMD 5.0 @@ -380,3 +435,8 @@ public class MyTestCase extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/logging-jakarta-commons.md b/docs/pages/pmd/rules/java/logging-jakarta-commons.md index 41dcdf068b..6e3473fe19 100644 --- a/docs/pages/pmd/rules/java/logging-jakarta-commons.md +++ b/docs/pages/pmd/rules/java/logging-jakarta-commons.md @@ -51,6 +51,11 @@ public class Test { |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| +**Use this rule by referencing it:** +``` xml + +``` + ## GuardLogStatement **Since:** PMD 5.1.0 @@ -77,6 +82,11 @@ otherwise skip the associate String creation and manipulation. |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| +**Use this rule by referencing it:** +``` xml + +``` + ## ProperLogger **Since:** PMD 3.3 @@ -116,6 +126,11 @@ public class Foo { |----|-------------|-----------| |staticLoggerName|LOG|Name of the static Logger variable| +**Use this rule by referencing it:** +``` xml + +``` + ## UseCorrectExceptionLogging **Since:** PMD 3.2 @@ -150,3 +165,8 @@ public class Main { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/logging-java.md b/docs/pages/pmd/rules/java/logging-java.md index a5f35147ed..20d350c430 100644 --- a/docs/pages/pmd/rules/java/logging-java.md +++ b/docs/pages/pmd/rules/java/logging-java.md @@ -35,6 +35,11 @@ class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## GuardLogStatementJavaUtil **Since:** PMD 5.1.0 @@ -63,6 +68,11 @@ if (log.isLoggable(Level.FINE)) { |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| +**Use this rule by referencing it:** +``` xml + +``` + ## InvalidSlf4jMessageFormat **Since:** PMD 5.5.0 @@ -81,6 +91,11 @@ LOGGER.error("too many args {}", "arg1", "arg2"); LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LoggerIsNotStaticFinal **Since:** PMD 2.0 @@ -108,6 +123,11 @@ public class Foo{ } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MoreThanOneLogger **Since:** PMD 2.0 @@ -129,6 +149,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SystemPrintln **Since:** PMD 2.1 @@ -160,3 +185,8 @@ class Foo{ } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md index 9659247d24..ae8f19c849 100644 --- a/docs/pages/pmd/rules/java/migrating.md +++ b/docs/pages/pmd/rules/java/migrating.md @@ -29,6 +29,11 @@ public class A { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidEnumAsIdentifier **Since:** PMD 3.4 @@ -51,6 +56,11 @@ public class A { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ByteInstantiation **Since:** PMD 4.0 @@ -75,6 +85,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ForLoopCanBeForeach **Since:** PMD 6.0 @@ -106,6 +121,11 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IntegerInstantiation **Since:** PMD 3.5 @@ -131,6 +151,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnit4SuitesShouldUseSuiteAnnotation **Since:** PMD 4.0 @@ -162,6 +187,11 @@ public class GoodTest { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnit4TestShouldUseAfterAnnotation **Since:** PMD 4.0 @@ -192,6 +222,11 @@ public class MyTest2 { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnit4TestShouldUseBeforeAnnotation **Since:** PMD 4.0 @@ -222,6 +257,11 @@ public class MyTest2 { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnit4TestShouldUseTestAnnotation **Since:** PMD 4.0 @@ -251,6 +291,11 @@ public class MyTest { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JUnitUseExpected **Since:** PMD 4.0 @@ -281,6 +326,11 @@ public class MyTest { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LongInstantiation **Since:** PMD 4.0 @@ -306,6 +356,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ReplaceEnumerationWithIterator **Since:** PMD 3.4 @@ -332,6 +387,11 @@ public class Foo implements Enumeration { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ReplaceHashtableWithMap **Since:** PMD 3.4 @@ -354,6 +414,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ReplaceVectorWithList **Since:** PMD 3.4 @@ -376,6 +441,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ShortInstantiation **Since:** PMD 4.0 @@ -401,3 +471,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/naming.md b/docs/pages/pmd/rules/java/naming.md index 6f9dd88cf9..db258a25ae 100644 --- a/docs/pages/pmd/rules/java/naming.md +++ b/docs/pages/pmd/rules/java/naming.md @@ -39,6 +39,11 @@ public abstract class Foo { // should be AbstractFoo |----|-------------|-----------| |strict|true|Also flag classes, that are named Abstract, but are not abstract.| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidDollarSigns **Since:** PMD 1.5 @@ -56,6 +61,11 @@ public class Fo$o { // not a recommended name } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidFieldNameMatchingMethodName **Since:** PMD 3.0 @@ -79,6 +89,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidFieldNameMatchingTypeName **Since:** PMD 3.0 @@ -98,6 +113,11 @@ public class Foo extends Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## BooleanGetMethodName **Since:** PMD 4.0 @@ -132,6 +152,11 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true |----|-------------|-----------| |checkParameterizedMethods|false|Check parameterized methods| +**Use this rule by referencing it:** +``` xml + +``` + ## ClassNamingConventions **Since:** PMD 1.2 @@ -148,6 +173,11 @@ Class names should always begin with an upper case character. public class Foo {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## GenericsNaming **Since:** PMD 4.2.6 @@ -184,6 +214,11 @@ public interface GenericDao { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LongVariable **Since:** PMD 0.3 @@ -216,6 +251,11 @@ public class Something { |----|-------------|-----------| |minimum|17|The variable length reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## MethodNamingConventions **Since:** PMD 1.2 @@ -241,6 +281,11 @@ public class Foo { |----|-------------|-----------| |checkNativeMethods|true|Check native methods| +**Use this rule by referencing it:** +``` xml + +``` + ## MethodWithSameNameAsEnclosingClass **Since:** PMD 1.5 @@ -262,6 +307,11 @@ public class MyClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MisleadingVariableName **Since:** PMD 3.4 @@ -287,6 +337,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoPackage **Since:** PMD 3.3 @@ -307,6 +362,11 @@ public class ClassInDefaultPackage { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## PackageCase **Since:** PMD 3.3 @@ -328,6 +388,11 @@ public class SomeClass { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ShortClassName **Since:** PMD 5.0 @@ -353,6 +418,11 @@ public class Foo { |----|-------------|-----------| |minimum|5|Number of characters that are required as a minimum for a class name.| +**Use this rule by referencing it:** +``` xml + +``` + ## ShortMethodName **Since:** PMD 0.3 @@ -380,6 +450,11 @@ public class ShortMethod { |----|-------------|-----------| |minimum|3|Number of characters that are required as a minimum for a method name.| +**Use this rule by referencing it:** +``` xml + +``` + ## ShortVariable **Since:** PMD 0.3 @@ -418,6 +493,11 @@ public class Something { |----|-------------|-----------| |minimum|3|Number of characters that are required as a minimum for a variable name.| +**Use this rule by referencing it:** +``` xml + +``` + ## SuspiciousConstantFieldName **Since:** PMD 2.0 @@ -445,6 +525,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SuspiciousEqualsMethodName **Since:** PMD 2.0 @@ -492,6 +577,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SuspiciousHashcodeMethodName **Since:** PMD 1.5 @@ -512,6 +602,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## VariableNamingConventions **Since:** PMD 1.2 @@ -551,3 +646,8 @@ public class Foo { |checkLocals|true|Check local variables| |checkMembers|true|Check member variables| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/optimizations.md b/docs/pages/pmd/rules/java/optimizations.md index 93ae39f7e0..a2670e8be4 100644 --- a/docs/pages/pmd/rules/java/optimizations.md +++ b/docs/pages/pmd/rules/java/optimizations.md @@ -27,6 +27,11 @@ String s = "" + 123; // inefficient String t = Integer.toString(456); // preferred approach ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidArrayLoops **Since:** PMD 3.5 @@ -74,6 +79,11 @@ public class Test { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidInstantiatingObjectsInLoops **Since:** PMD 2.2 @@ -96,6 +106,11 @@ public class Something { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## LocalVariableCouldBeFinal **Since:** PMD 2.2 @@ -117,6 +132,11 @@ public class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MethodArgumentCouldBeFinal **Since:** PMD 2.2 @@ -139,6 +159,11 @@ public void foo2 (final String param) { // better, do stuff with param never ass } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## PrematureDeclaration **Since:** PMD 5.0 @@ -166,6 +191,11 @@ public int getLength(String[] strings) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## RedundantFieldInitializer **Since:** PMD 5.0 @@ -201,6 +231,11 @@ public class C { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SimplifyStartsWith **Since:** PMD 3.1 @@ -238,6 +273,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryWrapperObjectCreation **Since:** PMD 3.8 @@ -269,6 +309,11 @@ public int convert(String s) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseArrayListInsteadOfVector **Since:** PMD 3.0 @@ -294,6 +339,11 @@ public class SimpleTest extends TestCase { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseArraysAsList **Since:** PMD 3.5 @@ -352,6 +402,11 @@ public class Test { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseStringBufferForStringAppends **Since:** PMD 3.1 @@ -379,3 +434,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/strictexception.md b/docs/pages/pmd/rules/java/strictexception.md index 764695a6f4..bb3ee1265e 100644 --- a/docs/pages/pmd/rules/java/strictexception.md +++ b/docs/pages/pmd/rules/java/strictexception.md @@ -43,6 +43,11 @@ public class PrimitiveType { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidCatchingNPE **Since:** PMD 1.8 @@ -70,6 +75,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidCatchingThrowable **Since:** PMD 1.2 @@ -93,6 +103,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidLosingExceptionInformation **Since:** PMD 4.2.6 @@ -129,6 +144,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidRethrowingException **Since:** PMD 3.8 @@ -156,6 +176,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidThrowingNewInstanceOfSameException **Since:** PMD 4.2.5 @@ -190,6 +215,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidThrowingNullPointerException **Since:** PMD 1.8 @@ -214,6 +244,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidThrowingRawExceptionTypes **Since:** PMD 1.8 @@ -246,6 +281,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoNotExtendJavaLangError **Since:** PMD 4.0 @@ -265,6 +305,11 @@ Errors are system exceptions. Do not extend them. public class Foo extends Error { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## DoNotThrowExceptionInFinally **Since:** PMD 4.2 @@ -296,6 +341,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ExceptionAsFlowControl **Since:** PMD 1.8 @@ -323,6 +373,11 @@ public void bar() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## SignatureDeclareThrowsException **Since:** PMD 1.2 @@ -341,3 +396,8 @@ public void foo() throws Exception { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/strings.md b/docs/pages/pmd/rules/java/strings.md index ae7f34c3be..085f2a2108 100644 --- a/docs/pages/pmd/rules/java/strings.md +++ b/docs/pages/pmd/rules/java/strings.md @@ -27,6 +27,11 @@ StringBuffer sb = new StringBuffer(); sb.append('a'); // use this instead ``` +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidDuplicateLiterals **Since:** PMD 1.0 @@ -60,6 +65,11 @@ private void buz(String x) {} |minimumLength|3|Minimum string length to check| |skipAnnotations|false|Skip literals within annotations| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidStringBufferField **Since:** PMD 4.2 @@ -81,6 +91,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ConsecutiveAppendsShouldReuse **Since:** PMD 5.1 @@ -106,6 +121,11 @@ StringBuffer buf = new StringBuffer(); buf.append("Hello").append(foo).append("World"); // good ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ConsecutiveLiteralAppends **Since:** PMD 3.5 @@ -130,6 +150,11 @@ buf.append("Hello World"); // good |----|-------------|-----------| |threshold|1|Max consecutive appends| +**Use this rule by referencing it:** +``` xml + +``` + ## InefficientEmptyStringCheck **Since:** PMD 3.6 @@ -155,6 +180,11 @@ public void bar(String string) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## InefficientStringBuffering **Since:** PMD 3.4 @@ -177,6 +207,11 @@ StringBuffer sb = new StringBuffer("tmp = "); sb.append(System.getProperty("java.io.tmpdir")); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## InsufficientStringBufferDeclaration **Since:** PMD 3.6 @@ -201,6 +236,11 @@ StringBuffer good = new StringBuffer(41); good.append("This is a long string, which is pre-sized"); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## StringBufferInstantiationWithChar **Since:** PMD 3.9 @@ -247,6 +287,11 @@ StringBuffer sb3 = new StringBuffer("c"); StringBuilder sb4 = new StringBuilder("c"); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## StringInstantiation **Since:** PMD 1.0 @@ -263,6 +308,11 @@ Avoid instantiating String objects; this is usually unnecessary since they are i private String bar = new String("bar"); // just do a String bar = "bar"; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## StringToString **Since:** PMD 1.0 @@ -282,6 +332,11 @@ private String baz() { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryCaseChange **Since:** PMD 3.3 @@ -300,6 +355,11 @@ boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase() ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseEqualsToCompareStrings **Since:** PMD 4.1 @@ -327,6 +387,11 @@ public boolean test(String s) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseIndexOfChar **Since:** PMD 3.5 @@ -347,6 +412,11 @@ if (s.indexOf("d") {} if (s.indexOf('d') {} ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UselessStringValueOf **Since:** PMD 3.8 @@ -368,6 +438,11 @@ public String convert(int i) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UseStringBufferLength **Since:** PMD 3.4 @@ -389,3 +464,8 @@ if (sb.toString().equals("")) {} // inefficient if (sb.length() == 0) {} // preferred ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/sunsecure.md b/docs/pages/pmd/rules/java/sunsecure.md index bf7d7f2bd7..f373281c62 100644 --- a/docs/pages/pmd/rules/java/sunsecure.md +++ b/docs/pages/pmd/rules/java/sunsecure.md @@ -30,6 +30,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## MethodReturnsInternalArray **Since:** PMD 2.2 @@ -53,3 +58,8 @@ public class SecureSystem { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/unnecessary.md b/docs/pages/pmd/rules/java/unnecessary.md index e41f7ba984..42f194a7ef 100644 --- a/docs/pages/pmd/rules/java/unnecessary.md +++ b/docs/pages/pmd/rules/java/unnecessary.md @@ -28,6 +28,11 @@ public String convert(int x) { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryFinalModifier **Since:** PMD 3.0 @@ -59,6 +64,11 @@ public final class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryModifier **Since:** PMD 1.02 @@ -96,6 +106,11 @@ public class Bar { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnnecessaryReturn **Since:** PMD 1.3 @@ -117,6 +132,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedNullCheckInEquals **Since:** PMD 3.5 @@ -175,6 +195,11 @@ public class Test { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UselessOperationOnImmutable **Since:** PMD 3.5 @@ -203,6 +228,11 @@ class Test { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UselessOverridingMethod **Since:** PMD 3.3 @@ -236,6 +266,11 @@ public Long getId() { |----|-------------|-----------| |ignoreAnnotations|false|Ignore annotations| +**Use this rule by referencing it:** +``` xml + +``` + ## UselessParentheses **Since:** PMD 5.0 @@ -315,6 +350,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UselessQualifiedThis **Since:** PMD 5.4.0 @@ -361,3 +401,8 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/java/unusedcode.md b/docs/pages/pmd/rules/java/unusedcode.md index 0d8305a890..bb87f2152b 100644 --- a/docs/pages/pmd/rules/java/unusedcode.md +++ b/docs/pages/pmd/rules/java/unusedcode.md @@ -33,6 +33,11 @@ public class Foo { |----|-------------|-----------| |checkAll|false|Check all methods, including non-private ones| +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedLocalVariable **Since:** PMD 0.1 @@ -53,6 +58,11 @@ public class Foo { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedPrivateField **Since:** PMD 0.1 @@ -76,6 +86,11 @@ public class Something { } ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedPrivateMethod **Since:** PMD 0.7 @@ -94,3 +109,8 @@ public class Something { } ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/jsp/basic-jsf.md b/docs/pages/pmd/rules/jsp/basic-jsf.md index 4fee12d783..d8104dca9d 100644 --- a/docs/pages/pmd/rules/jsp/basic-jsf.md +++ b/docs/pages/pmd/rules/jsp/basic-jsf.md @@ -33,3 +33,8 @@ Do not nest JSF component custom actions inside a custom action that iterates ov ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/jsp/basic.md b/docs/pages/pmd/rules/jsp/basic.md index 93f30ef763..f1704787d9 100644 --- a/docs/pages/pmd/rules/jsp/basic.md +++ b/docs/pages/pmd/rules/jsp/basic.md @@ -23,6 +23,11 @@ Avoid duplicate import statements inside JSP's. <%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%>/foo\">xxtext ``` +**Use this rule by referencing it:** +``` xml + +``` + ## IframeMissingSrcAttribute **Since:** PMD 3.6 @@ -48,6 +53,11 @@ through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 ``` +**Use this rule by referencing it:** +``` xml + +``` + ## JspEncoding **Since:** PMD 4.0 @@ -76,6 +86,11 @@ Most browsers should be able to interpret the following headers: ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoClassAttribute **Since:** PMD 3.6 @@ -96,6 +111,11 @@ Do not use an attribute called 'class'. Use "styleclass" for CSS styles. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoHtmlComments **Since:** PMD 3.6 @@ -122,6 +142,11 @@ little other purpose. Consider switching to JSP comments. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoInlineScript **Since:** PMD 4.0 @@ -145,6 +170,11 @@ Most browsers should be able to interpret the following headers: ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoInlineStyleInformation **Since:** PMD 3.6 @@ -162,6 +192,11 @@ tags, or attributes like "align='center'".

      text

      ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoJspForward **Since:** PMD 3.6 @@ -180,6 +215,11 @@ Do not do a forward from within a JSP file. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoLongScripts **Since:** PMD 3.6 @@ -218,6 +258,11 @@ onload=calcDays; ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoScriptlets **Since:** PMD 3.6 @@ -247,6 +292,11 @@ response.setHeader("Pragma", "No-cache"); ``` +**Use this rule by referencing it:** +``` xml + +``` + ## NoUnsanitizedJSPExpression **Since:** PMD 5.1.4 @@ -268,3 +318,8 @@ ${fn:escapeXml(expression)} ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/plsql/TomKytesDespair.md b/docs/pages/pmd/rules/plsql/TomKytesDespair.md index 1731f87847..d6f2bbdf6b 100644 --- a/docs/pages/pmd/rules/plsql/TomKytesDespair.md +++ b/docs/pages/pmd/rules/plsql/TomKytesDespair.md @@ -64,3 +64,8 @@ END update_planned_hrs; / ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/plsql/codesize.md b/docs/pages/pmd/rules/plsql/codesize.md index a31cea2cf3..60c525d2e5 100644 --- a/docs/pages/pmd/rules/plsql/codesize.md +++ b/docs/pages/pmd/rules/plsql/codesize.md @@ -147,6 +147,11 @@ END; |showClassesComplexity|true|Add class average violations to the report| |reportLevel|10|Cyclomatic Complexity reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveMethodLength **Since:** PMD 5.1 @@ -179,6 +184,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveObjectLength **Since:** PMD 5.1 @@ -221,6 +231,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessivePackageBodyLength **Since:** PMD 5.1 @@ -263,6 +278,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessivePackageSpecificationLength **Since:** PMD 5.1 @@ -298,6 +318,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveParameterList **Since:** PMD 5.1 @@ -335,6 +360,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveTypeLength **Since:** PMD 5.1 @@ -377,6 +407,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssMethodCount **Since:** PMD 5.1 @@ -408,6 +443,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NcssObjectCount **Since:** PMD 5.1 @@ -441,6 +481,11 @@ CREATE OR REPLACE PACKAGE pkg_ |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NPathComplexity **Since:** PMD 5.1 @@ -498,6 +543,11 @@ END; |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyFields **Since:** PMD 5.1 @@ -527,6 +577,11 @@ END pkg_too_many_fields; |----|-------------|-----------| |maxfields|15|Max allowable fields| +**Use this rule by referencing it:** +``` xml + +``` + ## TooManyMethods **Since:** PMD 5.1 @@ -576,3 +631,8 @@ have more fine grained objects. |----|-------------|-----------| |maxmethods|1|The method count reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/plsql/dates.md b/docs/pages/pmd/rules/plsql/dates.md index 1936db49a1..63e581f4ae 100644 --- a/docs/pages/pmd/rules/plsql/dates.md +++ b/docs/pages/pmd/rules/plsql/dates.md @@ -43,6 +43,11 @@ END date_utilities; / ``` +**Use this rule by referencing it:** +``` xml + +``` + ## TO_DATEWithoutDateFormat **Since:** PMD 5.1 @@ -86,6 +91,11 @@ END date_utilities; / ``` +**Use this rule by referencing it:** +``` xml + +``` + ## TO_TIMESTAMPWithoutDateFormat **Since:** PMD 5.1 @@ -129,3 +139,8 @@ END date_utilities; / ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/plsql/strictsyntax.md b/docs/pages/pmd/rules/plsql/strictsyntax.md index 180694ddf6..6e33ee8efa 100644 --- a/docs/pages/pmd/rules/plsql/strictsyntax.md +++ b/docs/pages/pmd/rules/plsql/strictsyntax.md @@ -42,3 +42,8 @@ end inline_pragma_error; / ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/pom/basic.md b/docs/pages/pmd/rules/pom/basic.md index 1ba49c5ab0..c00904d2de 100644 --- a/docs/pages/pmd/rules/pom/basic.md +++ b/docs/pages/pmd/rules/pom/basic.md @@ -39,6 +39,11 @@ dependency management section, it will not also uses the dependency. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## ProjectVersionAsDependencyVersion **Since:** PMD 5.4 @@ -64,3 +69,8 @@ By far the most common problem is the use of 6.0.0-SNAPSHOT in a BOM or parent P ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/vf/security.md b/docs/pages/pmd/rules/vf/security.md index 946a2501ef..1ed3b4febd 100644 --- a/docs/pages/pmd/rules/vf/security.md +++ b/docs/pages/pmd/rules/vf/security.md @@ -23,6 +23,11 @@ Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. ``` +**Use this rule by referencing it:** +``` xml + +``` + ## VfUnescapeEl **Since:** PMD 5.6.0 @@ -39,3 +44,8 @@ Avoid unescaped user controlled content in EL as it results in XSS. ``` +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/vm/basic.md b/docs/pages/pmd/rules/vm/basic.md index a44ef90fd5..2cdf621585 100644 --- a/docs/pages/pmd/rules/vm/basic.md +++ b/docs/pages/pmd/rules/vm/basic.md @@ -23,6 +23,11 @@ Avoid creating deeply nested if-then statements since they are harder to read an |----|-------------|-----------| |problemDepth|3|The if statement depth reporting threshold| +**Use this rule by referencing it:** +``` xml + +``` + ## AvoidReassigningParameters **Since:** PMD 5.1 @@ -33,6 +38,11 @@ Reassigning values to incoming parameters is not recommended. Use temporary loc **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.AvoidReassigningParametersRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/AvoidReassigningParametersRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## CollapsibleIfStatements **Since:** PMD 5.1 @@ -43,6 +53,11 @@ Sometimes two consecutive 'if' statements can be consolidated by separating thei **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.CollapsibleIfStatementsRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/CollapsibleIfStatementsRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyForeachStmt **Since:** PMD 5.1 @@ -53,6 +68,11 @@ Empty foreach statements should be deleted. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.EmptyForeachStmtRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/EmptyForeachStmtRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## EmptyIfStmt **Since:** PMD 5.1 @@ -63,6 +83,11 @@ Empty if statements should be deleted. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.EmptyIfStmtRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/EmptyIfStmtRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## ExcessiveTemplateLength **Since:** PMD 5.1 @@ -81,6 +106,11 @@ The template is too long. It should be broken up into smaller pieces. |minimum||Minimum reporting threshold| |sigma||Sigma value| +**Use this rule by referencing it:** +``` xml + +``` + ## NoInlineJavaScript **Since:** PMD 5.1 @@ -91,6 +121,11 @@ Avoid inline JavaScript. Import .js files instead. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.NoInlineJavaScriptRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/NoInlineJavaScriptRule.java) +**Use this rule by referencing it:** +``` xml + +``` + ## NoInlineStyles **Since:** PMD 5.1 @@ -103,6 +138,11 @@ Avoid inline styles. Use css classes instead. //Text[matches(@literal, "<[^>]+\s[sS][tT][yY][lL][eE]\s*=")] ``` +**Use this rule by referencing it:** +``` xml + +``` + ## UnusedMacroParameter **Since:** PMD 5.1 @@ -113,3 +153,8 @@ Avoid unused macro parameters. They should be deleted. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.UnusedMacroParameterRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/UnusedMacroParameterRule.java) +**Use this rule by referencing it:** +``` xml + +``` + diff --git a/docs/pages/pmd/rules/xml/basic.md b/docs/pages/pmd/rules/xml/basic.md index a385e12849..f153767559 100644 --- a/docs/pages/pmd/rules/xml/basic.md +++ b/docs/pages/pmd/rules/xml/basic.md @@ -25,3 +25,8 @@ An XML CDATA section begins with a +``` + diff --git a/docs/pages/pmd/rules/xsl/xpath.md b/docs/pages/pmd/rules/xsl/xpath.md index 8c6ab9544a..eda6752a0e 100644 --- a/docs/pages/pmd/rules/xsl/xpath.md +++ b/docs/pages/pmd/rules/xsl/xpath.md @@ -47,6 +47,11 @@ cutting through 100% of the document. |----|-------------|-----------| |checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.| +**Use this rule by referencing it:** +``` xml + +``` + ## UseConcatOnce **Since:** PMD 5.0 @@ -67,3 +72,8 @@ The XPath concat() functions accepts as many arguments as required so you can ha ``` +**Use this rule by referencing it:** +``` xml + +``` +