1
2
3
4 package net.sourceforge.pmd.lang.java.rule.basic;
5
6 import net.sourceforge.pmd.PropertySource;
7 import net.sourceforge.pmd.lang.ast.Node;
8 import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
9 import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement;
10 import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
11 import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
12 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
13 import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
14 import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
15 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
16 import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty;
17
18 public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
19
20 public static final String CHECK_FOR = "for";
21 public static final String CHECK_DO = "do";
22 public static final String CHECK_WHILE = "while";
23
24 private static final String[] ALL_LOOP_TYPES_LABELS = new String[] { CHECK_FOR, CHECK_DO, CHECK_WHILE };
25 private static final String[] ALL_LOOP_TYPES_VALUES = ALL_LOOP_TYPES_LABELS;
26 private static final int[] ALL_LOOP_TYPES_DEFAULTS = new int[] { 0, 1, 2 };
27
28 public static final EnumeratedMultiProperty<String> CHECK_BREAK_LOOP_TYPES = new EnumeratedMultiProperty(
29 "checkBreakLoopTypes", "Check for break statements in loop types", ALL_LOOP_TYPES_LABELS,
30 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 1);
31 public static final EnumeratedMultiProperty<String> CHECK_CONTINUE_LOOP_TYPES = new EnumeratedMultiProperty(
32 "checkContinueLoopTypes", "Check for continue statements in loop types", ALL_LOOP_TYPES_LABELS,
33 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 2);
34 public static final EnumeratedMultiProperty<String> CHECK_RETURN_LOOP_TYPES = new EnumeratedMultiProperty(
35 "checkReturnLoopTypes", "Check for return statements in loop types", ALL_LOOP_TYPES_LABELS,
36 ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 3);
37
38 public AvoidBranchingStatementAsLastInLoopRule() {
39 definePropertyDescriptor(CHECK_BREAK_LOOP_TYPES);
40 definePropertyDescriptor(CHECK_CONTINUE_LOOP_TYPES);
41 definePropertyDescriptor(CHECK_RETURN_LOOP_TYPES);
42
43 addRuleChainVisit(ASTBreakStatement.class);
44 addRuleChainVisit(ASTContinueStatement.class);
45 addRuleChainVisit(ASTReturnStatement.class);
46 }
47
48 @Override
49 public Object visit(ASTBreakStatement node, Object data) {
50
51 if (node.getNthParent(3) instanceof ASTSwitchStatement) {
52 return data;
53 }
54 return check(CHECK_BREAK_LOOP_TYPES, node, data);
55 }
56
57 @Override
58 public Object visit(ASTContinueStatement node, Object data) {
59 return check(CHECK_CONTINUE_LOOP_TYPES, node, data);
60 }
61
62 @Override
63 public Object visit(ASTReturnStatement node, Object data) {
64 return check(CHECK_RETURN_LOOP_TYPES, node, data);
65 }
66
67 protected Object check(EnumeratedMultiProperty<String> property, Node node, Object data) {
68 Node parent = node.getNthParent(5);
69 if (parent instanceof ASTForStatement) {
70 if (hasPropertyValue(property, CHECK_FOR)) {
71 super.addViolation(data, node);
72 }
73 } else if (parent instanceof ASTWhileStatement) {
74 if (hasPropertyValue(property, CHECK_WHILE)) {
75 super.addViolation(data, node);
76 }
77 } else if (parent instanceof ASTDoStatement) {
78 if (hasPropertyValue(property, CHECK_DO)) {
79 super.addViolation(data, node);
80 }
81 }
82 return data;
83 }
84
85 protected boolean hasPropertyValue(EnumeratedMultiProperty<String> property, String value) {
86 final Object[] values = getProperty(property);
87 for (int i = 0; i < values.length; i++) {
88 if (value.equals(values[i])) {
89 return true;
90 }
91 }
92 return false;
93 }
94
95 public boolean checksNothing() {
96
97 return getProperty(CHECK_BREAK_LOOP_TYPES).length == 0 &&
98 getProperty(CHECK_CONTINUE_LOOP_TYPES).length == 0 &&
99 getProperty(CHECK_RETURN_LOOP_TYPES).length == 0 ;
100 }
101
102
103
104
105 @Override
106 public String dysfunctionReason() {
107 return checksNothing() ?
108 "All loop types are ignored" :
109 null;
110 }
111 }