| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 part of dart2js.semantics_visitor; | 5 part of dart2js.semantics_visitor; |
| 6 | 6 |
| 7 enum SendStructureKind { | 7 enum SendStructureKind { |
| 8 GET, | 8 GET, |
| 9 SET, | 9 SET, |
| 10 INVOKE, | 10 INVOKE, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 POSTFIX, | 21 POSTFIX, |
| 22 INDEX_PREFIX, | 22 INDEX_PREFIX, |
| 23 INDEX_POSTFIX, | 23 INDEX_POSTFIX, |
| 24 } | 24 } |
| 25 | 25 |
| 26 abstract class SendResolverMixin { | 26 abstract class SendResolverMixin { |
| 27 TreeElements get elements; | 27 TreeElements get elements; |
| 28 | 28 |
| 29 internalError(Spannable spannable, String message); | 29 internalError(Spannable spannable, String message); |
| 30 | 30 |
| 31 AccessSemantics handleStaticallyResolvedAccess(Send node, | 31 AccessSemantics handleCompoundErroneousSetterAccess( |
| 32 Element element, | 32 Send node, |
| 33 Element getter) { | 33 Element setter, |
| 34 Element getter) { |
| 35 assert(invariant(node, Elements.isUnresolved(setter), |
| 36 message: "Unexpected erreneous compound setter: $setter.")); |
| 37 if (getter.isStatic) { |
| 38 if (getter.isGetter) { |
| 39 return new CompoundAccessSemantics( |
| 40 CompoundAccessKind.UNRESOLVED_STATIC_SETTER, getter, setter); |
| 41 } else if (getter.isField) { |
| 42 // TODO(johnniwinther): Handle const field separately. |
| 43 assert(invariant(node, getter.isFinal || getter.isConst, |
| 44 message: "Field expected to be final or const.")); |
| 45 return new StaticAccess.staticFinalField(getter); |
| 46 } else if (getter.isFunction) { |
| 47 return new StaticAccess.staticMethod(getter); |
| 48 } else { |
| 49 return internalError(node, |
| 50 "Unexpected erroneous static compound: getter=$getter"); |
| 51 } |
| 52 } else if (getter.isTopLevel) { |
| 53 if (getter.isGetter) { |
| 54 return new CompoundAccessSemantics( |
| 55 CompoundAccessKind.UNRESOLVED_TOPLEVEL_SETTER, getter, setter); |
| 56 } else if (getter.isField) { |
| 57 // TODO(johnniwinther): Handle const field separately. |
| 58 assert(invariant(node, getter.isFinal || getter.isConst, |
| 59 message: "Field expected to be final or const.")); |
| 60 return new StaticAccess.topLevelFinalField(getter); |
| 61 } else if (getter.isFunction) { |
| 62 return new StaticAccess.topLevelMethod(getter); |
| 63 } else { |
| 64 return internalError(node, |
| 65 "Unexpected erroneous top level compound: getter=$getter"); |
| 66 } |
| 67 } else if (getter.isParameter) { |
| 68 assert(invariant(node, getter.isFinal, |
| 69 message: "Parameter expected to be final.")); |
| 70 return new StaticAccess.finalParameter(getter); |
| 71 } else if (getter.isLocal) { |
| 72 if (getter.isVariable) { |
| 73 // TODO(johnniwinther): Handle const variable separately. |
| 74 assert(invariant(node, getter.isFinal || getter.isConst, |
| 75 message: "Variable expected to be final or const.")); |
| 76 return new StaticAccess.finalLocalVariable(getter); |
| 77 } else if (getter.isFunction) { |
| 78 return new StaticAccess.localFunction(getter); |
| 79 } else { |
| 80 return internalError(node, |
| 81 "Unexpected erroneous local compound: getter=$getter"); |
| 82 } |
| 83 } else if (getter.isErroneous) { |
| 84 return new StaticAccess.unresolved(getter); |
| 85 } else { |
| 86 return internalError(node, |
| 87 "Unexpected erroneous compound: getter=$getter"); |
| 88 } |
| 89 } |
| 90 |
| 91 AccessSemantics handleStaticallyResolvedAccess( |
| 92 Send node, |
| 93 Element element, |
| 94 Element getter, |
| 95 {bool isCompound}) { |
| 96 if (element == null) { |
| 97 assert(invariant(node, isCompound, message: |
| 98 "Non-compound static access without element.")); |
| 99 assert(invariant(node, getter != null, message: |
| 100 "Compound static access without element.")); |
| 101 return handleCompoundErroneousSetterAccess(node, element, getter); |
| 102 } |
| 34 if (element.isErroneous) { | 103 if (element.isErroneous) { |
| 104 if (isCompound) { |
| 105 return handleCompoundErroneousSetterAccess(node, element, getter); |
| 106 } |
| 35 return new StaticAccess.unresolved(element); | 107 return new StaticAccess.unresolved(element); |
| 36 } else if (element.isParameter) { | 108 } else if (element.isParameter) { |
| 37 return new StaticAccess.parameter(element); | 109 return new StaticAccess.parameter(element); |
| 38 } else if (element.isLocal) { | 110 } else if (element.isLocal) { |
| 39 if (element.isFunction) { | 111 if (element.isFunction) { |
| 40 return new StaticAccess.localFunction(element); | 112 return new StaticAccess.localFunction(element); |
| 41 } else { | 113 } else { |
| 42 return new StaticAccess.localVariable(element); | 114 return new StaticAccess.localVariable(element); |
| 43 } | 115 } |
| 44 } else if (element.isStatic) { | 116 } else if (element.isStatic) { |
| 45 if (element.isField) { | 117 if (element.isField) { |
| 118 if (element.isFinal || element.isConst) { |
| 119 // TODO(johnniwinther): Handle const field separately. |
| 120 return new StaticAccess.staticFinalField(element); |
| 121 } |
| 46 return new StaticAccess.staticField(element); | 122 return new StaticAccess.staticField(element); |
| 47 } else if (element.isGetter) { | 123 } else if (element.isGetter) { |
| 124 if (isCompound) { |
| 125 return new CompoundAccessSemantics( |
| 126 CompoundAccessKind.UNRESOLVED_STATIC_SETTER, element, null); |
| 127 } |
| 48 return new StaticAccess.staticGetter(element); | 128 return new StaticAccess.staticGetter(element); |
| 49 } else if (element.isSetter) { | 129 } else if (element.isSetter) { |
| 50 if (getter != null) { | 130 if (getter != null) { |
| 51 CompoundAccessKind accessKind; | 131 CompoundAccessKind accessKind; |
| 52 if (getter.isGetter) { | 132 if (getter.isErroneous) { |
| 133 accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER; |
| 134 } else if (getter.isAbstractField) { |
| 135 AbstractFieldElement abstractField = getter; |
| 136 if (abstractField.getter == null) { |
| 137 accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER; |
| 138 } else { |
| 139 // TODO(johnniwinther): This might be dead code. |
| 140 getter = abstractField.getter; |
| 141 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; |
| 142 } |
| 143 } else if (getter.isGetter) { |
| 53 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; | 144 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; |
| 54 } else { | 145 } else { |
| 55 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; | 146 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; |
| 56 } | 147 } |
| 57 return new CompoundAccessSemantics( | 148 return new CompoundAccessSemantics( |
| 58 accessKind, getter, element); | 149 accessKind, getter, element); |
| 59 } else { | 150 } else { |
| 60 return new StaticAccess.staticSetter(element); | 151 return new StaticAccess.staticSetter(element); |
| 61 } | 152 } |
| 62 } else { | 153 } else { |
| 63 return new StaticAccess.staticMethod(element); | 154 return new StaticAccess.staticMethod(element); |
| 64 } | 155 } |
| 65 } else if (element.isTopLevel) { | 156 } else if (element.isTopLevel) { |
| 66 if (element.isField) { | 157 if (element.isField) { |
| 158 if (element.isFinal || element.isConst) { |
| 159 // TODO(johnniwinther): Handle const field separately. |
| 160 return new StaticAccess.topLevelFinalField(element); |
| 161 } |
| 67 return new StaticAccess.topLevelField(element); | 162 return new StaticAccess.topLevelField(element); |
| 68 } else if (element.isGetter) { | 163 } else if (element.isGetter) { |
| 69 return new StaticAccess.topLevelGetter(element); | 164 return new StaticAccess.topLevelGetter(element); |
| 70 } else if (element.isSetter) { | 165 } else if (element.isSetter) { |
| 71 if (getter != null) { | 166 if (getter != null) { |
| 72 CompoundAccessKind accessKind; | 167 CompoundAccessKind accessKind; |
| 73 if (getter.isGetter) { | 168 if (getter.isErroneous) { |
| 169 accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER; |
| 170 } else if (getter.isAbstractField) { |
| 171 AbstractFieldElement abstractField = getter; |
| 172 if (abstractField.getter == null) { |
| 173 accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER; |
| 174 } else { |
| 175 // TODO(johnniwinther): This might be dead code. |
| 176 getter = abstractField.getter; |
| 177 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; |
| 178 } |
| 179 } else if (getter.isGetter) { |
| 74 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; | 180 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; |
| 75 } else { | 181 } else { |
| 76 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; | 182 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; |
| 77 } | 183 } |
| 78 return new CompoundAccessSemantics( | 184 return new CompoundAccessSemantics( |
| 79 accessKind, getter, element); | 185 accessKind, getter, element); |
| 80 } else { | 186 } else { |
| 81 return new StaticAccess.topLevelSetter(element); | 187 return new StaticAccess.topLevelSetter(element); |
| 82 } | 188 } |
| 83 } else { | 189 } else { |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 return new ConstantAccess.dynamicTypeLiteral(constant); | 443 return new ConstantAccess.dynamicTypeLiteral(constant); |
| 338 default: | 444 default: |
| 339 return internalError(node, "Unexpected type literal type: $dartType"); | 445 return internalError(node, "Unexpected type literal type: $dartType"); |
| 340 } | 446 } |
| 341 } else if (node.isSuperCall) { | 447 } else if (node.isSuperCall) { |
| 342 if (Elements.isUnresolved(element)) { | 448 if (Elements.isUnresolved(element)) { |
| 343 if (isCompound) { | 449 if (isCompound) { |
| 344 if (Elements.isUnresolved(getter)) { | 450 if (Elements.isUnresolved(getter)) { |
| 345 // TODO(johnniwinther): Ensure that [getter] is not null. This | 451 // TODO(johnniwinther): Ensure that [getter] is not null. This |
| 346 // happens in the case of missing super getter. | 452 // happens in the case of missing super getter. |
| 347 return new CompoundAccessSemantics( | 453 if (node.isIndex) { |
| 348 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 454 return new CompoundAccessSemantics( |
| 455 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 456 } else { |
| 457 return new StaticAccess.unresolvedSuper(element); |
| 458 } |
| 459 } else if (getter.isField) { |
| 460 assert(invariant(node, getter.isFinal, |
| 461 message: "Super field expected to be final.")); |
| 462 return new StaticAccess.superFinalField(getter); |
| 463 } else if (getter.isFunction) { |
| 464 if (node.isIndex) { |
| 465 return new CompoundAccessSemantics( |
| 466 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 467 } else { |
| 468 return new StaticAccess.superMethod(getter); |
| 469 } |
| 349 } else { | 470 } else { |
| 350 return new CompoundAccessSemantics( | 471 return new CompoundAccessSemantics( |
| 351 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); | 472 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 352 } | 473 } |
| 353 } else { | 474 } else { |
| 354 return new StaticAccess.unresolvedSuper(element); | 475 return new StaticAccess.unresolvedSuper(element); |
| 355 } | 476 } |
| 356 } else if (isCompound && Elements.isUnresolved(getter)) { | 477 } else if (isCompound && Elements.isUnresolved(getter)) { |
| 357 // TODO(johnniwinther): Ensure that [getter] is not null. This happens | 478 // TODO(johnniwinther): Ensure that [getter] is not null. This happens |
| 358 // in the case of missing super getter. | 479 // in the case of missing super getter. |
| 359 return new CompoundAccessSemantics( | 480 return new CompoundAccessSemantics( |
| 360 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 481 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 361 } else if (element.isField) { | 482 } else if (element.isField) { |
| 362 if (getter != null && getter != element) { | 483 if (getter != null && getter != element) { |
| 363 CompoundAccessKind accessKind; | 484 CompoundAccessKind accessKind; |
| 364 if (getter.isField) { | 485 if (getter.isField) { |
| 365 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; | 486 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; |
| 366 } else if (getter.isGetter) { | 487 } else if (getter.isGetter) { |
| 367 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; | 488 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; |
| 368 } else { | 489 } else { |
| 369 return internalError(node, | 490 return internalError(node, |
| 370 "Unsupported super call: $node : $element/$getter."); | 491 "Unsupported super call: $node : $element/$getter."); |
| 371 } | 492 } |
| 372 return new CompoundAccessSemantics(accessKind, getter, element); | 493 return new CompoundAccessSemantics(accessKind, getter, element); |
| 494 } else if (element.isFinal) { |
| 495 return new StaticAccess.superFinalField(element); |
| 373 } | 496 } |
| 374 return new StaticAccess.superField(element); | 497 return new StaticAccess.superField(element); |
| 375 } else if (element.isGetter) { | 498 } else if (element.isGetter) { |
| 376 return new StaticAccess.superGetter(element); | 499 return new StaticAccess.superGetter(element); |
| 377 } else if (element.isSetter) { | 500 } else if (element.isSetter) { |
| 378 if (getter != null) { | 501 if (getter != null) { |
| 379 CompoundAccessKind accessKind; | 502 CompoundAccessKind accessKind; |
| 380 if (getter.isField) { | 503 if (getter.isField) { |
| 381 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; | 504 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; |
| 382 } else if (getter.isGetter) { | 505 } else if (getter.isGetter) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 398 } else if (Elements.isClosureSend(node, element)) { | 521 } else if (Elements.isClosureSend(node, element)) { |
| 399 if (element == null) { | 522 if (element == null) { |
| 400 if (node.selector.isThis()) { | 523 if (node.selector.isThis()) { |
| 401 return new AccessSemantics.thisAccess(); | 524 return new AccessSemantics.thisAccess(); |
| 402 } else { | 525 } else { |
| 403 return new AccessSemantics.expression(); | 526 return new AccessSemantics.expression(); |
| 404 } | 527 } |
| 405 } else if (Elements.isErroneous(element)) { | 528 } else if (Elements.isErroneous(element)) { |
| 406 return new StaticAccess.unresolved(element); | 529 return new StaticAccess.unresolved(element); |
| 407 } else { | 530 } else { |
| 408 return handleStaticallyResolvedAccess(node, element, getter); | 531 return handleStaticallyResolvedAccess( |
| 532 node, element, getter, isCompound: isCompound); |
| 409 } | 533 } |
| 410 } else { | 534 } else { |
| 411 if (Elements.isErroneous(element)) { | 535 bool isDynamicAccess(Element e) => e == null || e.isInstanceMember; |
| 412 return new StaticAccess.unresolved(element); | 536 |
| 413 } else if (isCompound && Elements.isErroneous(getter)) { | 537 if (isDynamicAccess(element) && |
| 414 return new StaticAccess.unresolved(getter); | 538 (!isCompound || isDynamicAccess(getter))) { |
| 415 } else if (element == null || element.isInstanceMember) { | |
| 416 if (node.receiver == null || node.receiver.isThis()) { | 539 if (node.receiver == null || node.receiver.isThis()) { |
| 417 return new AccessSemantics.thisProperty(); | 540 return new AccessSemantics.thisProperty(); |
| 418 } else { | 541 } else { |
| 419 return new DynamicAccess.dynamicProperty(node.receiver); | 542 return new DynamicAccess.dynamicProperty(node.receiver); |
| 420 } | 543 } |
| 421 } else if (element.impliesType) { | 544 } else if (element != null && element.impliesType) { |
| 422 // TODO(johnniwinther): Provide an [ErroneousElement]. | 545 // TODO(johnniwinther): Provide an [ErroneousElement]. |
| 423 // This happens for code like `C.this`. | 546 // This happens for code like `C.this`. |
| 424 return new StaticAccess.unresolved(null); | 547 return new StaticAccess.unresolved(null); |
| 425 } else { | 548 } else { |
| 426 return handleStaticallyResolvedAccess(node, element, getter); | 549 return handleStaticallyResolvedAccess( |
| 550 node, element, getter, isCompound: isCompound); |
| 427 } | 551 } |
| 428 } | 552 } |
| 429 } | 553 } |
| 430 | 554 |
| 431 ConstructorAccessSemantics computeConstructorAccessSemantics( | 555 ConstructorAccessSemantics computeConstructorAccessSemantics( |
| 432 ConstructorElement constructor, | 556 ConstructorElement constructor, |
| 433 DartType type) { | 557 DartType type) { |
| 434 if (constructor.isErroneous) { | 558 if (constructor.isErroneous) { |
| 435 if (constructor is ErroneousElement) { | 559 if (constructor is ErroneousElement) { |
| 436 ErroneousElement error = constructor; | 560 ErroneousElement error = constructor; |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 return internalError(node, "Unexpected variable $element."); | 933 return internalError(node, "Unexpected variable $element."); |
| 810 } | 934 } |
| 811 if (element.isConst) { | 935 if (element.isConst) { |
| 812 ConstantExpression constant = elements.getConstant(element.initializer); | 936 ConstantExpression constant = elements.getConstant(element.initializer); |
| 813 return new ConstantVariableStructure(kind, node, element, constant); | 937 return new ConstantVariableStructure(kind, node, element, constant); |
| 814 } else { | 938 } else { |
| 815 return new NonConstantVariableStructure(kind, node, element); | 939 return new NonConstantVariableStructure(kind, node, element); |
| 816 } | 940 } |
| 817 } | 941 } |
| 818 } | 942 } |
| OLD | NEW |