KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > js > ast > JsModVisitor


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.js.ast;
17
18 import com.google.gwt.dev.jjs.InternalCompilerException;
19
20 import java.util.ArrayList JavaDoc;
21
22 /**
23  * A visitor for iterating through and modifying an AST.
24  */

25 public class JsModVisitor extends JsVisitor {
26
27   private interface ContextFactory {
28     JsContext create();
29   }
30
31   private class ContextPool extends ArrayList JavaDoc {
32
33     private ContextFactory factory;
34     private int pos = 0;
35
36     public ContextPool(ContextFactory factory) {
37       this.factory = factory;
38     }
39
40     public void release(JsContext ctx) {
41       if (get(--pos) != ctx) {
42         throw new InternalCompilerException(
43             "Tried to release the wrong context");
44       }
45     }
46
47     public JsContext take() {
48       if (pos == size()) {
49         add(factory.create());
50       }
51       return (JsContext) get(pos++);
52     }
53   }
54
55   private class ListContext implements JsContext {
56     private int index;
57     private JsCollection collection;
58     private boolean removed;
59     private boolean replaced;
60
61     public boolean canInsert() {
62       return true;
63     }
64
65     public boolean canRemove() {
66       return true;
67     }
68
69     public void insertAfter(JsNode node) {
70       checkRemoved();
71       collection.addNode(index + 1, node);
72       didChange = true;
73     }
74
75     public void insertBefore(JsNode node) {
76       checkRemoved();
77       collection.addNode(index++, node);
78       didChange = true;
79     }
80
81     public void removeMe() {
82       checkState();
83       collection.removeNode(index--);
84       didChange = removed = true;
85     }
86
87     public void replaceMe(JsNode node) {
88       checkState();
89       checkReplacement(collection.getNode(index), node);
90       collection.setNode(index, node);
91       didChange = replaced = true;
92     }
93
94     protected void doReplace(Class JavaDoc targetClass, JsNode x) {
95       checkState();
96       checkReplacement(collection.getNode(index), x);
97       collection.setNode(index, x);
98       didChange = replaced = true;
99     }
100
101     protected void traverse(JsCollection collection) {
102       this.collection = collection;
103       for (index = 0; index < collection.size(); ++index) {
104         removed = replaced = false;
105         doTraverse(collection.getNode(index), this);
106       }
107     }
108
109     private void checkRemoved() {
110       if (removed) {
111         throw new InternalCompilerException("Node was already removed");
112       }
113     }
114
115     private void checkState() {
116       checkRemoved();
117       if (replaced) {
118         throw new InternalCompilerException("Node was already replaced");
119       }
120     }
121   }
122
123   private class NodeContext implements JsContext {
124     private JsNode node;
125     private boolean replaced;
126
127     public boolean canInsert() {
128       return false;
129     }
130
131     public boolean canRemove() {
132       return false;
133     }
134
135     public void insertAfter(JsNode node) {
136       throw new UnsupportedOperationException JavaDoc();
137     }
138
139     public void insertBefore(JsNode node) {
140       throw new UnsupportedOperationException JavaDoc();
141     }
142
143     public void removeMe() {
144       throw new UnsupportedOperationException JavaDoc();
145     }
146
147     public void replaceMe(JsNode node) {
148       if (replaced) {
149         throw new InternalCompilerException("Node was already replaced");
150       }
151       checkReplacement(this.node, node);
152       this.node = node;
153       didChange = replaced = true;
154     }
155
156     protected JsNode traverse(JsNode node) {
157       this.node = node;
158       replaced = false;
159       doTraverse(node, this);
160       return this.node;
161     }
162   }
163
164   protected static void checkReplacement(JsNode origNode, JsNode newNode) {
165     if (newNode == null) {
166       throw new InternalCompilerException("Cannot replace with null");
167     }
168     if (newNode == origNode) {
169       throw new InternalCompilerException(
170           "The replacement is the same as the original");
171     }
172   }
173
174   protected boolean didChange = false;
175
176   private final ContextPool listContextPool = new ContextPool(
177       new ContextFactory() {
178         public JsContext create() {
179           return new ListContext();
180         }
181       });
182
183   private final ContextPool nodeContextPool = new ContextPool(
184       new ContextFactory() {
185         public JsContext create() {
186           return new NodeContext();
187         }
188       });
189
190   public boolean didChange() {
191     return didChange;
192   }
193
194   protected JsNode doAccept(JsNode node) {
195     NodeContext ctx = (NodeContext) nodeContextPool.take();
196     try {
197       return ctx.traverse(node);
198     } finally {
199       nodeContextPool.release(ctx);
200     }
201   }
202
203   protected void doAccept(JsCollection collection) {
204     NodeContext ctx = (NodeContext) nodeContextPool.take();
205     try {
206       for (int i = 0, c = collection.size(); i < c; ++i) {
207         collection.setNode(i, ctx.traverse(collection.getNode(i)));
208       }
209     } finally {
210       nodeContextPool.release(ctx);
211     }
212   }
213
214   protected void doAcceptWithInsertRemove(JsCollection collection) {
215     ListContext ctx = (ListContext) listContextPool.take();
216     try {
217       ctx.traverse(collection);
218     } finally {
219       listContextPool.release(ctx);
220     }
221   }
222
223 }
224
Popular Tags