01 package net.sourceforge.pmd.lang.java.rule.basic;
02
03 import net.sourceforge.pmd.lang.ast.Node;
04 import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
05 import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement;
06 import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
07 import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
08 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
09 import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
10 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
11 import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty;
12
13 public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
14
15 public static final String CHECK_FOR = "for";
16 public static final String CHECK_DO = "do";
17 public static final String CHECK_WHILE = "while";
18
19 private static final String[] ALL_LOOP_TYPES_LABELS = new String[] { CHECK_FOR, CHECK_DO, CHECK_WHILE };
20 private static final String[] ALL_LOOP_TYPES_VALUES = ALL_LOOP_TYPES_LABELS;
21 private static final int[] ALL_LOOP_TYPES_DEFAULTS = new int[] { 0, 1, 2 };
22
23 public static final EnumeratedMultiProperty<String> CHECK_BREAK_LOOP_TYPES = new EnumeratedMultiProperty(
24 "checkBreakLoopTypes", "Check for break statements in loop types", ALL_LOOP_TYPES_LABELS,
25 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 1);
26 public static final EnumeratedMultiProperty<String> CHECK_CONTINUE_LOOP_TYPES = new EnumeratedMultiProperty(
27 "checkContinueLoopTypes", "Check for continue statements in loop types", ALL_LOOP_TYPES_LABELS,
28 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 2);
29 public static final EnumeratedMultiProperty<String> CHECK_RETURN_LOOP_TYPES = new EnumeratedMultiProperty(
30 "checkReturnLoopTypes", "Check for return statements in loop types", ALL_LOOP_TYPES_LABELS,
31 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 3);
32
33 public AvoidBranchingStatementAsLastInLoopRule() {
34 definePropertyDescriptor(CHECK_BREAK_LOOP_TYPES);
35 definePropertyDescriptor(CHECK_CONTINUE_LOOP_TYPES);
36 definePropertyDescriptor(CHECK_RETURN_LOOP_TYPES);
37
38 addRuleChainVisit(ASTBreakStatement.class);
39 addRuleChainVisit(ASTContinueStatement.class);
40 addRuleChainVisit(ASTReturnStatement.class);
41 }
42
43 @Override
44 public Object visit(ASTBreakStatement node, Object data) {
45 return check(CHECK_BREAK_LOOP_TYPES, node, data);
46 }
47
48 @Override
49 public Object visit(ASTContinueStatement node, Object data) {
50 return check(CHECK_CONTINUE_LOOP_TYPES, node, data);
51 }
52
53 @Override
54 public Object visit(ASTReturnStatement node, Object data) {
55 return check(CHECK_RETURN_LOOP_TYPES, node, data);
56 }
57
58 protected Object check(EnumeratedMultiProperty<String> property, Node node, Object data) {
59 Node parent = node.getNthParent(5);
60 if (parent instanceof ASTForStatement) {
61 if (hasPropertyValue(property, CHECK_FOR)) {
62 super.addViolation(data, node);
63 }
64 } else if (parent instanceof ASTWhileStatement) {
65 if (hasPropertyValue(property, CHECK_WHILE)) {
66 super.addViolation(data, node);
67 }
68 } else if (parent instanceof ASTDoStatement) {
69 if (hasPropertyValue(property, CHECK_DO)) {
70 super.addViolation(data, node);
71 }
72 }
73 return data;
74 }
75
76 protected boolean hasPropertyValue(EnumeratedMultiProperty<String> property, String value) {
77 final Object[] values = getProperty(property);
78 for (int i = 0; i < values.length; i++) {
79 if (value.equals(values[i])) {
80 return true;
81 }
82 }
83 return false;
84 }
85 }
|