| 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 AccessErrorBuilder, ProblemBuilder; |
| 16 |
| 15 import '../errors.dart' show internalError, printUnexpected; | 17 import '../errors.dart' show internalError, printUnexpected; |
| 16 | 18 |
| 17 import 'frontend_accessors.dart' as kernel | 19 import 'frontend_accessors.dart' as kernel |
| 18 show | 20 show |
| 19 IndexAccessor, | 21 IndexAccessor, |
| 20 NullAwarePropertyAccessor, | 22 NullAwarePropertyAccessor, |
| 21 PropertyAccessor, | 23 PropertyAccessor, |
| 22 StaticAccessor, | 24 StaticAccessor, |
| 23 SuperIndexAccessor, | 25 SuperIndexAccessor, |
| 24 SuperPropertyAccessor, | 26 SuperPropertyAccessor, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 47 builderToFirstExpression(Builder builder, String name, int charOffset); | 49 builderToFirstExpression(Builder builder, String name, int charOffset); |
| 48 | 50 |
| 49 finishSend(Object receiver, Arguments arguments, int charOffset); | 51 finishSend(Object receiver, Arguments arguments, int charOffset); |
| 50 | 52 |
| 51 Expression buildCompileTimeError(error, [int charOffset]); | 53 Expression buildCompileTimeError(error, [int charOffset]); |
| 52 | 54 |
| 53 Initializer buildCompileTimeErrorIntializer(error, [int charOffset]); | 55 Initializer buildCompileTimeErrorIntializer(error, [int charOffset]); |
| 54 | 56 |
| 55 Expression buildStaticInvocation(Procedure target, Arguments arguments); | 57 Expression buildStaticInvocation(Procedure target, Arguments arguments); |
| 56 | 58 |
| 57 Expression buildProblemExpression(Builder builder, String name); | 59 Expression buildProblemExpression(ProblemBuilder builder, int charOffset); |
| 58 } | 60 } |
| 59 | 61 |
| 60 abstract class BuilderAccessor implements Accessor { | 62 abstract class BuilderAccessor implements Accessor { |
| 61 BuilderHelper get helper; | 63 BuilderHelper get helper; |
| 62 | 64 |
| 63 int get charOffset; | 65 int get charOffset; |
| 64 | 66 |
| 65 String get plainNameForRead; | 67 String get plainNameForRead; |
| 66 | 68 |
| 67 Uri get uri => helper.uri; | 69 Uri get uri => helper.uri; |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 prefix.exports[name.name], "${prefix.name}.${name.name}", charOffset); | 342 prefix.exports[name.name], "${prefix.name}.${name.name}", charOffset); |
| 341 return helper.finishSend(receiver, arguments, charOffset); | 343 return helper.finishSend(receiver, arguments, charOffset); |
| 342 } | 344 } |
| 343 Expression result; | 345 Expression result; |
| 344 if (receiver is KernelClassBuilder) { | 346 if (receiver is KernelClassBuilder) { |
| 345 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); | 347 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); |
| 346 if (builder == null) { | 348 if (builder == null) { |
| 347 return buildThrowNoSuchMethodError(arguments); | 349 return buildThrowNoSuchMethodError(arguments); |
| 348 } | 350 } |
| 349 if (builder.hasProblem) { | 351 if (builder.hasProblem) { |
| 350 result = helper.buildProblemExpression(builder, name.name); | 352 result = helper.buildProblemExpression(builder, charOffset); |
| 351 } else { | 353 } else { |
| 352 Member target = builder.target; | 354 Member target = builder.target; |
| 353 if (target != null) { | 355 if (target != null) { |
| 354 if (target is Field) { | 356 if (target is Field) { |
| 355 result = buildMethodInvocation( | 357 result = buildMethodInvocation( |
| 356 new StaticGet(target), new Name("call"), arguments, charOffset, | 358 new StaticGet(target), new Name("call"), arguments, charOffset, |
| 357 isNullAware: isNullAware); | 359 isNullAware: isNullAware); |
| 358 } else { | 360 } else { |
| 359 result = helper.buildStaticInvocation(target, arguments); | 361 result = helper.buildStaticInvocation(target, arguments); |
| 360 } | 362 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 if (receiver is BuilderAccessor) { | 422 if (receiver is BuilderAccessor) { |
| 421 return receiver.buildPropertyAccess(this, isNullAware); | 423 return receiver.buildPropertyAccess(this, isNullAware); |
| 422 } | 424 } |
| 423 if (receiver is PrefixBuilder) { | 425 if (receiver is PrefixBuilder) { |
| 424 PrefixBuilder prefix = receiver; | 426 PrefixBuilder prefix = receiver; |
| 425 return helper.builderToFirstExpression( | 427 return helper.builderToFirstExpression( |
| 426 prefix.exports[name.name], name.name, charOffset); | 428 prefix.exports[name.name], name.name, charOffset); |
| 427 } | 429 } |
| 428 if (receiver is KernelClassBuilder) { | 430 if (receiver is KernelClassBuilder) { |
| 429 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); | 431 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); |
| 430 Member getter = builder?.target; | |
| 431 Member setter; | |
| 432 if (builder == null) { | 432 if (builder == null) { |
| 433 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, |
| 434 isSetter: true); | 441 isSetter: true); |
| 435 if (builder == null) { | 442 } else if (builder.isField && !builder.isFinal) { |
| 436 return buildThrowNoSuchMethodError(null); | 443 setter = builder; |
| 437 } | |
| 438 setter = builder.target; | |
| 439 } | 444 } |
| 440 if (builder.hasProblem) { | 445 return new StaticAccessor.fromBuilder( |
| 441 return helper.buildProblemExpression(builder, name.name) | 446 helper, |
| 442 ..fileOffset = charOffset; | 447 builder, |
| 443 } | 448 charOffset, |
| 444 if (getter is Field) { | 449 setter); |
| 445 if (!getter.isFinal && !getter.isConst) { | |
| 446 setter = getter; | |
| 447 } | |
| 448 } else if (getter is Procedure) { | |
| 449 if (getter.isGetter) { | |
| 450 builder = receiver.findStaticBuilder(name.name, charOffset, uri, | |
| 451 isSetter: true); | |
| 452 if (builder != null && !builder.hasProblem) { | |
| 453 setter = builder.target; | |
| 454 } | |
| 455 } | |
| 456 } | |
| 457 if (getter == null && setter == null) { | |
| 458 return internalError("No accessor for '$name'."); | |
| 459 } | |
| 460 return new StaticAccessor(helper, charOffset, getter, setter); | |
| 461 } | 450 } |
| 462 return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver), | 451 return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver), |
| 463 name, null, null, isNullAware); | 452 name, null, null, isNullAware); |
| 464 } | 453 } |
| 465 | 454 |
| 466 Expression buildNullAwareAssignment(Expression value, DartType type, | 455 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 467 {bool voidContext: false}) { | 456 {bool voidContext: false}) { |
| 468 return internalError("Unhandled"); | 457 return internalError("Unhandled"); |
| 469 } | 458 } |
| 470 | 459 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 final BuilderHelper helper; | 555 final BuilderHelper helper; |
| 567 | 556 |
| 568 final int charOffset; | 557 final int charOffset; |
| 569 | 558 |
| 570 StaticAccessor( | 559 StaticAccessor( |
| 571 this.helper, this.charOffset, Member readTarget, Member writeTarget) | 560 this.helper, this.charOffset, Member readTarget, Member writeTarget) |
| 572 : super(readTarget, writeTarget) { | 561 : super(readTarget, writeTarget) { |
| 573 assert(readTarget != null || writeTarget != null); | 562 assert(readTarget != null || writeTarget != null); |
| 574 } | 563 } |
| 575 | 564 |
| 565 factory StaticAccessor.fromBuilder(BuilderHelper helper, Builder builder, |
| 566 int charOffset, Builder builderSetter) { |
| 567 if (builder is AccessErrorBuilder) { |
| 568 AccessErrorBuilder error = builder; |
| 569 builder = error.builder; |
| 570 // We should only see an access error here if we've looked up a setter |
| 571 // when not explicitly looking for a setter. |
| 572 assert(builder.isSetter); |
| 573 } else if (builder.target == null) { |
| 574 return internalError("Unhandled: ${builder}"); |
| 575 } |
| 576 Member getter = builder.target.hasGetter ? builder.target : null; |
| 577 Member setter = builder.target.hasSetter ? builder.target : null; |
| 578 if (setter == null) { |
| 579 if (builderSetter?.target?.hasSetter ?? false) { |
| 580 setter = builderSetter.target; |
| 581 } |
| 582 } |
| 583 return new StaticAccessor(helper, charOffset, getter, setter); |
| 584 } |
| 585 |
| 576 String get plainNameForRead => (readTarget ?? writeTarget).name.name; | 586 String get plainNameForRead => (readTarget ?? writeTarget).name.name; |
| 577 | 587 |
| 578 Expression doInvocation(int charOffset, Arguments arguments) { | 588 Expression doInvocation(int charOffset, Arguments arguments) { |
| 579 if (readTarget == null || isFieldOrGetter(readTarget)) { | 589 if (readTarget == null || isFieldOrGetter(readTarget)) { |
| 580 return buildMethodInvocation( | 590 return buildMethodInvocation( |
| 581 buildSimpleRead(), new Name("call"), arguments, charOffset); | 591 buildSimpleRead(), new Name("call"), arguments, charOffset); |
| 582 } else { | 592 } else { |
| 583 return helper.buildStaticInvocation(readTarget, arguments) | 593 return helper.buildStaticInvocation(readTarget, arguments) |
| 584 ..fileOffset = charOffset; | 594 ..fileOffset = charOffset; |
| 585 } | 595 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, | 728 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
| 719 charOffset + (variable.name?.length ?? 0)); | 729 charOffset + (variable.name?.length ?? 0)); |
| 720 } | 730 } |
| 721 | 731 |
| 722 toString() => "VariableAccessor()"; | 732 toString() => "VariableAccessor()"; |
| 723 } | 733 } |
| 724 | 734 |
| 725 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, | 735 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, |
| 726 int charOffset, CoreTypes coreTypes, | 736 int charOffset, CoreTypes coreTypes, |
| 727 {bool isSuper: false, isGetter: false, isSetter: false}) { | 737 {bool isSuper: false, isGetter: false, isSetter: false}) { |
| 728 printUnexpected(uri, charOffset, "Method not found: '$name'."); | 738 String errorName = name; |
| 739 if (isSuper) { |
| 740 errorName = "super.$name"; |
| 741 } |
| 742 if (isGetter) { |
| 743 printUnexpected(uri, charOffset, "Getter not found: '$errorName'."); |
| 744 } else if (isSetter) { |
| 745 printUnexpected(uri, charOffset, "Setter not found: '$errorName'."); |
| 746 } else { |
| 747 printUnexpected(uri, charOffset, "Method not found: '$name'."); |
| 748 } |
| 729 Constructor constructor = | 749 Constructor constructor = |
| 730 coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first; | 750 coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first; |
| 731 return new Throw(new ConstructorInvocation( | 751 return new Throw(new ConstructorInvocation( |
| 732 constructor, | 752 constructor, |
| 733 new Arguments(<Expression>[ | 753 new Arguments(<Expression>[ |
| 734 new NullLiteral(), | 754 new NullLiteral(), |
| 735 new SymbolLiteral(name), | 755 new SymbolLiteral(name), |
| 736 new ListLiteral(arguments.positional), | 756 new ListLiteral(arguments.positional), |
| 737 new MapLiteral(arguments.named.map((arg) { | 757 new MapLiteral(arguments.named.map((arg) { |
| 738 return new MapEntry(new SymbolLiteral(arg.name), arg.value); | 758 return new MapEntry(new SymbolLiteral(arg.name), arg.value); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 756 buildIsNull(new VariableGet(variable)), | 776 buildIsNull(new VariableGet(variable)), |
| 757 new NullLiteral(), | 777 new NullLiteral(), |
| 758 new MethodInvocation(new VariableGet(variable), name, arguments) | 778 new MethodInvocation(new VariableGet(variable), name, arguments) |
| 759 ..fileOffset = charOffset, | 779 ..fileOffset = charOffset, |
| 760 const DynamicType())); | 780 const DynamicType())); |
| 761 } else { | 781 } else { |
| 762 return new MethodInvocation(receiver, name, arguments) | 782 return new MethodInvocation(receiver, name, arguments) |
| 763 ..fileOffset = charOffset; | 783 ..fileOffset = charOffset; |
| 764 } | 784 } |
| 765 } | 785 } |
| OLD | NEW |