OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 analyzer.src.dart.constant.evaluation; | 5 library analyzer.src.dart.constant.evaluation; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/context/declared_variables.dart'; | 9 import 'package:analyzer/context/declared_variables.dart'; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 // Instantiate the constructor with the in-scope type arguments. | 543 // Instantiate the constructor with the in-scope type arguments. |
544 definingClass = constantVisitor.evaluateType(definingClass); | 544 definingClass = constantVisitor.evaluateType(definingClass); |
545 constructor = ConstructorMember.from(constructorBase, definingClass); | 545 constructor = ConstructorMember.from(constructorBase, definingClass); |
546 | 546 |
547 typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables( | 547 typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables( |
548 definingClass.typeParameters.map((t) => t.name), | 548 definingClass.typeParameters.map((t) => t.name), |
549 definingClass.typeArguments.map(constantVisitor.typeConstant)); | 549 definingClass.typeArguments.map(constantVisitor.typeConstant)); |
550 } | 550 } |
551 | 551 |
552 var fieldMap = new HashMap<String, DartObjectImpl>(); | 552 var fieldMap = new HashMap<String, DartObjectImpl>(); |
553 var fieldInitVisitor = new ConstantVisitor(this, errorReporter, | 553 |
| 554 // The errors reported while computing values for field initializers, or |
| 555 // default values for the constructor parameters, cannot be reported |
| 556 // into the current ErrorReporter, because they usually happen in a |
| 557 // different source. But they still should cause a constant evaluation |
| 558 // error for the current node. |
| 559 var externalErrorListener = new RecordingErrorListener(); |
| 560 var externalErrorReporter = |
| 561 new ErrorReporter(externalErrorListener, constructor.source); |
| 562 |
| 563 void reportLocalErrorForRecordedExternalErrors() { |
| 564 ErrorCode errorCode; |
| 565 for (AnalysisError error in externalErrorListener.errors) { |
| 566 if (error.errorCode is CompileTimeErrorCode) { |
| 567 errorCode = CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION; |
| 568 break; |
| 569 } |
| 570 if (error.errorCode is CheckedModeCompileTimeErrorCode) { |
| 571 errorCode = |
| 572 CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION; |
| 573 break; |
| 574 } |
| 575 } |
| 576 if (errorCode != null) { |
| 577 errorReporter.reportErrorForNode(errorCode, node); |
| 578 } |
| 579 } |
| 580 |
| 581 var fieldInitVisitor = new ConstantVisitor(this, externalErrorReporter, |
554 lexicalEnvironment: typeArgumentMap); | 582 lexicalEnvironment: typeArgumentMap); |
555 // Start with final fields that are initialized at their declaration site. | 583 // Start with final fields that are initialized at their declaration site. |
556 List<FieldElement> fields = constructor.enclosingElement.fields; | 584 List<FieldElement> fields = constructor.enclosingElement.fields; |
557 for (int i = 0; i < fields.length; i++) { | 585 for (int i = 0; i < fields.length; i++) { |
558 FieldElement field = fields[i]; | 586 FieldElement field = fields[i]; |
559 if ((field.isFinal || field.isConst) && | 587 if ((field.isFinal || field.isConst) && |
560 !field.isStatic && | 588 !field.isStatic && |
561 field is ConstFieldElementImpl) { | 589 field is ConstFieldElementImpl) { |
562 validator.beforeGetFieldEvaluationResult(field); | 590 validator.beforeGetFieldEvaluationResult(field); |
563 | 591 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); | 694 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); |
667 } | 695 } |
668 fieldMap[fieldName] = argumentValue; | 696 fieldMap[fieldName] = argumentValue; |
669 } | 697 } |
670 } | 698 } |
671 String name = baseParameter.name; | 699 String name = baseParameter.name; |
672 parameterMap[name] = argumentValue; | 700 parameterMap[name] = argumentValue; |
673 } | 701 } |
674 } | 702 } |
675 ConstantVisitor initializerVisitor = new ConstantVisitor( | 703 ConstantVisitor initializerVisitor = new ConstantVisitor( |
676 this, errorReporter, | 704 this, externalErrorReporter, |
677 lexicalEnvironment: parameterMap); | 705 lexicalEnvironment: parameterMap); |
678 String superName = null; | 706 String superName = null; |
679 NodeList<Expression> superArguments = null; | 707 NodeList<Expression> superArguments = null; |
680 for (ConstructorInitializer initializer in initializers) { | 708 for (ConstructorInitializer initializer in initializers) { |
681 if (initializer is ConstructorFieldInitializer) { | 709 if (initializer is ConstructorFieldInitializer) { |
682 Expression initializerExpression = initializer.expression; | 710 Expression initializerExpression = initializer.expression; |
683 DartObjectImpl evaluationResult = | 711 DartObjectImpl evaluationResult = |
684 initializerExpression.accept(initializerVisitor); | 712 initializerExpression.accept(initializerVisitor); |
685 if (evaluationResult != null) { | 713 if (evaluationResult != null) { |
686 String fieldName = initializer.fieldName.name; | 714 String fieldName = initializer.fieldName.name; |
(...skipping 18 matching lines...) Expand all Loading... |
705 SimpleIdentifier name = initializer.constructorName; | 733 SimpleIdentifier name = initializer.constructorName; |
706 if (name != null) { | 734 if (name != null) { |
707 superName = name.name; | 735 superName = name.name; |
708 } | 736 } |
709 superArguments = initializer.argumentList.arguments; | 737 superArguments = initializer.argumentList.arguments; |
710 } else if (initializer is RedirectingConstructorInvocation) { | 738 } else if (initializer is RedirectingConstructorInvocation) { |
711 // This is a redirecting constructor, so just evaluate the constructor | 739 // This is a redirecting constructor, so just evaluate the constructor |
712 // it redirects to. | 740 // it redirects to. |
713 ConstructorElement constructor = initializer.staticElement; | 741 ConstructorElement constructor = initializer.staticElement; |
714 if (constructor != null && constructor.isConst) { | 742 if (constructor != null && constructor.isConst) { |
715 return evaluateConstructorCall( | 743 DartObjectImpl result = evaluateConstructorCall( |
716 node, | 744 node, |
717 initializer.argumentList.arguments, | 745 initializer.argumentList.arguments, |
718 constructor, | 746 constructor, |
719 initializerVisitor, | 747 initializerVisitor, |
720 errorReporter, | 748 externalErrorReporter, |
721 invocation: invocation); | 749 invocation: invocation); |
| 750 reportLocalErrorForRecordedExternalErrors(); |
| 751 return result; |
722 } | 752 } |
723 } | 753 } |
724 } | 754 } |
725 // Evaluate explicit or implicit call to super(). | 755 // Evaluate explicit or implicit call to super(). |
726 InterfaceType superclass = definingClass.superclass; | 756 InterfaceType superclass = definingClass.superclass; |
727 if (superclass != null && !superclass.isObject) { | 757 if (superclass != null && !superclass.isObject) { |
728 ConstructorElement superConstructor = | 758 ConstructorElement superConstructor = |
729 superclass.lookUpConstructor(superName, constructor.library); | 759 superclass.lookUpConstructor(superName, constructor.library); |
730 if (superConstructor != null) { | 760 if (superConstructor != null) { |
731 if (superArguments == null) { | 761 if (superArguments == null) { |
732 superArguments = astFactory.nodeList/*<Expression>*/(null); | 762 superArguments = astFactory.nodeList/*<Expression>*/(null); |
733 } | 763 } |
734 | 764 |
735 evaluateSuperConstructorCall(node, fieldMap, superConstructor, | 765 evaluateSuperConstructorCall(node, fieldMap, superConstructor, |
736 superArguments, initializerVisitor, errorReporter); | 766 superArguments, initializerVisitor, externalErrorReporter); |
737 } | 767 } |
738 } | 768 } |
| 769 reportLocalErrorForRecordedExternalErrors(); |
739 return new DartObjectImpl( | 770 return new DartObjectImpl( |
740 definingClass, new GenericState(fieldMap, invocation: invocation)); | 771 definingClass, new GenericState(fieldMap, invocation: invocation)); |
741 } | 772 } |
742 | 773 |
743 void evaluateSuperConstructorCall( | 774 void evaluateSuperConstructorCall( |
744 AstNode node, | 775 AstNode node, |
745 HashMap<String, DartObjectImpl> fieldMap, | 776 HashMap<String, DartObjectImpl> fieldMap, |
746 ConstructorElement superConstructor, | 777 ConstructorElement superConstructor, |
747 List<Expression> superArguments, | 778 List<Expression> superArguments, |
748 ConstantVisitor initializerVisitor, | 779 ConstantVisitor initializerVisitor, |
(...skipping 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2096 } | 2127 } |
2097 | 2128 |
2098 @override | 2129 @override |
2099 String toString() { | 2130 String toString() { |
2100 if (value == null) { | 2131 if (value == null) { |
2101 return "error"; | 2132 return "error"; |
2102 } | 2133 } |
2103 return value.toString(); | 2134 return value.toString(); |
2104 } | 2135 } |
2105 } | 2136 } |
OLD | NEW |