OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 part of js_ast; |
| 6 |
| 7 /// Visitor that computes whether two [Node]s are structurally equivalent. |
| 8 class EquivalenceVisitor implements NodeVisitor1<bool, Node> { |
| 9 const EquivalenceVisitor(); |
| 10 |
| 11 /// Called when [node1] and [node2] are not equivalent. |
| 12 /// |
| 13 /// Override this to collect or report information on the inequivalent nodes. |
| 14 bool failAt(Node node1, Node node2) => false; |
| 15 |
| 16 /// Returns whether the non-node values [value1] and [value2] are equivalent. |
| 17 bool testValues(Node node1, Object value1, Node node2, Object value2) => |
| 18 value1 == value2; |
| 19 |
| 20 /// Returns whether the labels [label1] and [label2] are equivalent. |
| 21 bool testLabels(Node node1, String label1, Node node2, String label2) => |
| 22 label1 == label2; |
| 23 |
| 24 bool testNodes(Node node1, Node node2) { |
| 25 if (identical(node1, node2)) return true; |
| 26 if (node1 == null || node2 == null) return failAt(node1, node2); |
| 27 return node1.accept1(this, node2); |
| 28 } |
| 29 |
| 30 bool testNodeLists(List<Node> list1, List<Node> list2) { |
| 31 int index = 0; |
| 32 while (index < list1.length && index < list2.length) { |
| 33 if (!testNodes(list1[index], list2[index])) return false; |
| 34 index++; |
| 35 } |
| 36 if (index < list1.length) { |
| 37 return failAt(list1[index], null); |
| 38 } else if (index < list2.length) { |
| 39 return failAt(list2[index], null); |
| 40 } |
| 41 return true; |
| 42 } |
| 43 |
| 44 @override |
| 45 bool visitProgram(Program node, Node arg) { |
| 46 if (arg is! Program) return failAt(node, arg); |
| 47 Program other = arg; |
| 48 return testNodeLists(node.body, other.body); |
| 49 } |
| 50 |
| 51 @override |
| 52 bool visitInterpolatedDeclaration(InterpolatedDeclaration node, Node arg) { |
| 53 if (arg is! InterpolatedDeclaration) return failAt(node, arg); |
| 54 InterpolatedDeclaration other = arg; |
| 55 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 56 } |
| 57 |
| 58 @override |
| 59 bool visitInterpolatedStatement(InterpolatedStatement node, Node arg) { |
| 60 if (arg is! InterpolatedStatement) return failAt(node, arg); |
| 61 InterpolatedStatement other = arg; |
| 62 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 63 } |
| 64 |
| 65 @override |
| 66 bool visitInterpolatedSelector(InterpolatedSelector node, Node arg) { |
| 67 if (arg is! InterpolatedSelector) return failAt(node, arg); |
| 68 InterpolatedSelector other = arg; |
| 69 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 70 } |
| 71 |
| 72 @override |
| 73 bool visitInterpolatedParameter(InterpolatedParameter node, Node arg) { |
| 74 if (arg is! InterpolatedParameter) return failAt(node, arg); |
| 75 InterpolatedParameter other = arg; |
| 76 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 77 } |
| 78 |
| 79 @override |
| 80 bool visitInterpolatedLiteral(InterpolatedLiteral node, Node arg) { |
| 81 if (arg is! InterpolatedLiteral) return failAt(node, arg); |
| 82 InterpolatedLiteral other = arg; |
| 83 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 84 } |
| 85 |
| 86 @override |
| 87 bool visitInterpolatedExpression(InterpolatedExpression node, Node arg) { |
| 88 if (arg is! InterpolatedExpression) return failAt(node, arg); |
| 89 InterpolatedExpression other = arg; |
| 90 return testValues(node, node.nameOrPosition, other, other.nameOrPosition); |
| 91 } |
| 92 |
| 93 @override |
| 94 bool visitComment(Comment node, Node arg) { |
| 95 if (arg is! Comment) return failAt(node, arg); |
| 96 Comment other = arg; |
| 97 return testValues(node, node.comment, other, other.comment); |
| 98 } |
| 99 |
| 100 @override |
| 101 bool visitAwait(Await node, Node arg) { |
| 102 if (arg is! Await) return failAt(node, arg); |
| 103 Await other = arg; |
| 104 return testNodes(node.expression, other.expression); |
| 105 } |
| 106 |
| 107 @override |
| 108 bool visitRegExpLiteral(RegExpLiteral node, Node arg) { |
| 109 if (arg is! RegExpLiteral) return failAt(node, arg); |
| 110 RegExpLiteral other = arg; |
| 111 return testValues(node, node.pattern, other, other.pattern); |
| 112 } |
| 113 |
| 114 @override |
| 115 bool visitProperty(Property node, Node arg) { |
| 116 if (arg is! Property) return failAt(node, arg); |
| 117 Property other = arg; |
| 118 return testNodes(node.name, other.name) && |
| 119 testNodes(node.value, other.value); |
| 120 } |
| 121 |
| 122 @override |
| 123 bool visitObjectInitializer(ObjectInitializer node, Node arg) { |
| 124 if (arg is! ObjectInitializer) return failAt(node, arg); |
| 125 ObjectInitializer other = arg; |
| 126 return testNodeLists(node.properties, other.properties); |
| 127 } |
| 128 |
| 129 @override |
| 130 bool visitArrayHole(ArrayHole node, Node arg) { |
| 131 if (arg is! ArrayHole) return failAt(node, arg); |
| 132 return true; |
| 133 } |
| 134 |
| 135 @override |
| 136 bool visitArrayInitializer(ArrayInitializer node, Node arg) { |
| 137 if (arg is! ArrayInitializer) return failAt(node, arg); |
| 138 ArrayInitializer other = arg; |
| 139 return testNodeLists(node.elements, other.elements); |
| 140 } |
| 141 |
| 142 @override |
| 143 bool visitName(Name node, Node arg) { |
| 144 if (arg is! Name) return failAt(node, arg); |
| 145 Name other = arg; |
| 146 return testValues(node, node.key, other, other.key); |
| 147 } |
| 148 |
| 149 @override |
| 150 bool visitStringConcatenation(StringConcatenation node, Node arg) { |
| 151 if (arg is! StringConcatenation) return failAt(node, arg); |
| 152 StringConcatenation other = arg; |
| 153 return testNodeLists(node.parts, other.parts); |
| 154 } |
| 155 |
| 156 @override |
| 157 bool visitLiteralNull(LiteralNull node, Node arg) { |
| 158 if (arg is! LiteralNull) return failAt(node, arg); |
| 159 return true; |
| 160 } |
| 161 |
| 162 @override |
| 163 bool visitLiteralNumber(LiteralNumber node, Node arg) { |
| 164 if (arg is! LiteralNumber) return failAt(node, arg); |
| 165 LiteralNumber other = arg; |
| 166 return testValues(node, node.value, other, other.value); |
| 167 } |
| 168 |
| 169 @override |
| 170 bool visitLiteralString(LiteralString node, Node arg) { |
| 171 if (arg is! LiteralString) return failAt(node, arg); |
| 172 LiteralString other = arg; |
| 173 return testValues(node, node.value, other, other.value); |
| 174 } |
| 175 |
| 176 @override |
| 177 bool visitLiteralBool(LiteralBool node, Node arg) { |
| 178 if (arg is! LiteralBool) return failAt(node, arg); |
| 179 LiteralBool other = arg; |
| 180 return testValues(node, node.value, other, other.value); |
| 181 } |
| 182 |
| 183 @override |
| 184 bool visitDeferredString(DeferredString node, Node arg) { |
| 185 if (arg is! DeferredString) return failAt(node, arg); |
| 186 DeferredString other = arg; |
| 187 return testValues(node, node.value, other, other.value); |
| 188 } |
| 189 |
| 190 @override |
| 191 bool visitDeferredNumber(DeferredNumber node, Node arg) { |
| 192 if (arg is! DeferredNumber) return failAt(node, arg); |
| 193 DeferredNumber other = arg; |
| 194 return testValues(node, node.value, other, other.value); |
| 195 } |
| 196 |
| 197 @override |
| 198 bool visitDeferredExpression(DeferredExpression node, Node arg) { |
| 199 if (arg is! DeferredExpression) return failAt(node, arg); |
| 200 DeferredExpression other = arg; |
| 201 return testNodes(node.value, other.value); |
| 202 } |
| 203 |
| 204 @override |
| 205 bool visitFun(Fun node, Node arg) { |
| 206 if (arg is! Fun) return failAt(node, arg); |
| 207 Fun other = arg; |
| 208 return testNodeLists(node.params, other.params) && |
| 209 testNodes(node.body, other.body) && |
| 210 testValues(node, node.asyncModifier, other, other.asyncModifier); |
| 211 } |
| 212 |
| 213 @override |
| 214 bool visitNamedFunction(NamedFunction node, Node arg) { |
| 215 if (arg is! NamedFunction) return failAt(node, arg); |
| 216 NamedFunction other = arg; |
| 217 return testNodes(node.name, other.name) && |
| 218 testNodes(node.function, other.function); |
| 219 } |
| 220 |
| 221 @override |
| 222 bool visitAccess(PropertyAccess node, Node arg) { |
| 223 if (arg is! PropertyAccess) return failAt(node, arg); |
| 224 PropertyAccess other = arg; |
| 225 return testNodes(node.receiver, other.receiver) && |
| 226 testNodes(node.selector, other.selector); |
| 227 } |
| 228 |
| 229 @override |
| 230 bool visitParameter(Parameter node, Node arg) { |
| 231 if (arg is! Parameter) return failAt(node, arg); |
| 232 Parameter other = arg; |
| 233 return testValues(node, node.name, other, other.name); |
| 234 } |
| 235 |
| 236 @override |
| 237 bool visitVariableDeclaration(VariableDeclaration node, Node arg) { |
| 238 if (arg is! VariableDeclaration) return failAt(node, arg); |
| 239 VariableDeclaration other = arg; |
| 240 return testValues(node, node.name, other, other.name) && |
| 241 testValues(node, node.allowRename, other, other.allowRename); |
| 242 } |
| 243 |
| 244 @override |
| 245 bool visitThis(This node, Node arg) { |
| 246 if (arg is! This) return failAt(node, arg); |
| 247 return true; |
| 248 } |
| 249 |
| 250 @override |
| 251 bool visitVariableUse(VariableUse node, Node arg) { |
| 252 if (arg is! VariableUse) return failAt(node, arg); |
| 253 VariableUse other = arg; |
| 254 return testValues(node, node.name, other, other.name); |
| 255 } |
| 256 |
| 257 @override |
| 258 bool visitPostfix(Postfix node, Node arg) { |
| 259 if (arg is! Postfix) return failAt(node, arg); |
| 260 Postfix other = arg; |
| 261 return testValues(node, node.op, other, other.op) && |
| 262 testNodes(node.argument, other.argument); |
| 263 } |
| 264 |
| 265 @override |
| 266 bool visitPrefix(Prefix node, Node arg) { |
| 267 if (arg is! Prefix) return failAt(node, arg); |
| 268 Prefix other = arg; |
| 269 return testValues(node, node.op, other, other.op) && |
| 270 testNodes(node.argument, other.argument); |
| 271 } |
| 272 |
| 273 @override |
| 274 bool visitBinary(Binary node, Node arg) { |
| 275 if (arg is! Binary) return failAt(node, arg); |
| 276 Binary other = arg; |
| 277 return testNodes(node.left, other.left) && |
| 278 testValues(node, node.op, other, other.op) && |
| 279 testNodes(node.right, other.right); |
| 280 } |
| 281 |
| 282 @override |
| 283 bool visitCall(Call node, Node arg) { |
| 284 if (arg is! Call) return failAt(node, arg); |
| 285 Call other = arg; |
| 286 return testNodes(node.target, other.target) && |
| 287 testNodeLists(node.arguments, other.arguments); |
| 288 } |
| 289 |
| 290 @override |
| 291 bool visitNew(New node, Node arg) { |
| 292 if (arg is! New) return failAt(node, arg); |
| 293 New other = arg; |
| 294 return testNodes(node.target, other.target) && |
| 295 testNodeLists(node.arguments, other.arguments); |
| 296 } |
| 297 |
| 298 @override |
| 299 bool visitConditional(Conditional node, Node arg) { |
| 300 if (arg is! Conditional) return failAt(node, arg); |
| 301 Conditional other = arg; |
| 302 return testNodes(node.condition, other.condition) && |
| 303 testNodes(node.then, other.then) && |
| 304 testNodes(node.otherwise, other.otherwise); |
| 305 } |
| 306 |
| 307 @override |
| 308 bool visitVariableInitialization(VariableInitialization node, Node arg) { |
| 309 if (arg is! VariableInitialization) return failAt(node, arg); |
| 310 VariableInitialization other = arg; |
| 311 return testNodes(node.declaration, other.declaration) && |
| 312 testNodes(node.leftHandSide, other.leftHandSide) && |
| 313 testValues(node, node.op, other, other.op) && |
| 314 testNodes(node.value, other.value); |
| 315 } |
| 316 |
| 317 @override |
| 318 bool visitAssignment(Assignment node, Node arg) { |
| 319 if (arg is! Assignment) return failAt(node, arg); |
| 320 Assignment other = arg; |
| 321 return testNodes(node.leftHandSide, other.leftHandSide) && |
| 322 testValues(node, node.op, other, other.op) && |
| 323 testNodes(node.value, other.value); |
| 324 } |
| 325 |
| 326 @override |
| 327 bool visitVariableDeclarationList(VariableDeclarationList node, Node arg) { |
| 328 if (arg is! VariableDeclarationList) return failAt(node, arg); |
| 329 VariableDeclarationList other = arg; |
| 330 return testNodeLists(node.declarations, other.declarations); |
| 331 } |
| 332 |
| 333 @override |
| 334 bool visitLiteralExpression(LiteralExpression node, Node arg) { |
| 335 if (arg is! LiteralExpression) return failAt(node, arg); |
| 336 LiteralExpression other = arg; |
| 337 return testValues(node, node.template, other, other.template) && |
| 338 testNodeLists(node.inputs, other.inputs); |
| 339 } |
| 340 |
| 341 @override |
| 342 bool visitDartYield(DartYield node, Node arg) { |
| 343 if (arg is! DartYield) return failAt(node, arg); |
| 344 DartYield other = arg; |
| 345 return testNodes(node.expression, other.expression) && |
| 346 testValues(node, node.hasStar, other, other.hasStar); |
| 347 } |
| 348 |
| 349 @override |
| 350 bool visitLiteralStatement(LiteralStatement node, Node arg) { |
| 351 if (arg is! LiteralStatement) return failAt(node, arg); |
| 352 LiteralStatement other = arg; |
| 353 return testValues(node, node.code, other, other.code); |
| 354 } |
| 355 |
| 356 @override |
| 357 bool visitLabeledStatement(LabeledStatement node, Node arg) { |
| 358 if (arg is! LabeledStatement) return failAt(node, arg); |
| 359 LabeledStatement other = arg; |
| 360 return testLabels(node, node.label, other, other.label) && |
| 361 testNodes(node.body, other.body); |
| 362 } |
| 363 |
| 364 @override |
| 365 bool visitFunctionDeclaration(FunctionDeclaration node, Node arg) { |
| 366 if (arg is! FunctionDeclaration) return failAt(node, arg); |
| 367 FunctionDeclaration other = arg; |
| 368 return testNodes(node.name, other.name) && |
| 369 testNodes(node.function, other.function); |
| 370 } |
| 371 |
| 372 @override |
| 373 bool visitDefault(Default node, Node arg) { |
| 374 if (arg is! Default) return failAt(node, arg); |
| 375 Default other = arg; |
| 376 return testNodes(node.body, other.body); |
| 377 } |
| 378 |
| 379 @override |
| 380 bool visitCase(Case node, Node arg) { |
| 381 if (arg is! Case) return failAt(node, arg); |
| 382 Case other = arg; |
| 383 return testNodes(node.expression, other.expression) && |
| 384 testNodes(node.body, other.body); |
| 385 } |
| 386 |
| 387 @override |
| 388 bool visitSwitch(Switch node, Node arg) { |
| 389 if (arg is! Switch) return failAt(node, arg); |
| 390 Switch other = arg; |
| 391 return testNodes(node.key, other.key) && |
| 392 testNodeLists(node.cases, other.cases); |
| 393 } |
| 394 |
| 395 @override |
| 396 bool visitCatch(Catch node, Node arg) { |
| 397 if (arg is! Catch) return failAt(node, arg); |
| 398 Catch other = arg; |
| 399 return testNodes(node.declaration, other.declaration) && |
| 400 testNodes(node.body, other.body); |
| 401 } |
| 402 |
| 403 @override |
| 404 bool visitTry(Try node, Node arg) { |
| 405 if (arg is! Try) return failAt(node, arg); |
| 406 Try other = arg; |
| 407 return testNodes(node.body, other.body) && |
| 408 testNodes(node.catchPart, other.catchPart) && |
| 409 testNodes(node.finallyPart, other.finallyPart); |
| 410 } |
| 411 |
| 412 @override |
| 413 bool visitThrow(Throw node, Node arg) { |
| 414 if (arg is! Throw) return failAt(node, arg); |
| 415 Throw other = arg; |
| 416 return testNodes(node.expression, other.expression); |
| 417 } |
| 418 |
| 419 @override |
| 420 bool visitReturn(Return node, Node arg) { |
| 421 if (arg is! Return) return failAt(node, arg); |
| 422 Return other = arg; |
| 423 return testNodes(node.value, other.value); |
| 424 } |
| 425 |
| 426 @override |
| 427 bool visitBreak(Break node, Node arg) { |
| 428 if (arg is! Break) return failAt(node, arg); |
| 429 Break other = arg; |
| 430 return testLabels(node, node.targetLabel, other, other.targetLabel); |
| 431 } |
| 432 |
| 433 @override |
| 434 bool visitContinue(Continue node, Node arg) { |
| 435 if (arg is! Continue) return failAt(node, arg); |
| 436 Continue other = arg; |
| 437 return testLabels(node, node.targetLabel, other, other.targetLabel); |
| 438 } |
| 439 |
| 440 @override |
| 441 bool visitDo(Do node, Node arg) { |
| 442 if (arg is! Do) return failAt(node, arg); |
| 443 Do other = arg; |
| 444 return testNodes(node.condition, other.condition) && |
| 445 testNodes(node.body, other.body); |
| 446 } |
| 447 |
| 448 @override |
| 449 bool visitWhile(While node, Node arg) { |
| 450 if (arg is! While) return failAt(node, arg); |
| 451 While other = arg; |
| 452 return testNodes(node.condition, other.condition) && |
| 453 testNodes(node.body, other.body); |
| 454 } |
| 455 |
| 456 @override |
| 457 bool visitForIn(ForIn node, Node arg) { |
| 458 if (arg is! ForIn) return failAt(node, arg); |
| 459 ForIn other = arg; |
| 460 return testNodes(node.leftHandSide, other.leftHandSide) && |
| 461 testNodes(node.object, other.object) && |
| 462 testNodes(node.body, other.body); |
| 463 } |
| 464 |
| 465 @override |
| 466 bool visitFor(For node, Node arg) { |
| 467 if (arg is! For) return failAt(node, arg); |
| 468 For other = arg; |
| 469 return testNodes(node.init, other.init) && |
| 470 testNodes(node.condition, other.condition) && |
| 471 testNodes(node.update, other.update) && |
| 472 testNodes(node.body, other.body); |
| 473 } |
| 474 |
| 475 @override |
| 476 bool visitIf(If node, Node arg) { |
| 477 if (arg is! If) return failAt(node, arg); |
| 478 If other = arg; |
| 479 return testNodes(node.condition, other.condition) && |
| 480 testNodes(node.then, other.then) && |
| 481 testNodes(node.otherwise, other.otherwise); |
| 482 } |
| 483 |
| 484 @override |
| 485 bool visitEmptyStatement(EmptyStatement node, Node arg) { |
| 486 if (arg is! EmptyStatement) return failAt(node, arg); |
| 487 return true; |
| 488 } |
| 489 |
| 490 @override |
| 491 bool visitExpressionStatement(ExpressionStatement node, Node arg) { |
| 492 if (arg is! ExpressionStatement) return failAt(node, arg); |
| 493 ExpressionStatement other = arg; |
| 494 return testNodes(node.expression, other.expression); |
| 495 } |
| 496 |
| 497 @override |
| 498 bool visitBlock(Block node, Node arg) { |
| 499 if (arg is! Block) return failAt(node, arg); |
| 500 Block other = arg; |
| 501 return testNodeLists(node.statements, other.statements); |
| 502 } |
| 503 } |
OLD | NEW |