| 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 handleCompoundErroneousSetterAccess( | 31 AccessSemantics handleStaticallyResolvedAccess(Send node, |
| 32 Send node, | 32 Element element, |
| 33 Element setter, | 33 Element getter) { |
| 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 } | |
| 103 if (element.isErroneous) { | 34 if (element.isErroneous) { |
| 104 if (isCompound) { | |
| 105 return handleCompoundErroneousSetterAccess(node, element, getter); | |
| 106 } | |
| 107 return new StaticAccess.unresolved(element); | 35 return new StaticAccess.unresolved(element); |
| 108 } else if (element.isParameter) { | 36 } else if (element.isParameter) { |
| 109 return new StaticAccess.parameter(element); | 37 return new StaticAccess.parameter(element); |
| 110 } else if (element.isLocal) { | 38 } else if (element.isLocal) { |
| 111 if (element.isFunction) { | 39 if (element.isFunction) { |
| 112 return new StaticAccess.localFunction(element); | 40 return new StaticAccess.localFunction(element); |
| 113 } else { | 41 } else { |
| 114 return new StaticAccess.localVariable(element); | 42 return new StaticAccess.localVariable(element); |
| 115 } | 43 } |
| 116 } else if (element.isStatic) { | 44 } else if (element.isStatic) { |
| 117 if (element.isField) { | 45 if (element.isField) { |
| 118 if (element.isFinal || element.isConst) { | |
| 119 // TODO(johnniwinther): Handle const field separately. | |
| 120 return new StaticAccess.finalStaticField(element); | |
| 121 } | |
| 122 return new StaticAccess.staticField(element); | 46 return new StaticAccess.staticField(element); |
| 123 } else if (element.isGetter) { | 47 } else if (element.isGetter) { |
| 124 if (isCompound) { | |
| 125 return new CompoundAccessSemantics( | |
| 126 CompoundAccessKind.UNRESOLVED_STATIC_SETTER, element, null); | |
| 127 } | |
| 128 return new StaticAccess.staticGetter(element); | 48 return new StaticAccess.staticGetter(element); |
| 129 } else if (element.isSetter) { | 49 } else if (element.isSetter) { |
| 130 if (getter != null) { | 50 if (getter != null) { |
| 131 CompoundAccessKind accessKind; | 51 CompoundAccessKind accessKind; |
| 132 if (getter.isErroneous) { | 52 if (getter.isGetter) { |
| 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) { | |
| 144 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; | 53 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; |
| 145 } else { | 54 } else { |
| 146 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; | 55 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; |
| 147 } | 56 } |
| 148 return new CompoundAccessSemantics( | 57 return new CompoundAccessSemantics( |
| 149 accessKind, getter, element); | 58 accessKind, getter, element); |
| 150 } else { | 59 } else { |
| 151 return new StaticAccess.staticSetter(element); | 60 return new StaticAccess.staticSetter(element); |
| 152 } | 61 } |
| 153 } else { | 62 } else { |
| 154 return new StaticAccess.staticMethod(element); | 63 return new StaticAccess.staticMethod(element); |
| 155 } | 64 } |
| 156 } else if (element.isTopLevel) { | 65 } else if (element.isTopLevel) { |
| 157 if (element.isField) { | 66 if (element.isField) { |
| 158 if (element.isFinal || element.isConst) { | |
| 159 // TODO(johnniwinther): Handle const field separately. | |
| 160 return new StaticAccess.finalTopLevelField(element); | |
| 161 } | |
| 162 return new StaticAccess.topLevelField(element); | 67 return new StaticAccess.topLevelField(element); |
| 163 } else if (element.isGetter) { | 68 } else if (element.isGetter) { |
| 164 return new StaticAccess.topLevelGetter(element); | 69 return new StaticAccess.topLevelGetter(element); |
| 165 } else if (element.isSetter) { | 70 } else if (element.isSetter) { |
| 166 if (getter != null) { | 71 if (getter != null) { |
| 167 CompoundAccessKind accessKind; | 72 CompoundAccessKind accessKind; |
| 168 if (getter.isErroneous) { | 73 if (getter.isGetter) { |
| 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) { | |
| 180 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; | 74 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; |
| 181 } else { | 75 } else { |
| 182 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; | 76 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; |
| 183 } | 77 } |
| 184 return new CompoundAccessSemantics( | 78 return new CompoundAccessSemantics( |
| 185 accessKind, getter, element); | 79 accessKind, getter, element); |
| 186 } else { | 80 } else { |
| 187 return new StaticAccess.topLevelSetter(element); | 81 return new StaticAccess.topLevelSetter(element); |
| 188 } | 82 } |
| 189 } else { | 83 } else { |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 return new ConstantAccess.dynamicTypeLiteral(constant); | 337 return new ConstantAccess.dynamicTypeLiteral(constant); |
| 444 default: | 338 default: |
| 445 return internalError(node, "Unexpected type literal type: $dartType"); | 339 return internalError(node, "Unexpected type literal type: $dartType"); |
| 446 } | 340 } |
| 447 } else if (node.isSuperCall) { | 341 } else if (node.isSuperCall) { |
| 448 if (Elements.isUnresolved(element)) { | 342 if (Elements.isUnresolved(element)) { |
| 449 if (isCompound) { | 343 if (isCompound) { |
| 450 if (Elements.isUnresolved(getter)) { | 344 if (Elements.isUnresolved(getter)) { |
| 451 // TODO(johnniwinther): Ensure that [getter] is not null. This | 345 // TODO(johnniwinther): Ensure that [getter] is not null. This |
| 452 // happens in the case of missing super getter. | 346 // happens in the case of missing super getter. |
| 453 return new StaticAccess.unresolvedSuper(element); | 347 return new CompoundAccessSemantics( |
| 454 } else if (getter.isField) { | 348 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 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 } | |
| 465 } else { | 349 } else { |
| 466 return new CompoundAccessSemantics( | 350 return new CompoundAccessSemantics( |
| 467 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); | 351 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 468 } | 352 } |
| 469 } else { | 353 } else { |
| 470 return new StaticAccess.unresolvedSuper(element); | 354 return new StaticAccess.unresolvedSuper(element); |
| 471 } | 355 } |
| 472 } else if (isCompound && Elements.isUnresolved(getter)) { | 356 } else if (isCompound && Elements.isUnresolved(getter)) { |
| 473 // TODO(johnniwinther): Ensure that [getter] is not null. This happens | 357 // TODO(johnniwinther): Ensure that [getter] is not null. This happens |
| 474 // in the case of missing super getter. | 358 // in the case of missing super getter. |
| 475 return new CompoundAccessSemantics( | 359 return new CompoundAccessSemantics( |
| 476 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 360 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 477 } else if (element.isField) { | 361 } else if (element.isField) { |
| 478 if (getter != null && getter != element) { | 362 if (getter != null && getter != element) { |
| 479 CompoundAccessKind accessKind; | 363 CompoundAccessKind accessKind; |
| 480 if (getter.isField) { | 364 if (getter.isField) { |
| 481 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; | 365 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; |
| 482 } else if (getter.isGetter) { | 366 } else if (getter.isGetter) { |
| 483 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; | 367 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; |
| 484 } else { | 368 } else { |
| 485 return internalError(node, | 369 return internalError(node, |
| 486 "Unsupported super call: $node : $element/$getter."); | 370 "Unsupported super call: $node : $element/$getter."); |
| 487 } | 371 } |
| 488 return new CompoundAccessSemantics(accessKind, getter, element); | 372 return new CompoundAccessSemantics(accessKind, getter, element); |
| 489 } else if (element.isFinal) { | |
| 490 return new StaticAccess.superFinalField(element); | |
| 491 } | 373 } |
| 492 return new StaticAccess.superField(element); | 374 return new StaticAccess.superField(element); |
| 493 } else if (element.isGetter) { | 375 } else if (element.isGetter) { |
| 494 return new StaticAccess.superGetter(element); | 376 return new StaticAccess.superGetter(element); |
| 495 } else if (element.isSetter) { | 377 } else if (element.isSetter) { |
| 496 if (getter != null) { | 378 if (getter != null) { |
| 497 CompoundAccessKind accessKind; | 379 CompoundAccessKind accessKind; |
| 498 if (getter.isField) { | 380 if (getter.isField) { |
| 499 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; | 381 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; |
| 500 } else if (getter.isGetter) { | 382 } else if (getter.isGetter) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 516 } else if (Elements.isClosureSend(node, element)) { | 398 } else if (Elements.isClosureSend(node, element)) { |
| 517 if (element == null) { | 399 if (element == null) { |
| 518 if (node.selector.isThis()) { | 400 if (node.selector.isThis()) { |
| 519 return new AccessSemantics.thisAccess(); | 401 return new AccessSemantics.thisAccess(); |
| 520 } else { | 402 } else { |
| 521 return new AccessSemantics.expression(); | 403 return new AccessSemantics.expression(); |
| 522 } | 404 } |
| 523 } else if (Elements.isErroneous(element)) { | 405 } else if (Elements.isErroneous(element)) { |
| 524 return new StaticAccess.unresolved(element); | 406 return new StaticAccess.unresolved(element); |
| 525 } else { | 407 } else { |
| 526 return handleStaticallyResolvedAccess( | 408 return handleStaticallyResolvedAccess(node, element, getter); |
| 527 node, element, getter, isCompound: isCompound); | |
| 528 } | 409 } |
| 529 } else { | 410 } else { |
| 530 bool isDynamicAccess(Element e) => e == null || e.isInstanceMember; | 411 if (Elements.isErroneous(element)) { |
| 531 | 412 return new StaticAccess.unresolved(element); |
| 532 if (isDynamicAccess(element) && | 413 } else if (isCompound && Elements.isErroneous(getter)) { |
| 533 (!isCompound || isDynamicAccess(getter))) { | 414 return new StaticAccess.unresolved(getter); |
| 415 } else if (element == null || element.isInstanceMember) { |
| 534 if (node.receiver == null || node.receiver.isThis()) { | 416 if (node.receiver == null || node.receiver.isThis()) { |
| 535 return new AccessSemantics.thisProperty(); | 417 return new AccessSemantics.thisProperty(); |
| 536 } else { | 418 } else { |
| 537 return new DynamicAccess.dynamicProperty(node.receiver); | 419 return new DynamicAccess.dynamicProperty(node.receiver); |
| 538 } | 420 } |
| 539 } else if (element != null && element.impliesType) { | 421 } else if (element.impliesType) { |
| 540 // TODO(johnniwinther): Provide an [ErroneousElement]. | 422 // TODO(johnniwinther): Provide an [ErroneousElement]. |
| 541 // This happens for code like `C.this`. | 423 // This happens for code like `C.this`. |
| 542 return new StaticAccess.unresolved(null); | 424 return new StaticAccess.unresolved(null); |
| 543 } else { | 425 } else { |
| 544 return handleStaticallyResolvedAccess( | 426 return handleStaticallyResolvedAccess(node, element, getter); |
| 545 node, element, getter, isCompound: isCompound); | |
| 546 } | 427 } |
| 547 } | 428 } |
| 548 } | 429 } |
| 549 | 430 |
| 550 ConstructorAccessSemantics computeConstructorAccessSemantics( | 431 ConstructorAccessSemantics computeConstructorAccessSemantics( |
| 551 ConstructorElement constructor, | 432 ConstructorElement constructor, |
| 552 DartType type, | 433 DartType type, |
| 553 {bool mustBeConstant: false}) { | 434 {bool mustBeConstant: false}) { |
| 554 if (mustBeConstant && !constructor.isConst) { | 435 if (mustBeConstant && !constructor.isConst) { |
| 555 return new ConstructorAccessSemantics( | 436 return new ConstructorAccessSemantics( |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 return internalError(node, "Unexpected variable $element."); | 813 return internalError(node, "Unexpected variable $element."); |
| 933 } | 814 } |
| 934 if (element.isConst) { | 815 if (element.isConst) { |
| 935 ConstantExpression constant = elements.getConstant(element.initializer); | 816 ConstantExpression constant = elements.getConstant(element.initializer); |
| 936 return new ConstantVariableStructure(kind, node, element, constant); | 817 return new ConstantVariableStructure(kind, node, element, constant); |
| 937 } else { | 818 } else { |
| 938 return new NonConstantVariableStructure(kind, node, element); | 819 return new NonConstantVariableStructure(kind, node, element); |
| 939 } | 820 } |
| 940 } | 821 } |
| 941 } | 822 } |
| OLD | NEW |