OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library fasta.builder_accessors; | 5 library fasta.builder_accessors; |
6 | 6 |
7 export 'frontend_accessors.dart' show wrapInvalid; | 7 export 'frontend_accessors.dart' show wrapInvalid; |
8 | 8 |
9 import 'frontend_accessors.dart' show Accessor; | 9 import 'frontend_accessors.dart' show Accessor; |
10 | 10 |
11 import 'package:kernel/ast.dart'; | 11 import 'package:kernel/ast.dart'; |
12 | 12 |
13 import 'package:kernel/core_types.dart' show CoreTypes; | 13 import 'package:kernel/core_types.dart' show CoreTypes; |
14 | 14 |
15 import '../builder/scope.dart' show ProblemBuilder; | 15 import '../builder/scope.dart' show AccessErrorBuilder, ProblemBuilder; |
16 | 16 |
17 import '../errors.dart' show internalError, printUnexpected; | 17 import '../errors.dart' show internalError, printUnexpected; |
18 | 18 |
19 import 'frontend_accessors.dart' as kernel | 19 import 'frontend_accessors.dart' as kernel |
20 show | 20 show |
21 IndexAccessor, | 21 IndexAccessor, |
22 NullAwarePropertyAccessor, | 22 NullAwarePropertyAccessor, |
23 PropertyAccessor, | 23 PropertyAccessor, |
24 StaticAccessor, | 24 StaticAccessor, |
25 SuperIndexAccessor, | 25 SuperIndexAccessor, |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 if (receiver is BuilderAccessor) { | 422 if (receiver is BuilderAccessor) { |
423 return receiver.buildPropertyAccess(this, isNullAware); | 423 return receiver.buildPropertyAccess(this, isNullAware); |
424 } | 424 } |
425 if (receiver is PrefixBuilder) { | 425 if (receiver is PrefixBuilder) { |
426 PrefixBuilder prefix = receiver; | 426 PrefixBuilder prefix = receiver; |
427 return helper.builderToFirstExpression( | 427 return helper.builderToFirstExpression( |
428 prefix.exports[name.name], name.name, charOffset); | 428 prefix.exports[name.name], name.name, charOffset); |
429 } | 429 } |
430 if (receiver is KernelClassBuilder) { | 430 if (receiver is KernelClassBuilder) { |
431 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); | 431 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); |
432 Member getter = builder?.target; | |
433 Member setter; | |
434 if (builder == null) { | 432 if (builder == null) { |
435 builder = receiver.findStaticBuilder(name.name, charOffset, uri, | 433 // If we find a setter, [builder] is an [AccessErrorBuilder], not null. |
| 434 return buildThrowNoSuchMethodError(null); |
| 435 } |
| 436 Builder setter; |
| 437 if (builder.isSetter) { |
| 438 setter = builder; |
| 439 } else if (builder.isGetter) { |
| 440 setter = receiver.findStaticBuilder(name.name, charOffset, uri, |
436 isSetter: true); | 441 isSetter: true); |
437 if (builder == null) { | 442 } else if (builder.isField && !builder.isFinal) { |
438 return buildThrowNoSuchMethodError(null); | 443 setter = builder; |
439 } | |
440 setter = builder.target; | |
441 } | 444 } |
442 if (builder.hasProblem) { | 445 return new StaticAccessor.fromBuilder( |
443 return helper.buildProblemExpression(builder, charOffset); | 446 helper, builder, charOffset, setter); |
444 } | |
445 if (getter is Field) { | |
446 if (!getter.isFinal && !getter.isConst) { | |
447 setter = getter; | |
448 } | |
449 } else if (getter is Procedure) { | |
450 if (getter.isGetter) { | |
451 builder = receiver.findStaticBuilder(name.name, charOffset, uri, | |
452 isSetter: true); | |
453 if (builder != null && !builder.hasProblem) { | |
454 setter = builder.target; | |
455 } | |
456 } | |
457 } | |
458 if (getter == null && setter == null) { | |
459 return internalError("No accessor for '$name'."); | |
460 } | |
461 return new StaticAccessor(helper, charOffset, getter, setter); | |
462 } | 447 } |
463 return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver), | 448 return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver), |
464 name, null, null, isNullAware); | 449 name, null, null, isNullAware); |
465 } | 450 } |
466 | 451 |
467 Expression buildNullAwareAssignment(Expression value, DartType type, | 452 Expression buildNullAwareAssignment(Expression value, DartType type, |
468 {bool voidContext: false}) { | 453 {bool voidContext: false}) { |
469 return internalError("Unhandled"); | 454 return internalError("Unhandled"); |
470 } | 455 } |
471 | 456 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 final BuilderHelper helper; | 552 final BuilderHelper helper; |
568 | 553 |
569 final int charOffset; | 554 final int charOffset; |
570 | 555 |
571 StaticAccessor( | 556 StaticAccessor( |
572 this.helper, this.charOffset, Member readTarget, Member writeTarget) | 557 this.helper, this.charOffset, Member readTarget, Member writeTarget) |
573 : super(readTarget, writeTarget) { | 558 : super(readTarget, writeTarget) { |
574 assert(readTarget != null || writeTarget != null); | 559 assert(readTarget != null || writeTarget != null); |
575 } | 560 } |
576 | 561 |
| 562 factory StaticAccessor.fromBuilder(BuilderHelper helper, Builder builder, |
| 563 int charOffset, Builder builderSetter) { |
| 564 if (builder is AccessErrorBuilder) { |
| 565 AccessErrorBuilder error = builder; |
| 566 builder = error.builder; |
| 567 // We should only see an access error here if we've looked up a setter |
| 568 // when not explicitly looking for a setter. |
| 569 assert(builder.isSetter); |
| 570 } else if (builder.target == null) { |
| 571 return internalError("Unhandled: ${builder}"); |
| 572 } |
| 573 Member getter = builder.target.hasGetter ? builder.target : null; |
| 574 Member setter = builder.target.hasSetter ? builder.target : null; |
| 575 if (setter == null) { |
| 576 if (builderSetter?.target?.hasSetter ?? false) { |
| 577 setter = builderSetter.target; |
| 578 } |
| 579 } |
| 580 return new StaticAccessor(helper, charOffset, getter, setter); |
| 581 } |
| 582 |
577 String get plainNameForRead => (readTarget ?? writeTarget).name.name; | 583 String get plainNameForRead => (readTarget ?? writeTarget).name.name; |
578 | 584 |
579 Expression doInvocation(int charOffset, Arguments arguments) { | 585 Expression doInvocation(int charOffset, Arguments arguments) { |
580 if (readTarget == null || isFieldOrGetter(readTarget)) { | 586 if (readTarget == null || isFieldOrGetter(readTarget)) { |
581 return buildMethodInvocation( | 587 return buildMethodInvocation( |
582 buildSimpleRead(), new Name("call"), arguments, charOffset); | 588 buildSimpleRead(), new Name("call"), arguments, charOffset); |
583 } else { | 589 } else { |
584 return helper.buildStaticInvocation(readTarget, arguments) | 590 return helper.buildStaticInvocation(readTarget, arguments) |
585 ..fileOffset = charOffset; | 591 ..fileOffset = charOffset; |
586 } | 592 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, | 725 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
720 charOffset + (variable.name?.length ?? 0)); | 726 charOffset + (variable.name?.length ?? 0)); |
721 } | 727 } |
722 | 728 |
723 toString() => "VariableAccessor()"; | 729 toString() => "VariableAccessor()"; |
724 } | 730 } |
725 | 731 |
726 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, | 732 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, |
727 int charOffset, CoreTypes coreTypes, | 733 int charOffset, CoreTypes coreTypes, |
728 {bool isSuper: false, isGetter: false, isSetter: false}) { | 734 {bool isSuper: false, isGetter: false, isSetter: false}) { |
729 printUnexpected(uri, charOffset, "Method not found: '$name'."); | 735 String errorName = name; |
| 736 if (isSuper) { |
| 737 errorName = "super.$name"; |
| 738 } |
| 739 if (isGetter) { |
| 740 printUnexpected(uri, charOffset, "Getter not found: '$errorName'."); |
| 741 } else if (isSetter) { |
| 742 printUnexpected(uri, charOffset, "Setter not found: '$errorName'."); |
| 743 } else { |
| 744 printUnexpected(uri, charOffset, "Method not found: '$name'."); |
| 745 } |
730 Constructor constructor = | 746 Constructor constructor = |
731 coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first; | 747 coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first; |
732 return new Throw(new ConstructorInvocation( | 748 return new Throw(new ConstructorInvocation( |
733 constructor, | 749 constructor, |
734 new Arguments(<Expression>[ | 750 new Arguments(<Expression>[ |
735 new NullLiteral(), | 751 new NullLiteral(), |
736 new SymbolLiteral(name), | 752 new SymbolLiteral(name), |
737 new ListLiteral(arguments.positional), | 753 new ListLiteral(arguments.positional), |
738 new MapLiteral(arguments.named.map((arg) { | 754 new MapLiteral(arguments.named.map((arg) { |
739 return new MapEntry(new SymbolLiteral(arg.name), arg.value); | 755 return new MapEntry(new SymbolLiteral(arg.name), arg.value); |
(...skipping 17 matching lines...) Expand all Loading... |
757 buildIsNull(new VariableGet(variable)), | 773 buildIsNull(new VariableGet(variable)), |
758 new NullLiteral(), | 774 new NullLiteral(), |
759 new MethodInvocation(new VariableGet(variable), name, arguments) | 775 new MethodInvocation(new VariableGet(variable), name, arguments) |
760 ..fileOffset = charOffset, | 776 ..fileOffset = charOffset, |
761 const DynamicType())); | 777 const DynamicType())); |
762 } else { | 778 } else { |
763 return new MethodInvocation(receiver, name, arguments) | 779 return new MethodInvocation(receiver, name, arguments) |
764 ..fileOffset = charOffset; | 780 ..fileOffset = charOffset; |
765 } | 781 } |
766 } | 782 } |
OLD | NEW |