1 16 package com.google.gwt.dev.js.ast; 17 18 import com.google.gwt.dev.jjs.InternalCompilerException; 19 20 import java.util.ArrayList ; 21 22 25 public class JsModVisitor extends JsVisitor { 26 27 private interface ContextFactory { 28 JsContext create(); 29 } 30 31 private class ContextPool extends ArrayList { 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 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 (); 137 } 138 139 public void insertBefore(JsNode node) { 140 throw new UnsupportedOperationException (); 141 } 142 143 public void removeMe() { 144 throw new UnsupportedOperationException (); 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 |