Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: lib/compiler/implementation/tree/prettyprint.dart

Issue 10837017: Refactor prettyprinter, keep track of currently opened nodes, (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Pretty-prints Node tree in XML-like format. 6 * Pretty-prints Node tree in XML-like format.
7 * 7 *
8 * TODO(smok): Add main() to run from command-line to print out tree for given 8 * TODO(smok): Add main() to run from command-line to print out tree for given
9 * .dart file. 9 * .dart file.
10 */ 10 */
11 class PrettyPrinter implements Visitor { 11 class PrettyPrinter implements Visitor {
12 12
13 /** String used to represent one level of indent. */ 13 /** String used to represent one level of indent. */
14 static final String INDENT = " "; 14 static final String INDENT = " ";
15 15
16 StringBuffer sb; 16 StringBuffer sb;
17 int depth; 17 int depth;
18 /** Prefix for the type passed to the next [openNode()] call. */ 18 /** Prefix for the type passed to the next [openNode()] call. */
19 String nextTypePrefix; 19 String nextTypePrefix;
20 /** Nodes that were opened with [openNodoe()] calls. */
Anton Muhin 2012/07/31 09:35:27 nit: openNode
Roman 2012/07/31 10:08:34 Done.
21 Link<String> currentNodeTypes;
20 22
21 PrettyPrinter() : sb = new StringBuffer(), depth = 0; 23 PrettyPrinter() :
24 sb = new StringBuffer(),
25 depth = 0,
26 currentNodeTypes = new EmptyLink<String>();
27
28 void pushCurrentNodeType(String nodeType) {
29 currentNodeTypes = currentNodeTypes.prepend(nodeType);
30 }
31
32 String popCurrentNodeType() {
33 assert(!currentNodeTypes.isEmpty());
34 String currentNodeType = currentNodeTypes.head;
35 currentNodeTypes = currentNodeTypes.tail;
36 return currentNodeType;
37 }
22 38
23 /** 39 /**
24 * Adds given string to result string. 40 * Adds given string to result string.
25 */ 41 */
26 void add(SourceString string) { 42 void add(SourceString string) {
27 string.printOn(sb); 43 string.printOn(sb);
28 } 44 }
29 45
46 void addBeginAndEndTokensToParams(Node node, Map params) {
47 params['getBeginToken'] = tokenToStringOrNull(node.getBeginToken());
48 params['getEndToken'] = tokenToStringOrNull(node.getEndToken());
49 }
50
30 /** 51 /**
31 * Adds given node type to result string, increasing current depth by 1. 52 * Adds given node type to result string, increasing current depth by 1.
32 * The method "opens" the node, meaning that all output after calling 53 * The method "opens" the node, meaning that all output after calling
33 * this method and before calling closeNode() will represent contents 54 * this method and before calling closeNode() will represent contents
34 * of given node. 55 * of given node.
35 */ 56 */
36 void openNode(String type, [Map params]) { 57 void openNode(Node node, String type, [Map params]) {
58 if (params == null) params = new Map();
Anton Muhin 2012/07/31 09:35:27 nit: ===
Roman 2012/07/31 10:08:34 Done.
37 addCurrentIndent(); 59 addCurrentIndent();
38 sb.add("<"); 60 sb.add("<");
61 addBeginAndEndTokensToParams(node, params);
39 addTypeWithParams(type, params); 62 addTypeWithParams(type, params);
40 sb.add(">\n"); 63 sb.add(">\n");
64 pushCurrentNodeType(type);
41 depth++; 65 depth++;
42 } 66 }
43 67
44 /** 68 /**
45 * Adds given node to result string, depth is not affected. 69 * Adds given node to result string, depth is not affected.
46 */ 70 */
47 void openAndCloseNode(String type, [Map params]) { 71 void openAndCloseNode(Node node, String type, [Map params]) {
72 if (params == null) params = new Map();
48 addCurrentIndent(); 73 addCurrentIndent();
49 sb.add("<"); 74 sb.add("<");
75 addBeginAndEndTokensToParams(node, params);
50 addTypeWithParams(type, params); 76 addTypeWithParams(type, params);
51 sb.add("/>\n"); 77 sb.add("/>\n");
52 } 78 }
53 79
54 /** 80 /**
55 * Closes given node type, decreasing current depth by 1. 81 * Closes current node type, decreasing current depth by 1.
56 */ 82 */
57 void closeNode(String type, [Map params]) { 83 void closeNode() {
58 depth--; 84 depth--;
59 addCurrentIndent(); 85 addCurrentIndent();
60 sb.add("</"); 86 sb.add("</");
61 addTypeWithParams(type, params); 87 addTypeWithParams(popCurrentNodeType());
62 sb.add(">\n"); 88 sb.add(">\n");
63 } 89 }
64 90
65 void addTypeWithParams(String type, [Map params]) { 91 void addTypeWithParams(String type, [Map params]) {
92 if (params == null) params = new Map();
66 if (nextTypePrefix !== null) { 93 if (nextTypePrefix !== null) {
67 sb.add(nextTypePrefix); 94 sb.add(nextTypePrefix);
68 nextTypePrefix = null; 95 nextTypePrefix = null;
69 } 96 }
70 sb.add("${type}"); 97 sb.add("${type}");
71 if (params != null) { 98 // TODO(smok): Escape doublequotes in values.
72 // TODO(smok): Escape doublequotes in values. 99 params.forEach((k, v) {
73 params.forEach((k, v) { 100 sb.add(' $k=');
74 sb.add(' $k='); 101 if (v !== null) {
75 if (v !== null) { 102 sb.add('"$v"');
76 sb.add('"$v"'); 103 } else {
77 } else { 104 sb.add('null');
78 sb.add('null'); 105 }
79 } 106 });
80 });
81 }
82 } 107 }
83 108
84 void addCurrentIndent() { 109 void addCurrentIndent() {
85 for (int i = 0; i < depth; i++) { 110 for (int i = 0; i < depth; i++) {
86 sb.add(INDENT); 111 sb.add(INDENT);
87 } 112 }
88 } 113 }
89 114
90 /** 115 /**
91 * Pretty-prints given node tree into string. 116 * Pretty-prints given node tree into string.
92 */ 117 */
93 static String prettyPrint(Node node) { 118 static String prettyPrint(Node node) {
94 var p = new PrettyPrinter(); 119 var p = new PrettyPrinter();
95 node.accept(p); 120 node.accept(p);
96 return p.sb.toString(); 121 return p.sb.toString();
97 } 122 }
98 123
99 visitNodeWithChildren(Node node, String type) { 124 visitNodeWithChildren(Node node, String type) {
100 openNode(type); 125 openNode(node, type);
101 node.visitChildren(this); 126 node.visitChildren(this);
102 closeNode(type); 127 closeNode();
103 } 128 }
104 129
105 visitBlock(Block node) { 130 visitBlock(Block node) {
106 visitNodeWithChildren(node, "Block"); 131 visitNodeWithChildren(node, "Block");
107 } 132 }
108 133
109 visitBreakStatement(BreakStatement node) { 134 visitBreakStatement(BreakStatement node) {
110 visitNodeWithChildren(node, "BreakStatement"); 135 visitNodeWithChildren(node, "BreakStatement");
111 } 136 }
112 137
113 visitCascade(Cascade node) { 138 visitCascade(Cascade node) {
114 visitNodeWithChildren(node, "Cascade"); 139 visitNodeWithChildren(node, "Cascade");
115 } 140 }
116 141
117 visitCascadeReceiver(CascadeReceiver node) { 142 visitCascadeReceiver(CascadeReceiver node) {
118 visitNodeWithChildren(node, "CascadeReceiver"); 143 visitNodeWithChildren(node, "CascadeReceiver");
119 } 144 }
120 145
121 visitCaseMatch(CaseMatch node) { 146 visitCaseMatch(CaseMatch node) {
122 visitNodeWithChildren(node, "CaseMatch"); 147 visitNodeWithChildren(node, "CaseMatch");
123 } 148 }
124 149
125 visitCatchBlock(CatchBlock node) { 150 visitCatchBlock(CatchBlock node) {
126 visitNodeWithChildren(node, "CatchBlock"); 151 visitNodeWithChildren(node, "CatchBlock");
127 } 152 }
128 153
129 visitClassNode(ClassNode node) { 154 visitClassNode(ClassNode node) {
130 openNode("ClassNode", { 155 openNode(node, "ClassNode", {
131 "beginToken" : tokenToStringOrNull(node.getBeginToken()),
132 "endToken" : tokenToStringOrNull(node.getEndToken()),
133 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword) 156 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword)
134 }); 157 });
135 visitWithPrefix(node.name, "name:"); 158 visitWithPrefix(node.name, "name:");
136 visitWithPrefix(node.superclass, "superclass:"); 159 visitWithPrefix(node.superclass, "superclass:");
137 visitWithPrefix(node.interfaces, "interfaces:"); 160 visitWithPrefix(node.interfaces, "interfaces:");
138 visitWithPrefix(node.typeParameters, "typeParameters:"); 161 visitWithPrefix(node.typeParameters, "typeParameters:");
139 visitWithPrefix(node.defaultClause, "defaultClause:"); 162 visitWithPrefix(node.defaultClause, "defaultClause:");
140 closeNode("ClassNode"); 163 closeNode();
141 } 164 }
142 165
143 visitConditional(Conditional node) { 166 visitConditional(Conditional node) {
144 visitNodeWithChildren(node, "Conditional"); 167 visitNodeWithChildren(node, "Conditional");
145 } 168 }
146 169
147 visitContinueStatement(ContinueStatement node) { 170 visitContinueStatement(ContinueStatement node) {
148 visitNodeWithChildren(node, "ContinueStatement"); 171 visitNodeWithChildren(node, "ContinueStatement");
149 } 172 }
150 173
(...skipping 15 matching lines...) Expand all
166 189
167 visitForIn(ForIn node) { 190 visitForIn(ForIn node) {
168 visitNodeWithChildren(node, "ForIn"); 191 visitNodeWithChildren(node, "ForIn");
169 } 192 }
170 193
171 visitFunctionDeclaration(FunctionDeclaration node) { 194 visitFunctionDeclaration(FunctionDeclaration node) {
172 visitNodeWithChildren(node, "FunctionDeclaration"); 195 visitNodeWithChildren(node, "FunctionDeclaration");
173 } 196 }
174 197
175 visitFunctionExpression(FunctionExpression node) { 198 visitFunctionExpression(FunctionExpression node) {
176 openNode("FunctionExpression", { 199 openNode(node, "FunctionExpression", {
177 "getOrSet" : tokenToStringOrNull(node.getOrSet) 200 "getOrSet" : tokenToStringOrNull(node.getOrSet)
178 }); 201 });
179 visitWithPrefix(node.modifiers, "modifiers:"); 202 visitWithPrefix(node.modifiers, "modifiers:");
180 visitWithPrefix(node.returnType, "returnType:"); 203 visitWithPrefix(node.returnType, "returnType:");
181 visitWithPrefix(node.name, "name:"); 204 visitWithPrefix(node.name, "name:");
182 visitWithPrefix(node.parameters, "parameters:"); 205 visitWithPrefix(node.parameters, "parameters:");
183 visitWithPrefix(node.initializers, "initializers:"); 206 visitWithPrefix(node.initializers, "initializers:");
184 visitWithPrefix(node.body, "body:"); 207 visitWithPrefix(node.body, "body:");
185 closeNode("FunctionExpression"); 208 closeNode();
186 } 209 }
187 210
188 visitIdentifier(Identifier node) { 211 visitIdentifier(Identifier node) {
189 openAndCloseNode("Identifier", {"token" : node.token.slowToString()}); 212 openAndCloseNode(node, "Identifier", {"token" : node.token.slowToString()});
190 } 213 }
191 214
192 visitIf(If node) { 215 visitIf(If node) {
193 visitNodeWithChildren(node, "If"); 216 visitNodeWithChildren(node, "If");
194 } 217 }
195 218
196 visitLabel(Label node) { 219 visitLabel(Label node) {
197 visitNodeWithChildren(node, "Label"); 220 visitNodeWithChildren(node, "Label");
198 } 221 }
199 222
200 visitLabeledStatement(LabeledStatement node) { 223 visitLabeledStatement(LabeledStatement node) {
201 visitNodeWithChildren(node, "LabeledStatement"); 224 visitNodeWithChildren(node, "LabeledStatement");
202 } 225 }
203 226
204 // Custom. 227 // Custom.
205 visitLiteral(Literal node, String type) { 228 visitLiteral(Literal node, String type) {
206 openAndCloseNode(type, {"value" : node.value.toString()}); 229 openAndCloseNode(node, type, {"value" : node.value.toString()});
207 } 230 }
208 231
209 visitLiteralBool(LiteralBool node) { 232 visitLiteralBool(LiteralBool node) {
210 visitLiteral(node, "LiteralBool"); 233 visitLiteral(node, "LiteralBool");
211 } 234 }
212 235
213 visitLiteralDouble(LiteralDouble node) { 236 visitLiteralDouble(LiteralDouble node) {
214 visitLiteral(node, "LiteralDouble"); 237 visitLiteral(node, "LiteralDouble");
215 } 238 }
216 239
217 visitLiteralInt(LiteralInt node) { 240 visitLiteralInt(LiteralInt node) {
218 visitLiteral(node, "LiteralInt"); 241 visitLiteral(node, "LiteralInt");
219 } 242 }
220 243
221 /** Returns token string value or [null] if token is [null]. */ 244 /** Returns token string value or [null] if token is [null]. */
222 tokenToStringOrNull(Token token) => token === null ? null : token.stringValue; 245 tokenToStringOrNull(Token token) => token === null ? null : token.stringValue;
223 246
224 visitLiteralList(LiteralList node) { 247 visitLiteralList(LiteralList node) {
225 openNode("LiteralList", { 248 openNode(node, "LiteralList", {
226 "constKeyword" : tokenToStringOrNull(node.constKeyword) 249 "constKeyword" : tokenToStringOrNull(node.constKeyword)
227 }); 250 });
228 visitWithPrefix(node.type, "type:"); 251 visitWithPrefix(node.type, "type:");
229 visitWithPrefix(node.elements, "elements:"); 252 visitWithPrefix(node.elements, "elements:");
230 closeNode("LiteralList"); 253 closeNode();
231 } 254 }
232 255
233 visitLiteralMap(LiteralMap node) { 256 visitLiteralMap(LiteralMap node) {
234 visitNodeWithChildren(node, "LiteralMap"); 257 visitNodeWithChildren(node, "LiteralMap");
235 } 258 }
236 259
237 visitLiteralMapEntry(LiteralMapEntry node) { 260 visitLiteralMapEntry(LiteralMapEntry node) {
238 visitNodeWithChildren(node, "LiteralMapEntry"); 261 visitNodeWithChildren(node, "LiteralMapEntry");
239 } 262 }
240 263
241 visitLiteralNull(LiteralNull node) { 264 visitLiteralNull(LiteralNull node) {
242 visitLiteral(node, "LiteralNull"); 265 visitLiteral(node, "LiteralNull");
243 } 266 }
244 267
245 visitLiteralString(LiteralString node) { 268 visitLiteralString(LiteralString node) {
246 openAndCloseNode("LiteralString", {"value" : node.token.slowToString()}); 269 openAndCloseNode(node, "LiteralString",
270 {"value" : node.token.slowToString()});
247 } 271 }
248 272
249 visitModifiers(Modifiers node) { 273 visitModifiers(Modifiers node) {
250 visitNodeWithChildren(node, "Modifiers"); 274 visitNodeWithChildren(node, "Modifiers");
251 } 275 }
252 276
253 visitNamedArgument(NamedArgument node) { 277 visitNamedArgument(NamedArgument node) {
254 visitNodeWithChildren(node, "NamedArgument"); 278 visitNodeWithChildren(node, "NamedArgument");
255 } 279 }
256 280
257 visitNewExpression(NewExpression node) { 281 visitNewExpression(NewExpression node) {
258 visitNodeWithChildren(node, "NewExpression"); 282 visitNodeWithChildren(node, "NewExpression");
259 } 283 }
260 284
261 visitNodeList(NodeList node) { 285 visitNodeList(NodeList node) {
262 var params = { 286 var params = {
263 "delimiter" : 287 "delimiter" :
264 node.delimiter !== null ? node.delimiter.stringValue : null, 288 node.delimiter !== null ? node.delimiter.stringValue : null
265 "beginToken" : tokenToStringOrNull(node.getBeginToken()), 289 };
266 "endToken" : tokenToStringOrNull(node.getEndToken())};
267 if (node.nodes.toList().length == 0) { 290 if (node.nodes.toList().length == 0) {
268 openAndCloseNode("NodeList", params); 291 openAndCloseNode(node, "NodeList", params);
269 } else { 292 } else {
270 openNode("NodeList", params); 293 openNode(node, "NodeList", params);
271 node.visitChildren(this); 294 node.visitChildren(this);
272 closeNode("NodeList"); 295 closeNode();
273 } 296 }
274 } 297 }
275 298
276 visitOperator(Operator node) { 299 visitOperator(Operator node) {
277 openAndCloseNode("Operator", {"value" : node.token.slowToString()}); 300 openAndCloseNode(node, "Operator", {"value" : node.token.slowToString()});
278 } 301 }
279 302
280 visitParenthesizedExpression(ParenthesizedExpression node) { 303 visitParenthesizedExpression(ParenthesizedExpression node) {
281 visitNodeWithChildren(node, "ParenthesizedExpression"); 304 visitNodeWithChildren(node, "ParenthesizedExpression");
282 } 305 }
283 306
284 visitReturn(Return node) { 307 visitReturn(Return node) {
285 var beginToken = node.getBeginToken() !== null 308 openNode(node, "Return");
286 ? node.getBeginToken().stringValue : "null";
287 var endToken = node.getEndToken() !== null
288 ? node.getEndToken().stringValue : "null";
289 openNode("Return", {"beginToken" : beginToken, "endToken" : endToken});
290 visitWithPrefix(node.expression, "expression:"); 309 visitWithPrefix(node.expression, "expression:");
291 closeNode("Return"); 310 closeNode();
292 } 311 }
293 312
294 visitScriptTag(ScriptTag node) { 313 visitScriptTag(ScriptTag node) {
295 visitNodeWithChildren(node, "ScriptTag"); 314 visitNodeWithChildren(node, "ScriptTag");
296 } 315 }
297 316
298 /** Custom helper to visit given node and print its type with prefix. */ 317 /** Custom helper to visit given node and print its type with prefix. */
299 visitWithPrefix(Node node, String prefix) { 318 visitWithPrefix(Node node, String prefix) {
300 if (node === null) return; 319 if (node === null) return;
301 nextTypePrefix = prefix; 320 nextTypePrefix = prefix;
302 node.accept(this); 321 node.accept(this);
303 } 322 }
304 323
305 openSendNodeWithFields(Send node, String type) { 324 openSendNodeWithFields(Send node, String type) {
306 openNode(type, { 325 openNode(node, type, {
307 "isPrefix" : "${node.isPrefix}", 326 "isPrefix" : "${node.isPrefix}",
308 "isPostfix" : "${node.isPostfix}", 327 "isPostfix" : "${node.isPostfix}",
309 "isIndex" : "${node.isIndex}", 328 "isIndex" : "${node.isIndex}"
310 "beginToken" : tokenToStringOrNull(node.getBeginToken()),
311 "endToken" : tokenToStringOrNull(node.getEndToken())
312 }); 329 });
313 visitWithPrefix(node.receiver, "receiver:"); 330 visitWithPrefix(node.receiver, "receiver:");
314 visitWithPrefix(node.selector, "selector:"); 331 visitWithPrefix(node.selector, "selector:");
315 visitWithPrefix(node.argumentsNode, "argumentsNode:"); 332 visitWithPrefix(node.argumentsNode, "argumentsNode:");
316 } 333 }
317 334
318 visitSend(Send node) { 335 visitSend(Send node) {
319 openSendNodeWithFields(node, "Send"); 336 openSendNodeWithFields(node, "Send");
320 closeNode("Send"); 337 closeNode();
321 } 338 }
322 339
323 visitSendSet(SendSet node) { 340 visitSendSet(SendSet node) {
324 openSendNodeWithFields(node, "SendSet"); 341 openSendNodeWithFields(node, "SendSet");
325 visitWithPrefix(node.assignmentOperator, "assignmentOperator:"); 342 visitWithPrefix(node.assignmentOperator, "assignmentOperator:");
326 closeNode("SendSet"); 343 closeNode();
327 } 344 }
328 345
329 visitStringInterpolation(StringInterpolation node) { 346 visitStringInterpolation(StringInterpolation node) {
330 visitNodeWithChildren(node, "StringInterpolation"); 347 visitNodeWithChildren(node, "StringInterpolation");
331 } 348 }
332 349
333 visitStringInterpolationPart(StringInterpolationPart node) { 350 visitStringInterpolationPart(StringInterpolationPart node) {
334 visitNodeWithChildren(node, "StringInterpolationPart"); 351 visitNodeWithChildren(node, "StringInterpolationPart");
335 } 352 }
336 353
(...skipping 11 matching lines...) Expand all
348 365
349 visitThrow(Throw node) { 366 visitThrow(Throw node) {
350 visitNodeWithChildren(node, "Throw"); 367 visitNodeWithChildren(node, "Throw");
351 } 368 }
352 369
353 visitTryStatement(TryStatement node) { 370 visitTryStatement(TryStatement node) {
354 visitNodeWithChildren(node, "TryStatement"); 371 visitNodeWithChildren(node, "TryStatement");
355 } 372 }
356 373
357 visitTypeAnnotation(TypeAnnotation node) { 374 visitTypeAnnotation(TypeAnnotation node) {
358 openNode("TypeAnnotation", { 375 openNode(node, "TypeAnnotation");
359 "beginToken" : tokenToStringOrNull(node.getBeginToken()),
360 "endToken" : tokenToStringOrNull(node.getEndToken())
361 });
362 visitWithPrefix(node.typeName, "typeName:"); 376 visitWithPrefix(node.typeName, "typeName:");
363 visitWithPrefix(node.typeArguments, "typeArguments:"); 377 visitWithPrefix(node.typeArguments, "typeArguments:");
364 closeNode("TypeAnnotation"); 378 closeNode();
365 } 379 }
366 380
367 visitTypedef(Typedef node) { 381 visitTypedef(Typedef node) {
368 visitNodeWithChildren(node, "Typedef"); 382 visitNodeWithChildren(node, "Typedef");
369 } 383 }
370 384
371 visitTypeVariable(TypeVariable node) { 385 visitTypeVariable(TypeVariable node) {
372 visitNodeWithChildren(node, "TypeVariable"); 386 openNode(node, "TypeVariable");
387 visitWithPrefix(node.name, "name:");
388 visitWithPrefix(node.bound, "bound:");
389 closeNode();
373 } 390 }
374 391
375 visitVariableDefinitions(VariableDefinitions node) { 392 visitVariableDefinitions(VariableDefinitions node) {
376 openNode("VariableDefinitions", { 393 openNode(node, "VariableDefinitions");
377 "beginToken" : "${node.getBeginToken().stringValue}",
378 "endToken" : "${node.getEndToken().stringValue}"
379 });
380 visitWithPrefix(node.type, "type:"); 394 visitWithPrefix(node.type, "type:");
381 visitWithPrefix(node.modifiers, "modifiers:"); 395 visitWithPrefix(node.modifiers, "modifiers:");
382 visitWithPrefix(node.definitions, "definitions:"); 396 visitWithPrefix(node.definitions, "definitions:");
383 closeNode("VariableDefinitions"); 397 closeNode();
384 } 398 }
385 399
386 visitWhile(While node) { 400 visitWhile(While node) {
387 visitNodeWithChildren(node, "While"); 401 visitNodeWithChildren(node, "While");
388 } 402 }
389 } 403 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698