1 |
| |
2 |
| |
3 |
| |
4 |
| package net.sourceforge.pmd.dfa; |
5 |
| |
6 |
| import java.util.ArrayList; |
7 |
| import java.util.List; |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| |
21 |
| |
22 |
| |
23 |
| public class SequenceChecker { |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| private static class Status { |
29 |
| public static final int ROOT = -1; |
30 |
| |
31 |
| private List nextSteps = new ArrayList(); |
32 |
| private int type; |
33 |
| private boolean lastStep; |
34 |
| |
35 |
| |
36 |
65
| public Status(int type) {
|
37 |
65
| this(type, false);
|
38 |
| } |
39 |
| |
40 |
100
| public Status(int type, boolean lastStep) {
|
41 |
100
| this.type = type;
|
42 |
100
| this.lastStep = lastStep;
|
43 |
| } |
44 |
| |
45 |
185
| public void addStep(Status type) {
|
46 |
185
| nextSteps.add(type);
|
47 |
| } |
48 |
| |
49 |
315
| public Status step(int type) {
|
50 |
315
| for (int i = 0; i < this.nextSteps.size(); i++) {
|
51 |
537
| if (type == ((Status) nextSteps.get(i)).type) {
|
52 |
284
| return (Status) nextSteps.get(i);
|
53 |
| } |
54 |
| } |
55 |
31
| return null;
|
56 |
| } |
57 |
| |
58 |
505
| public boolean isLastStep() {
|
59 |
505
| return this.lastStep;
|
60 |
| } |
61 |
| |
62 |
63
| public boolean hasMoreSteps() {
|
63 |
63
| return this.nextSteps.size() > 1;
|
64 |
| } |
65 |
| } |
66 |
| |
67 |
| private static Status root; |
68 |
| |
69 |
| static { |
70 |
5
| root = new Status(Status.ROOT);
|
71 |
5
| Status ifNode = new Status(NodeType.IF_EXPR);
|
72 |
5
| Status ifSt = new Status(NodeType.IF_LAST_STATEMENT);
|
73 |
5
| Status ifStWithoutElse = new Status(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, true);
|
74 |
5
| Status elseSt = new Status(NodeType.ELSE_LAST_STATEMENT, true);
|
75 |
5
| Status whileNode = new Status(NodeType.WHILE_EXPR);
|
76 |
5
| Status whileSt = new Status(NodeType.WHILE_LAST_STATEMENT, true);
|
77 |
5
| Status switchNode = new Status(NodeType.SWITCH_START);
|
78 |
5
| Status caseSt = new Status(NodeType.CASE_LAST_STATEMENT);
|
79 |
5
| Status switchDefault = new Status(NodeType.SWITCH_LAST_DEFAULT_STATEMENT);
|
80 |
5
| Status switchEnd = new Status(NodeType.SWITCH_END, true);
|
81 |
| |
82 |
5
| Status forInit = new Status(NodeType.FOR_INIT);
|
83 |
5
| Status forExpr = new Status(NodeType.FOR_EXPR);
|
84 |
5
| Status forUpdate = new Status(NodeType.FOR_UPDATE);
|
85 |
5
| Status forSt = new Status(NodeType.FOR_BEFORE_FIRST_STATEMENT);
|
86 |
5
| Status forEnd = new Status(NodeType.FOR_END, true);
|
87 |
| |
88 |
5
| Status doSt = new Status(NodeType.DO_BEFORE_FIRST_STATEMENT);
|
89 |
5
| Status doExpr = new Status(NodeType.DO_EXPR, true);
|
90 |
| |
91 |
5
| Status labelNode = new Status(NodeType.LABEL_STATEMENT);
|
92 |
5
| Status labelEnd = new Status(NodeType.LABEL_LAST_STATEMENT, true);
|
93 |
| |
94 |
5
| root.addStep(ifNode);
|
95 |
5
| root.addStep(whileNode);
|
96 |
5
| root.addStep(switchNode);
|
97 |
5
| root.addStep(forInit);
|
98 |
5
| root.addStep(forExpr);
|
99 |
5
| root.addStep(forUpdate);
|
100 |
5
| root.addStep(forSt);
|
101 |
5
| root.addStep(doSt);
|
102 |
5
| root.addStep(labelNode);
|
103 |
| |
104 |
5
| ifNode.addStep(ifSt);
|
105 |
5
| ifNode.addStep(ifStWithoutElse);
|
106 |
5
| ifSt.addStep(elseSt);
|
107 |
5
| ifStWithoutElse.addStep(root);
|
108 |
5
| elseSt.addStep(root);
|
109 |
| |
110 |
5
| labelNode.addStep(labelEnd);
|
111 |
5
| labelEnd.addStep(root);
|
112 |
| |
113 |
5
| whileNode.addStep(whileSt);
|
114 |
5
| whileSt.addStep(root);
|
115 |
| |
116 |
5
| switchNode.addStep(caseSt);
|
117 |
5
| switchNode.addStep(switchDefault);
|
118 |
5
| switchNode.addStep(switchEnd);
|
119 |
5
| caseSt.addStep(caseSt);
|
120 |
5
| caseSt.addStep(switchDefault);
|
121 |
5
| caseSt.addStep(switchEnd);
|
122 |
5
| switchDefault.addStep(switchEnd);
|
123 |
5
| switchDefault.addStep(caseSt);
|
124 |
5
| switchEnd.addStep(root);
|
125 |
| |
126 |
5
| forInit.addStep(forExpr);
|
127 |
5
| forInit.addStep(forUpdate);
|
128 |
5
| forInit.addStep(forSt);
|
129 |
5
| forExpr.addStep(forUpdate);
|
130 |
5
| forExpr.addStep(forSt);
|
131 |
5
| forUpdate.addStep(forSt);
|
132 |
5
| forSt.addStep(forEnd);
|
133 |
5
| forEnd.addStep(root);
|
134 |
| |
135 |
5
| doSt.addStep(doExpr);
|
136 |
5
| doExpr.addStep(root);
|
137 |
| } |
138 |
| |
139 |
| private Status aktStatus; |
140 |
| private List bracesList; |
141 |
| |
142 |
| private int firstIndex = -1; |
143 |
| private int lastIndex = -1; |
144 |
| |
145 |
| |
146 |
| |
147 |
| |
148 |
45
| public SequenceChecker(List bracesList) {
|
149 |
45
| this.aktStatus = root;
|
150 |
45
| this.bracesList = bracesList;
|
151 |
| } |
152 |
| |
153 |
| |
154 |
| |
155 |
| |
156 |
| |
157 |
108
| public boolean run() {
|
158 |
108
| this.aktStatus = root;
|
159 |
108
| this.firstIndex = 0;
|
160 |
108
| this.lastIndex = 0;
|
161 |
108
| boolean lookAhead = false;
|
162 |
| |
163 |
108
| for (int i = 0; i < this.bracesList.size(); i++) {
|
164 |
315
| StackObject so = (StackObject) bracesList.get(i);
|
165 |
315
| aktStatus = this.aktStatus.step(so.getType());
|
166 |
| |
167 |
315
| if (aktStatus == null) {
|
168 |
31
| if (lookAhead) {
|
169 |
0
| this.lastIndex = i - 1;
|
170 |
0
| return false;
|
171 |
| } |
172 |
31
| this.aktStatus = root;
|
173 |
31
| this.firstIndex = i;
|
174 |
31
| i--;
|
175 |
31
| continue;
|
176 |
| } else { |
177 |
284
| if (aktStatus.isLastStep() && !aktStatus.hasMoreSteps()) {
|
178 |
63
| this.lastIndex = i;
|
179 |
63
| return false;
|
180 |
221
| } else if (aktStatus.isLastStep() && aktStatus.hasMoreSteps()) {
|
181 |
0
| lookAhead = true;
|
182 |
0
| this.lastIndex = i;
|
183 |
| } |
184 |
| } |
185 |
| } |
186 |
45
| return this.firstIndex == this.lastIndex;
|
187 |
| } |
188 |
| |
189 |
499
| public int getFirstIndex() {
|
190 |
499
| return this.firstIndex;
|
191 |
| } |
192 |
| |
193 |
215
| public int getLastIndex() {
|
194 |
215
| return this.lastIndex;
|
195 |
| } |
196 |
| |
197 |
| } |