-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
ASTSwitchStatement.java
128 lines (102 loc) · 3.8 KB
/
ASTSwitchStatement.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.EnumUtils;
import net.sourceforge.pmd.annotation.InternalApi;
/**
* Represents a {@code switch} statement.
*
* <pre>
* SwitchStatement ::= "switch" "(" {@linkplain ASTExpression Expression} ")" "{"
* ( {@linkplain ASTSwitchLabel SwitchLabel} {@linkplain ASTBlockStatement BlockStatement}* )*
* "}"
* </pre>
*/
public class ASTSwitchStatement extends AbstractJavaNode implements Iterable<ASTSwitchLabel> {
@InternalApi
@Deprecated
public ASTSwitchStatement(int id) {
super(id);
}
@InternalApi
@Deprecated
public ASTSwitchStatement(JavaParser p, int id) {
super(p, id);
}
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
/**
* Returns true if this switch has a {@code default} case.
*/
public boolean hasDefaultCase() {
for (ASTSwitchLabel label : this) {
if (label.isDefault()) {
return true;
}
}
return false;
}
/**
* Gets the expression tested by this switch.
* This is the expression between the parentheses.
*/
public ASTExpression getTestedExpression() {
return (ASTExpression) getChild(0);
}
/**
* Returns true if this switch statement tests an expression
* having an enum type and all the constants of this type
* are covered by a switch case. Returns false if the type of
* the tested expression could not be resolved.
*/
public boolean isExhaustiveEnumSwitch() {
ASTExpression expression = getTestedExpression();
if (expression.getType() == null) {
return false;
}
if (Enum.class.isAssignableFrom(expression.getType())) {
@SuppressWarnings("unchecked")
Set<String> constantNames = EnumUtils.getEnumMap((Class<? extends Enum>) expression.getType()).keySet();
for (ASTSwitchLabel label : this) {
// since this is an enum switch, the labels are necessarily
// the simple name of some enum constant.
// descendant can be null for default case
if (label.getFirstDescendantOfType(ASTName.class) != null) {
constantNames.remove(label.getFirstDescendantOfType(ASTName.class).getImage());
}
}
return constantNames.isEmpty();
}
return false;
}
/**
* Returns true if this a switch which uses fallthrough branches
* (old school {@code case label: break;}) and not arrow branches.
* If the switch has no branches, returns false.
*/
public boolean isFallthroughSwitch() {
return getFirstChildOfType(ASTSwitchLabel.class) != null
&& getNumChildren() != 1;
}
@Override
public Iterator<ASTSwitchLabel> iterator() {
List<ASTSwitchLabel> result = new ArrayList<>(findChildrenOfType(ASTSwitchLabel.class));
for (ASTSwitchLabeledBlock labeled : findChildrenOfType(ASTSwitchLabeledBlock.class)) {
result.add((ASTSwitchLabel) labeled.getChild(0));
}
for (ASTSwitchLabeledExpression labeled : findChildrenOfType(ASTSwitchLabeledExpression.class)) {
result.add((ASTSwitchLabel) labeled.getChild(0));
}
for (ASTSwitchLabeledThrowStatement labeled : findChildrenOfType(ASTSwitchLabeledThrowStatement.class)) {
result.add((ASTSwitchLabel) labeled.getChild(0));
}
return result.iterator();
}
}