| 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.finalStaticField(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.finalTopLevelField(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.finalStaticField(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.finalTopLevelField(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 return new StaticAccess.unresolvedSuper(element); |
| 348 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 454 } else if (getter.isField) { |
| 455 assert(invariant(node, getter.isFinal, |
| 456 message: "Super field expected to be final.")); |
| 457 return new StaticAccess.superFinalField(getter); |
| 458 } else if (getter.isFunction) { |
| 459 if (node.isIndex) { |
| 460 return new CompoundAccessSemantics( |
| 461 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 462 } else { |
| 463 return new StaticAccess.superMethod(getter); |
| 464 } |
| 349 } else { | 465 } else { |
| 350 return new CompoundAccessSemantics( | 466 return new CompoundAccessSemantics( |
| 351 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); | 467 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 352 } | 468 } |
| 353 } else { | 469 } else { |
| 354 return new StaticAccess.unresolvedSuper(element); | 470 return new StaticAccess.unresolvedSuper(element); |
| 355 } | 471 } |
| 356 } else if (isCompound && Elements.isUnresolved(getter)) { | 472 } else if (isCompound && Elements.isUnresolved(getter)) { |
| 357 // TODO(johnniwinther): Ensure that [getter] is not null. This happens | 473 // TODO(johnniwinther): Ensure that [getter] is not null. This happens |
| 358 // in the case of missing super getter. | 474 // in the case of missing super getter. |
| 359 return new CompoundAccessSemantics( | 475 return new CompoundAccessSemantics( |
| 360 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 476 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 361 } else if (element.isField) { | 477 } else if (element.isField) { |
| 362 if (getter != null && getter != element) { | 478 if (getter != null && getter != element) { |
| 363 CompoundAccessKind accessKind; | 479 CompoundAccessKind accessKind; |
| 364 if (getter.isField) { | 480 if (getter.isField) { |
| 365 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; | 481 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; |
| 366 } else if (getter.isGetter) { | 482 } else if (getter.isGetter) { |
| 367 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; | 483 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; |
| 368 } else { | 484 } else { |
| 369 return internalError(node, | 485 return internalError(node, |
| 370 "Unsupported super call: $node : $element/$getter."); | 486 "Unsupported super call: $node : $element/$getter."); |
| 371 } | 487 } |
| 372 return new CompoundAccessSemantics(accessKind, getter, element); | 488 return new CompoundAccessSemantics(accessKind, getter, element); |
| 489 } else if (element.isFinal) { |
| 490 return new StaticAccess.superFinalField(element); |
| 373 } | 491 } |
| 374 return new StaticAccess.superField(element); | 492 return new StaticAccess.superField(element); |
| 375 } else if (element.isGetter) { | 493 } else if (element.isGetter) { |
| 376 return new StaticAccess.superGetter(element); | 494 return new StaticAccess.superGetter(element); |
| 377 } else if (element.isSetter) { | 495 } else if (element.isSetter) { |
| 378 if (getter != null) { | 496 if (getter != null) { |
| 379 CompoundAccessKind accessKind; | 497 CompoundAccessKind accessKind; |
| 380 if (getter.isField) { | 498 if (getter.isField) { |
| 381 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; | 499 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; |
| 382 } else if (getter.isGetter) { | 500 } else if (getter.isGetter) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 398 } else if (Elements.isClosureSend(node, element)) { | 516 } else if (Elements.isClosureSend(node, element)) { |
| 399 if (element == null) { | 517 if (element == null) { |
| 400 if (node.selector.isThis()) { | 518 if (node.selector.isThis()) { |
| 401 return new AccessSemantics.thisAccess(); | 519 return new AccessSemantics.thisAccess(); |
| 402 } else { | 520 } else { |
| 403 return new AccessSemantics.expression(); | 521 return new AccessSemantics.expression(); |
| 404 } | 522 } |
| 405 } else if (Elements.isErroneous(element)) { | 523 } else if (Elements.isErroneous(element)) { |
| 406 return new StaticAccess.unresolved(element); | 524 return new StaticAccess.unresolved(element); |
| 407 } else { | 525 } else { |
| 408 return handleStaticallyResolvedAccess(node, element, getter); | 526 return handleStaticallyResolvedAccess( |
| 527 node, element, getter, isCompound: isCompound); |
| 409 } | 528 } |
| 410 } else { | 529 } else { |
| 411 if (Elements.isErroneous(element)) { | 530 bool isDynamicAccess(Element e) => e == null || e.isInstanceMember; |
| 412 return new StaticAccess.unresolved(element); | 531 |
| 413 } else if (isCompound && Elements.isErroneous(getter)) { | 532 if (isDynamicAccess(element) && |
| 414 return new StaticAccess.unresolved(getter); | 533 (!isCompound || isDynamicAccess(getter))) { |
| 415 } else if (element == null || element.isInstanceMember) { | |
| 416 if (node.receiver == null || node.receiver.isThis()) { | 534 if (node.receiver == null || node.receiver.isThis()) { |
| 417 return new AccessSemantics.thisProperty(); | 535 return new AccessSemantics.thisProperty(); |
| 418 } else { | 536 } else { |
| 419 return new DynamicAccess.dynamicProperty(node.receiver); | 537 return new DynamicAccess.dynamicProperty(node.receiver); |
| 420 } | 538 } |
| 421 } else if (element.impliesType) { | 539 } else if (element != null && element.impliesType) { |
| 422 // TODO(johnniwinther): Provide an [ErroneousElement]. | 540 // TODO(johnniwinther): Provide an [ErroneousElement]. |
| 423 // This happens for code like `C.this`. | 541 // This happens for code like `C.this`. |
| 424 return new StaticAccess.unresolved(null); | 542 return new StaticAccess.unresolved(null); |
| 425 } else { | 543 } else { |
| 426 return handleStaticallyResolvedAccess(node, element, getter); | 544 return handleStaticallyResolvedAccess( |
| 545 node, element, getter, isCompound: isCompound); |
| 427 } | 546 } |
| 428 } | 547 } |
| 429 } | 548 } |
| 430 | 549 |
| 431 ConstructorAccessSemantics computeConstructorAccessSemantics( | 550 ConstructorAccessSemantics computeConstructorAccessSemantics( |
| 432 ConstructorElement constructor, | 551 ConstructorElement constructor, |
| 433 DartType type) { | 552 DartType type) { |
| 434 if (constructor.isErroneous) { | 553 if (constructor.isErroneous) { |
| 435 if (constructor is ErroneousElement) { | 554 if (constructor is ErroneousElement) { |
| 436 ErroneousElement error = constructor; | 555 ErroneousElement error = constructor; |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 return internalError(node, "Unexpected variable $element."); | 928 return internalError(node, "Unexpected variable $element."); |
| 810 } | 929 } |
| 811 if (element.isConst) { | 930 if (element.isConst) { |
| 812 ConstantExpression constant = elements.getConstant(element.initializer); | 931 ConstantExpression constant = elements.getConstant(element.initializer); |
| 813 return new ConstantVariableStructure(kind, node, element, constant); | 932 return new ConstantVariableStructure(kind, node, element, constant); |
| 814 } else { | 933 } else { |
| 815 return new NonConstantVariableStructure(kind, node, element); | 934 return new NonConstantVariableStructure(kind, node, element); |
| 816 } | 935 } |
| 817 } | 936 } |
| 818 } | 937 } |
| OLD | NEW |