Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 // Returns null if no need to rename a node. | |
| 6 typedef String Renamer(Node node); | |
| 7 | |
| 5 class Unparser implements Visitor { | 8 class Unparser implements Visitor { |
| 6 final Renamer renamer; | 9 Renamer rename; |
|
Anton Muhin
2012/08/08 08:27:20
why it's not final any more?
Roman
2012/08/09 05:02:35
Done.
| |
| 7 StringBuffer sb; | 10 StringBuffer sb; |
| 8 | 11 |
| 9 Unparser([this.renamer = const Renamer()]); | 12 Unparser() : this.withRenamer((Node) => null); |
| 13 Unparser.withRenamer(this.rename); | |
| 10 | 14 |
| 11 String unparse(Node node) { | 15 String unparse(Node node) { |
| 12 sb = new StringBuffer(); | 16 sb = new StringBuffer(); |
| 13 visit(node); | 17 visit(node); |
| 14 return sb.toString(); | 18 return sb.toString(); |
| 15 } | 19 } |
| 16 | 20 |
| 17 void add(SourceString string) { | 21 void add(SourceString string) { |
| 18 string.printOn(sb); | 22 string.printOn(sb); |
| 19 } | 23 } |
| 20 | 24 |
| 21 void addToken(Token token) { | 25 void addToken(Token token) { |
| 22 if (token === null) return; | 26 if (token === null) return; |
| 23 add(token.value); | 27 add(token.value); |
| 24 if (token.kind === KEYWORD_TOKEN || token.kind === IDENTIFIER_TOKEN) { | 28 if (token.kind === KEYWORD_TOKEN || token.kind === IDENTIFIER_TOKEN) { |
| 25 sb.add(' '); | 29 sb.add(' '); |
| 26 } | 30 } |
| 27 } | 31 } |
| 28 | 32 |
| 29 visit(Node node) { | 33 visit(Node node) { |
| 30 if (node !== null) node.accept(this); | 34 if (node === null) return; |
| 35 String renamed = rename(node); | |
| 36 if (renamed !== null) { | |
| 37 sb.add(renamed); | |
| 38 } else { | |
| 39 // Fallback. | |
| 40 node.accept(this); | |
| 41 } | |
| 31 } | 42 } |
| 32 | 43 |
| 33 visitBlock(Block node) { | 44 visitBlock(Block node) { |
| 34 visit(node.statements); | 45 visit(node.statements); |
| 35 } | 46 } |
| 36 | 47 |
| 37 visitCascade(Cascade node) { | 48 visitCascade(Cascade node) { |
| 38 visit(node.expression); | 49 visit(node.expression); |
| 39 } | 50 } |
| 40 | 51 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 sb.add(' '); | 110 sb.add(' '); |
| 100 } | 111 } |
| 101 if (node.getOrSet !== null) { | 112 if (node.getOrSet !== null) { |
| 102 add(node.getOrSet.value); | 113 add(node.getOrSet.value); |
| 103 sb.add(' '); | 114 sb.add(' '); |
| 104 } | 115 } |
| 105 // TODO(antonm): that's a workaround as currently FunctionExpression | 116 // TODO(antonm): that's a workaround as currently FunctionExpression |
| 106 // names are modelled with Send and it emits operator[] as only | 117 // names are modelled with Send and it emits operator[] as only |
| 107 // operator, without [] which are expected to be emitted with | 118 // operator, without [] which are expected to be emitted with |
| 108 // arguments. | 119 // arguments. |
| 109 emitName(Identifier name) { | |
| 110 final newName = renamer.renameIdentifier(name); | |
| 111 if (newName === null) { | |
| 112 visit(name); | |
| 113 } else { | |
| 114 sb.add(newName); | |
| 115 } | |
| 116 } | |
| 117 if (node.name is Send) { | 120 if (node.name is Send) { |
| 118 Send send = node.name; | 121 Send send = node.name; |
| 119 assert(send is !SendSet); | 122 assert(send is !SendSet); |
| 120 if (!send.isOperator) { | 123 if (!send.isOperator) { |
| 121 // Looks like a factory method. | 124 // Looks like a factory method. |
| 122 emitName(send.receiver); | 125 visit(send.receiver); |
| 123 sb.add('.'); | 126 sb.add('.'); |
| 124 } else { | 127 } else { |
| 125 visit(send.receiver); | 128 visit(send.receiver); |
| 126 if (send.selector.token.kind === KEYWORD_TOKEN) sb.add(' '); | 129 if (send.selector.token.kind === KEYWORD_TOKEN) sb.add(' '); |
| 127 } | 130 } |
| 128 visit(send.selector); | 131 visit(send.selector); |
| 129 } else { | 132 } else { |
| 130 if (node.name !== null) emitName(node.name); | 133 if (node.name !== null) visit(node.name); |
|
Anton Muhin
2012/08/08 08:27:20
no need in !== null check, but after rebase this d
| |
| 131 } | 134 } |
| 132 visit(node.parameters); | 135 visit(node.parameters); |
| 133 visit(node.initializers); | 136 visit(node.initializers); |
| 134 visit(node.body); | 137 visit(node.body); |
| 135 } | 138 } |
| 136 | 139 |
| 137 visitIdentifier(Identifier node) { | 140 visitIdentifier(Identifier node) { |
| 138 add(node.token.value); | 141 add(node.token.value); |
| 139 } | 142 } |
| 140 | 143 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 } | 233 } |
| 231 | 234 |
| 232 unparseSendPart(Send node) { | 235 unparseSendPart(Send node) { |
| 233 Operator op = node.selector.asOperator(); | 236 Operator op = node.selector.asOperator(); |
| 234 bool spacesNeeded = op !== null && | 237 bool spacesNeeded = op !== null && |
| 235 (op.source.stringValue === 'is' || op.source.stringValue == 'as'); | 238 (op.source.stringValue === 'is' || op.source.stringValue == 'as'); |
| 236 | 239 |
| 237 if (node.isPrefix) { | 240 if (node.isPrefix) { |
| 238 visit(node.selector); | 241 visit(node.selector); |
| 239 } | 242 } |
| 240 if (node.receiver !== null) { | 243 // TODO(smok): Remove ugly hack for library preferences. |
| 244 // Check that renamer does not want to omit receiver at all, | |
| 245 // in that case we don't need spaces or dot. | |
| 246 if (node.receiver !== null && rename(node.receiver) != '') { | |
| 241 visit(node.receiver); | 247 visit(node.receiver); |
| 242 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver(); | 248 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver(); |
| 243 if (asCascadeReceiver !== null) { | 249 if (asCascadeReceiver !== null) { |
| 244 add(asCascadeReceiver.cascadeOperator.value); | 250 add(asCascadeReceiver.cascadeOperator.value); |
| 245 } else if (op === null) { | 251 } else if (op === null) { |
| 246 sb.add('.'); | 252 sb.add('.'); |
| 247 } else if (spacesNeeded) { | 253 } else if (spacesNeeded) { |
| 248 sb.add(' '); | 254 sb.add(' '); |
| 249 } | 255 } |
| 250 } | 256 } |
| 251 if (!node.isPrefix && !node.isIndex) { | 257 if (!node.isPrefix && !node.isIndex) { |
| 252 visit(node.selector); | 258 visit(node.selector); |
| 253 } | 259 } |
| 254 if (spacesNeeded) { | 260 if (spacesNeeded) { |
| 255 sb.add(' '); | 261 sb.add(' '); |
| 256 } | 262 } |
| 257 } | 263 } |
| 258 | 264 |
| 259 unparseSend(Send node) { | 265 unparseSend(Send node) { |
| 260 unparseSendPart(node); | 266 unparseSendPart(node); |
| 261 visit(node.argumentsNode); | 267 visit(node.argumentsNode); |
| 262 } | 268 } |
| 263 | 269 |
| 264 visitSend(Send node) { | 270 visitSend(Send node) { |
| 265 String newMethodName = renamer.renameSendMethod(node); | 271 unparseSendPart(node); |
| 266 if (newMethodName !== null) { | 272 visit(node.argumentsNode); |
| 267 sb.add(newMethodName); | |
| 268 visit(node.argumentsNode); | |
| 269 } else { | |
| 270 unparseSendPart(node); | |
| 271 visit(node.argumentsNode); | |
| 272 } | |
| 273 } | 273 } |
| 274 | 274 |
| 275 /** | 275 /** |
| 276 * Special case for assignments like "list[0] = 1". | 276 * Special case for assignments like "list[0] = 1". |
| 277 */ | 277 */ |
| 278 unparseIndexedSet(SendSet node) { | 278 unparseIndexedSet(SendSet node) { |
| 279 if (node.isPrefix) { | 279 if (node.isPrefix) { |
| 280 add(node.assignmentOperator.token.value); | 280 add(node.assignmentOperator.token.value); |
| 281 } | 281 } |
| 282 visit(node.receiver); | 282 visit(node.receiver); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 311 visitThrow(Throw node) { | 311 visitThrow(Throw node) { |
| 312 add(node.throwToken.value); | 312 add(node.throwToken.value); |
| 313 if (node.expression !== null) { | 313 if (node.expression !== null) { |
| 314 sb.add(' '); | 314 sb.add(' '); |
| 315 visit(node.expression); | 315 visit(node.expression); |
| 316 } | 316 } |
| 317 node.endToken.value.printOn(sb); | 317 node.endToken.value.printOn(sb); |
| 318 } | 318 } |
| 319 | 319 |
| 320 visitTypeAnnotation(TypeAnnotation node) { | 320 visitTypeAnnotation(TypeAnnotation node) { |
| 321 String newName = renamer.renameTypeName(node); | 321 visit(node.typeName); |
|
Anton Muhin
2012/08/08 08:27:20
what about TODO as was discussed before?
Roman
2012/08/09 05:02:35
As discussed, keeping as is.
| |
| 322 if (newName !== null) { | 322 visit(node.typeArguments); |
| 323 sb.add(newName); | |
| 324 visit(node.typeArguments); | |
| 325 } else { | |
| 326 // Fallback to default unparse without renaming. | |
| 327 node.visitChildren(this); | |
| 328 } | |
| 329 } | 323 } |
| 330 | 324 |
| 331 visitTypeVariable(TypeVariable node) { | 325 visitTypeVariable(TypeVariable node) { |
| 332 visit(node.name); | 326 visit(node.name); |
| 333 if (node.bound !== null) { | 327 if (node.bound !== null) { |
| 334 sb.add(' extends '); | 328 sb.add(' extends '); |
| 335 visit(node.bound); | 329 visit(node.bound); |
| 336 } | 330 } |
| 337 } | 331 } |
| 338 | 332 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 sb.add(' '); | 504 sb.add(' '); |
| 511 } | 505 } |
| 512 visit(node.name); | 506 visit(node.name); |
| 513 if (node.typeParameters !== null) { | 507 if (node.typeParameters !== null) { |
| 514 visit(node.typeParameters); | 508 visit(node.typeParameters); |
| 515 } | 509 } |
| 516 visit(node.formals); | 510 visit(node.formals); |
| 517 add(node.endToken.value); | 511 add(node.endToken.value); |
| 518 } | 512 } |
| 519 } | 513 } |
| OLD | NEW |