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 |
48
| public Status(int type) {
|
37 |
48
| this(type, false);
|
38 |
| } |
39 |
| |
40 |
72
| public Status(int type, boolean lastStep) {
|
41 |
72
| this.type = type;
|
42 |
72
| this.lastStep = lastStep;
|
43 |
| } |
44 |
| |
45 |
136
| public void addStep(Status type) {
|
46 |
136
| nextSteps.add(type);
|
47 |
| } |
48 |
| |
49 |
300
| public Status step(int type) {
|
50 |
300
| for (int i = 0; i < this.nextSteps.size(); i++) {
|
51 |
500
| if (type == ((Status) nextSteps.get(i)).type) {
|
52 |
270
| return (Status) nextSteps.get(i);
|
53 |
| } |
54 |
| } |
55 |
30
| return null;
|
56 |
| } |
57 |
| |
58 |
482
| public boolean isLastStep() {
|
59 |
482
| return this.lastStep;
|
60 |
| } |
61 |
| |
62 |
58
| public boolean hasMoreSteps() {
|
63 |
58
| return this.nextSteps.size() > 1;
|
64 |
| } |
65 |
| } |
66 |
| |
67 |
| private static Status root; |
68 |
| |
69 |
| static { |
70 |
4
| root = new Status(Status.ROOT);
|
71 |
4
| Status ifNode = new Status(NodeType.IF_EXPR);
|
72 |
4
| Status ifSt = new Status(NodeType.IF_LAST_STATEMENT);
|
73 |
4
| Status ifStWithoutElse = new Status(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, true);
|
74 |
4
| Status elseSt = new Status(NodeType.ELSE_LAST_STATEMENT, true);
|
75 |
4
| Status whileNode = new Status(NodeType.WHILE_EXPR);
|
76 |
4
| Status whileSt = new Status(NodeType.WHILE_LAST_STATEMENT, true);
|
77 |
4
| Status switchNode = new Status(NodeType.SWITCH_START);
|
78 |
4
| Status caseSt = new Status(NodeType.CASE_LAST_STATEMENT);
|
79 |
4
| Status switchDefault = new Status(NodeType.SWITCH_LAST_DEFAULT_STATEMENT);
|
80 |
4
| Status switchEnd = new Status(NodeType.SWITCH_END, true);
|
81 |
| |
82 |
4
| Status forInit = new Status(NodeType.FOR_INIT);
|
83 |
4
| Status forExpr = new Status(NodeType.FOR_EXPR);
|
84 |
4
| Status forUpdate = new Status(NodeType.FOR_UPDATE);
|
85 |
4
| Status forSt = new Status(NodeType.FOR_BEFORE_FIRST_STATEMENT);
|
86 |
4
| Status forEnd = new Status(NodeType.FOR_END, true);
|
87 |
| |
88 |
4
| Status doSt = new Status(NodeType.DO_BEFORE_FIRST_STATEMENT);
|
89 |
4
| Status doExpr = new Status(NodeType.DO_EXPR, true);
|
90 |
| |
91 |
4
| root.addStep(ifNode);
|
92 |
4
| root.addStep(whileNode);
|
93 |
4
| root.addStep(switchNode);
|
94 |
4
| root.addStep(forInit);
|
95 |
4
| root.addStep(forExpr);
|
96 |
4
| root.addStep(forUpdate);
|
97 |
4
| root.addStep(forSt);
|
98 |
4
| root.addStep(doSt);
|
99 |
| |
100 |
4
| ifNode.addStep(ifSt);
|
101 |
4
| ifNode.addStep(ifStWithoutElse);
|
102 |
4
| ifSt.addStep(elseSt);
|
103 |
4
| ifStWithoutElse.addStep(root);
|
104 |
4
| elseSt.addStep(root);
|
105 |
| |
106 |
4
| whileNode.addStep(whileSt);
|
107 |
4
| whileSt.addStep(root);
|
108 |
| |
109 |
4
| switchNode.addStep(caseSt);
|
110 |
4
| switchNode.addStep(switchDefault);
|
111 |
4
| switchNode.addStep(switchEnd);
|
112 |
4
| caseSt.addStep(caseSt);
|
113 |
4
| caseSt.addStep(switchDefault);
|
114 |
4
| caseSt.addStep(switchEnd);
|
115 |
4
| switchDefault.addStep(switchEnd);
|
116 |
4
| switchDefault.addStep(caseSt);
|
117 |
4
| switchEnd.addStep(root);
|
118 |
| |
119 |
4
| forInit.addStep(forExpr);
|
120 |
4
| forInit.addStep(forUpdate);
|
121 |
4
| forInit.addStep(forSt);
|
122 |
4
| forExpr.addStep(forUpdate);
|
123 |
4
| forExpr.addStep(forSt);
|
124 |
4
| forUpdate.addStep(forSt);
|
125 |
4
| forSt.addStep(forEnd);
|
126 |
4
| forEnd.addStep(root);
|
127 |
| |
128 |
4
| doSt.addStep(doExpr);
|
129 |
4
| doExpr.addStep(root);
|
130 |
| } |
131 |
| |
132 |
| private Status aktStatus; |
133 |
| private List bracesList; |
134 |
| |
135 |
| private int firstIndex = -1; |
136 |
| private int lastIndex = -1; |
137 |
| |
138 |
| |
139 |
| |
140 |
| |
141 |
40
| public SequenceChecker(List bracesList) {
|
142 |
40
| this.aktStatus = root;
|
143 |
40
| this.bracesList = bracesList;
|
144 |
| } |
145 |
| |
146 |
| |
147 |
| |
148 |
| |
149 |
| |
150 |
98
| public boolean run() {
|
151 |
98
| this.aktStatus = root;
|
152 |
98
| this.firstIndex = 0;
|
153 |
98
| this.lastIndex = 0;
|
154 |
98
| boolean lookAhead = false;
|
155 |
| |
156 |
98
| for (int i = 0; i < this.bracesList.size(); i++) {
|
157 |
300
| StackObject so = (StackObject) bracesList.get(i);
|
158 |
300
| aktStatus = this.aktStatus.step(so.getType());
|
159 |
| |
160 |
300
| if (aktStatus == null) {
|
161 |
30
| if (lookAhead) {
|
162 |
0
| this.lastIndex = i - 1;
|
163 |
0
| return false;
|
164 |
| } |
165 |
30
| this.aktStatus = root;
|
166 |
30
| this.firstIndex = i;
|
167 |
30
| i--;
|
168 |
30
| continue;
|
169 |
| } else { |
170 |
270
| if (aktStatus.isLastStep() && !aktStatus.hasMoreSteps()) {
|
171 |
58
| this.lastIndex = i;
|
172 |
58
| return false;
|
173 |
212
| } else if (aktStatus.isLastStep() && aktStatus.hasMoreSteps()) {
|
174 |
0
| lookAhead = true;
|
175 |
0
| this.lastIndex = i;
|
176 |
| } |
177 |
| } |
178 |
| } |
179 |
40
| return this.firstIndex == this.lastIndex;
|
180 |
| } |
181 |
| |
182 |
464
| public int getFirstIndex() {
|
183 |
464
| return this.firstIndex;
|
184 |
| } |
185 |
| |
186 |
198
| public int getLastIndex() {
|
187 |
198
| return this.lastIndex;
|
188 |
| } |
189 |
| |
190 |
| } |