1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package uk.co.badgersinfoil.metaas.impl.antlr;
20
21 import org.asdt.core.internal.antlr.AS3Parser;
22 import uk.co.badgersinfoil.metaas.impl.ASTUtils;
23 import uk.co.badgersinfoil.metaas.impl.TokenBuilder;
24
25
26
27
28
29
30
31 public class BasicListUpdateDelegate implements TreeTokenListUpdateDelegate {
32
33
34
35 public void addedChild(LinkedListTree parent, LinkedListTree child) {
36 if (isPlaceholder(parent)) {
37 if (isPlaceholder(child)) {
38 throw new IllegalArgumentException("The parent node ("+ASTUtils.tokenName(parent)+") has only a placeholder token, so a child which also has only a placeholder token ("+ASTUtils.tokenName(child)+") can't be added yet");
39 }
40 LinkedListToken placeholder = parent.getStartToken();
41 if (placeholder.getPrev() != null) {
42 placeholder.getPrev().setNext(child.getStartToken());
43 }
44 if (placeholder.getNext() != null) {
45 placeholder.getNext().setPrev(child.getStopToken());
46 }
47 parent.setStartToken(child.getStartToken());
48 parent.setStopToken(child.getStopToken());
49 return;
50 }
51 LinkedListToken stop = findTokenInsertionPointForChildWithinParent(parent, child);
52 if (parent.getStartToken() == null) {
53 parent.setStartToken(child.getStartToken());
54 }
55 if (stop != null) {
56 insertAfter(stop, stop.getNext(),
57 child.getStartToken(), child.getStopToken());
58 }
59 if (child.getStopToken() != null) {
60 parent.setStopToken(child.getStopToken());
61 }
62 }
63
64 private boolean isPlaceholder(LinkedListTree ast) {
65 return ast.getStartToken()==ast.getStopToken()
66 && ast.getStartToken()!=null
67 && ast.getStartToken().getType()==AS3Parser.VIRTUAL_PLACEHOLDER
68 && ((PlaceholderLinkedListToken)ast.getStartToken()).getHeld()==ast;
69 }
70
71 private LinkedListToken findTokenInsertionPointForChildWithinParent(LinkedListTree parent, LinkedListTree child) {
72
73
74 while (parent != null) {
75 if (parent.getChildCount() == 1) {
76
77 if (parent.getStopToken() != null) {
78 return parent.getStopToken();
79 }
80 if (parent.getStartToken() != null) {
81 return parent.getStartToken();
82 }
83 }
84 int index = parent.getIndexOfChild(child);
85 if (index > 0 && index < parent.getChildCount()-1) {
86
87 LinkedListTree precedent = (LinkedListTree)parent.getChild(index-1);
88 if (precedent.getStopToken() == null) {
89
90 return findTokenInsertionPointForChildWithinParent(parent, precedent);
91 }
92 return precedent.getStopToken();
93 }
94 if (index==0 && parent.getStartToken()!=null) {
95 return parent.getStartToken();
96 }
97 if (parent.getStopToken() != null) {
98 return parent.getStopToken();
99 }
100 child = parent;
101 parent = parent.getParent();
102 }
103 return null;
104 }
105
106 public void addedChild(LinkedListTree parent, int index, LinkedListTree child) {
107 LinkedListToken target;
108 LinkedListToken targetNext;
109 if (index == 0) {
110 LinkedListTree prevFirstChild = (LinkedListTree)parent.getChild(1);
111 targetNext = prevFirstChild.getStartToken();
112 target = targetNext.getPrev();
113 if (targetNext == parent.getStartToken()) {
114 parent.setStartToken(child.getStartToken());
115 }
116 } else {
117 target = ((LinkedListTree)parent.getChild(index - 1)).getStopToken();
118 targetNext = target.getNext();
119 }
120 insertAfter(target, targetNext,
121 child.getStartToken(), child.getStopToken());
122 }
123
124 protected static void insertAfter(LinkedListToken target, LinkedListToken targetNext,
125 LinkedListToken start, LinkedListToken stop)
126 {
127 if (target == null && targetNext == null) {
128 throw new IllegalArgumentException("At least one of target and targetNext must be non-null");
129 }
130 if (start != null) {
131
132
133
134
135
136 if (target != null) {
137 target.setNext(start);
138 }
139 stop.setNext(targetNext);
140 if (targetNext != null) {
141 targetNext.setPrev(stop);
142 }
143 }
144 }
145
146 public void appendToken(LinkedListTree parent, LinkedListToken append) {
147 if (parent.getStopToken() == null) {
148 parent.setStartToken(append);
149 parent.setStopToken(append);
150 } else {
151
152 append.setNext(parent.getStopToken().getNext());
153 parent.getStopToken().setNext(append);
154 append.setPrev(parent.getStopToken());
155 parent.setStopToken(append);
156 }
157 }
158
159 public void addToken(LinkedListTree parent, int index, LinkedListToken append) {
160 if (isPlaceholder(parent)) {
161 LinkedListToken placeholder = parent.getStartToken();
162 parent.setStartToken(append);
163 parent.setStopToken(append);
164 placeholder.setPrev(null);
165 placeholder.setNext(null);
166 }
167 if (parent.getStopToken() == null) {
168 parent.setStartToken(append);
169 parent.setStopToken(append);
170 } else {
171 LinkedListToken target;
172 LinkedListToken targetNext;
173 if (index == 0) {
174 targetNext = parent.getStartToken();
175 target = targetNext.getPrev();
176 parent.setStartToken(append);
177 } else if (index == parent.getChildCount()) {
178 target = parent.getStopToken();
179 targetNext = target.getNext();
180 parent.setStopToken(append);
181 } else {
182 LinkedListTree beforeChild = (LinkedListTree)parent.getChild(index);
183 targetNext = beforeChild.getStartToken();
184 target = targetNext.getPrev();
185 }
186 insertAfter(target, targetNext,
187 append, append);
188 }
189 }
190
191 public void deletedChild(LinkedListTree parent, int index, LinkedListTree child) {
192
193
194 LinkedListToken start = child.getStartToken();
195 LinkedListToken stop = child.getStopToken();
196 LinkedListToken startPrev = start.getPrev();
197 LinkedListToken stopNext = stop.getNext();
198
199
200
201
202
203
204 if (parent.getChildCount() == 0
205 && start == parent.getStartToken()
206 && stop == parent.getStopToken())
207 {
208
209
210
211
212
213
214 LinkedListToken placeholder = TokenBuilder.newPlaceholder(parent);
215 startPrev.setNext(placeholder);
216 stopNext.setPrev(placeholder);
217 } else {
218 if (startPrev != null) {
219 startPrev.setNext(stopNext);
220 } else if (stopNext != null) {
221 stopNext.setPrev(startPrev);
222 }
223 if (parent.getStartToken() == start) {
224 parent.setStartToken(stopNext);
225 }
226 if (parent.getStopToken() == stop) {
227 parent.setStopToken(startPrev);
228 }
229 }
230
231
232 start.setPrev(null);
233 stop.setNext(null);
234 }
235
236 public void replacedChild(LinkedListTree tree, int index, LinkedListTree child, LinkedListTree oldChild) {
237
238 if (child.getStartToken() == null) {
239 throw new IllegalArgumentException("No startToken: "+child);
240 }
241 if (child.getStopToken() == null) {
242 throw new IllegalArgumentException("No stopToken: "+child);
243 }
244
245 LinkedListToken oldBefore = findOldBeforeToken(tree, index, child, oldChild);
246 LinkedListToken oldAfter = findOldAfterToken(tree, index, child, oldChild);
247 if (oldBefore != null) {
248 oldBefore.setNext(child.getStartToken());
249 }
250 if (oldAfter != null) {
251 oldAfter.setPrev(child.getStopToken());
252 }
253
254
255 oldChild.getStartToken().setPrev(null);
256 oldChild.getStopToken().setNext(null);
257
258 if (tree.getStartToken() == oldChild.getStartToken()) {
259 tree.setStartToken(child.getStartToken());
260 }
261 if (tree.getStopToken() == oldChild.getStopToken()) {
262 tree.setStopToken(child.getStopToken());
263 }
264 }
265
266 private LinkedListToken findOldBeforeToken(LinkedListTree tree, int index, LinkedListTree child, LinkedListTree oldChild) {
267 LinkedListToken oldStart = oldChild.getStartToken();
268 if (oldStart == null) {
269 throw new IllegalStateException("<"+oldChild+">, child "+index+" of <"+tree+">, had no startToken");
270 }
271 return oldStart.getPrev();
272 }
273
274 private LinkedListToken findOldAfterToken(LinkedListTree tree, int index, LinkedListTree child, LinkedListTree oldChild) {
275 LinkedListToken oldStop = oldChild.getStopToken();
276 if (oldStop == null) {
277 throw new IllegalStateException("<"+oldChild+">, child "+index+" of <"+tree+">, had no stopToken");
278 }
279 return oldStop.getNext();
280 }
281 }