Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: pkg/analyzer/lib/src/generated/constant.dart

Issue 1121313004: Move validation logic for constant evaluation into its own class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.constant; 8 library engine.constant;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 SuperConstructorInvocation visitSuperConstructorInvocation( 179 SuperConstructorInvocation visitSuperConstructorInvocation(
180 SuperConstructorInvocation node) { 180 SuperConstructorInvocation node) {
181 SuperConstructorInvocation invocation = 181 SuperConstructorInvocation invocation =
182 super.visitSuperConstructorInvocation(node); 182 super.visitSuperConstructorInvocation(node);
183 invocation.staticElement = node.staticElement; 183 invocation.staticElement = node.staticElement;
184 return invocation; 184 return invocation;
185 } 185 }
186 } 186 }
187 187
188 /** 188 /**
189 * Interface used by unit tests to verify correct dependency analysis during
190 * constant evaluation.
191 */
192 abstract class ConstantEvaluationValidator {
193 /**
194 * This method is called just before computing the constant value associated
195 * with [constNode]. Unit tests will override this method to introduce
196 * additional error checking.
197 */
198 void beforeComputeValue(AstNode constNode);
199
200 /**
201 * This method is called just before getting the constant initializers
202 * associated with the [constructor]. Unit tests will override this method to
203 * introduce additional error checking.
204 */
205 void beforeGetConstantInitializers(ConstructorElement constructor);
206
207 /**
208 * This method is called just before retrieving an evaluation result from an
209 * AST node. Unit tests will override it to introduce additional error
210 * checking.
211 */
212 void beforeGetEvaluationResult(AstNode node);
213
214 /**
215 * This method is called just before getting the constant value of a field
216 * with an initializer. Unit tests will override this method to introduce
217 * additional error checking.
218 */
219 void beforeGetFieldEvaluationResult(FieldElementImpl field);
220
221 /**
222 * This method is called just before getting a parameter's default value. Unit
223 * tests will override this method to introduce additional error checking.
224 */
225 void beforeGetParameterDefault(ParameterElement parameter);
226 }
227
228 /**
229 * Implementation of [ConstantEvaluationValidator] used in production; does no
230 * validation.
231 */
232 class ConstantEvaluationValidator_ForProduction
233 implements ConstantEvaluationValidator {
234 @override
235 void beforeComputeValue(AstNode constNode) {}
236
237 @override
238 void beforeGetConstantInitializers(ConstructorElement constructor) {}
239
240 @override
241 void beforeGetEvaluationResult(AstNode node) {}
242
243 @override
244 void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
245
246 @override
247 void beforeGetParameterDefault(ParameterElement parameter) {}
248 }
249
250 /**
189 * Instances of the class `ConstantEvaluator` evaluate constant expressions to 251 * Instances of the class `ConstantEvaluator` evaluate constant expressions to
190 * produce their compile-time value. According to the Dart Language 252 * produce their compile-time value. According to the Dart Language
191 * Specification: 253 * Specification:
192 * <blockquote> 254 * <blockquote>
193 * A constant expression is one of the following: 255 * A constant expression is one of the following:
194 * * A literal number. 256 * * A literal number.
195 * * A literal boolean. 257 * * A literal boolean.
196 * * A literal string where any interpolated expression is a compile-time 258 * * A literal string where any interpolated expression is a compile-time
197 * constant that evaluates to a numeric, string or boolean value or to 259 * constant that evaluates to a numeric, string or boolean value or to
198 * <b>null</b>. 260 * <b>null</b>.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 /** 317 /**
256 * Initialize a newly created evaluator to evaluate expressions in the given 318 * Initialize a newly created evaluator to evaluate expressions in the given
257 * [source]. The [typeProvider] is the type provider used to access known 319 * [source]. The [typeProvider] is the type provider used to access known
258 * types. 320 * types.
259 */ 321 */
260 ConstantEvaluator(this._source, this._typeProvider); 322 ConstantEvaluator(this._source, this._typeProvider);
261 323
262 EvaluationResult evaluate(Expression expression) { 324 EvaluationResult evaluate(Expression expression) {
263 RecordingErrorListener errorListener = new RecordingErrorListener(); 325 RecordingErrorListener errorListener = new RecordingErrorListener();
264 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); 326 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
265 DartObjectImpl result = expression 327 DartObjectImpl result =
266 .accept(new ConstantVisitor.con1(_typeProvider, errorReporter)); 328 expression.accept(new ConstantVisitor(_typeProvider, errorReporter));
267 if (result != null) { 329 if (result != null) {
268 return EvaluationResult.forValue(result); 330 return EvaluationResult.forValue(result);
269 } 331 }
270 return EvaluationResult.forErrors(errorListener.errors); 332 return EvaluationResult.forErrors(errorListener.errors);
271 } 333 }
272 } 334 }
273 335
274 /** 336 /**
275 * A visitor used to traverse the AST structures of all of the compilation units 337 * A visitor used to traverse the AST structures of all of the compilation units
276 * being resolved and build tables of the constant variables, constant 338 * being resolved and build tables of the constant variables, constant
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 /** 471 /**
410 * RegExp that validates a non-empty non-private symbol. 472 * RegExp that validates a non-empty non-private symbol.
411 * From sdk/lib/internal/symbol.dart. 473 * From sdk/lib/internal/symbol.dart.
412 */ 474 */
413 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp( 475 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
414 "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$ |[.](?!\$)))+?\$"); 476 "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$ |[.](?!\$)))+?\$");
415 477
416 /** 478 /**
417 * The type provider used to access the known types. 479 * The type provider used to access the known types.
418 */ 480 */
419 TypeProvider typeProvider; 481 final TypeProvider typeProvider;
482
483 /**
484 * Validator used to verify correct dependency analysis when running unit
485 * tests.
486 */
487 final ConstantEvaluationValidator validator;
420 488
421 /** 489 /**
422 * The object used to find constant variables and constant constructor 490 * The object used to find constant variables and constant constructor
423 * invocations in the compilation units that were added. 491 * invocations in the compilation units that were added.
424 */ 492 */
425 ConstantFinder _constantFinder = new ConstantFinder(); 493 ConstantFinder _constantFinder = new ConstantFinder();
426 494
427 /** 495 /**
428 * A graph in which the nodes are the constants, and the edges are from each 496 * A graph in which the nodes are the constants, and the edges are from each
429 * constant to the other constants that are referenced by it. 497 * constant to the other constants that are referenced by it.
(...skipping 24 matching lines...) Expand all
454 /** 522 /**
455 * The set of variables declared on the command line using '-D'. 523 * The set of variables declared on the command line using '-D'.
456 */ 524 */
457 final DeclaredVariables _declaredVariables; 525 final DeclaredVariables _declaredVariables;
458 526
459 /** 527 /**
460 * Initialize a newly created constant value computer. The [typeProvider] is 528 * Initialize a newly created constant value computer. The [typeProvider] is
461 * the type provider used to access known types. The [declaredVariables] is 529 * the type provider used to access known types. The [declaredVariables] is
462 * the set of variables declared on the command line using '-D'. 530 * the set of variables declared on the command line using '-D'.
463 */ 531 */
464 ConstantValueComputer(TypeProvider typeProvider, this._declaredVariables) { 532 ConstantValueComputer(this.typeProvider, this._declaredVariables,
465 this.typeProvider = typeProvider; 533 [ConstantEvaluationValidator validator])
466 } 534 : validator = validator != null
535 ? validator
536 : new ConstantEvaluationValidator_ForProduction();
467 537
468 /** 538 /**
469 * Add the constants in the given compilation [unit] to the list of constants 539 * Add the constants in the given compilation [unit] to the list of constants
470 * whose value needs to be computed. 540 * whose value needs to be computed.
471 */ 541 */
472 void add(CompilationUnit unit) { 542 void add(CompilationUnit unit) {
473 unit.accept(_constantFinder); 543 unit.accept(_constantFinder);
474 } 544 }
475 545
476 /** 546 /**
477 * This method is called just before computing the constant value associated
478 * with [constNode]. Unit tests will override this method to introduce
479 * additional error checking.
480 */
481 void beforeComputeValue(AstNode constNode) {}
482
483 /**
484 * This method is called just before getting the constant value of a field
485 * with an initializer. Unit tests will override this method to introduce
486 * additional error checking.
487 */
488 void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
489
490 /**
491 * This method is called just before getting the constant initializers
492 * associated with the [constructor]. Unit tests will override this method to
493 * introduce additional error checking.
494 */
495 void beforeGetConstantInitializers(ConstructorElement constructor) {}
496
497 /**
498 * This method is called just before getting a parameter's default value. Unit
499 * tests will override this method to introduce additional error checking.
500 */
501 void beforeGetParameterDefault(ParameterElement parameter) {}
502
503 /**
504 * Compute values for all of the constants in the compilation units that were 547 * Compute values for all of the constants in the compilation units that were
505 * added. 548 * added.
506 */ 549 */
507 void computeValues() { 550 void computeValues() {
508 _variableDeclarationMap = _constantFinder.variableMap; 551 _variableDeclarationMap = _constantFinder.variableMap;
509 constructorDeclarationMap = _constantFinder.constructorMap; 552 constructorDeclarationMap = _constantFinder.constructorMap;
510 _constructorInvocations = _constantFinder.constructorInvocations; 553 _constructorInvocations = _constantFinder.constructorInvocations;
511 _annotations = _constantFinder.annotations; 554 _annotations = _constantFinder.annotations;
512 _variableDeclarationMap.values.forEach((VariableDeclaration declaration) { 555 _variableDeclarationMap.values.forEach((VariableDeclaration declaration) {
513 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, 556 ReferenceFinder referenceFinder = new ReferenceFinder(declaration,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 } 650 }
608 } 651 }
609 // Since no constant can depend on an annotation, we don't waste time 652 // Since no constant can depend on an annotation, we don't waste time
610 // including them in the topological sort. We just process all the 653 // including them in the topological sort. We just process all the
611 // annotations after all other constants are finished. 654 // annotations after all other constants are finished.
612 for (Annotation annotation in _annotations) { 655 for (Annotation annotation in _annotations) {
613 _computeValueFor(annotation); 656 _computeValueFor(annotation);
614 } 657 }
615 } 658 }
616 659
617 /**
618 * Create the ConstantVisitor used to evaluate constants. Unit tests will
619 * override this method to introduce additional error checking.
620 */
621 ConstantVisitor createConstantVisitor(ErrorReporter errorReporter) =>
622 new ConstantVisitor.con1(typeProvider, errorReporter);
623
624 ConstructorDeclaration findConstructorDeclaration( 660 ConstructorDeclaration findConstructorDeclaration(
625 ConstructorElement constructor) => 661 ConstructorElement constructor) =>
626 constructorDeclarationMap[_getConstructorBase(constructor)]; 662 constructorDeclarationMap[_getConstructorBase(constructor)];
627 663
628 VariableDeclaration findVariableDeclaration( 664 VariableDeclaration findVariableDeclaration(
629 PotentiallyConstVariableElement variable) => 665 PotentiallyConstVariableElement variable) =>
630 _variableDeclarationMap[variable]; 666 _variableDeclarationMap[variable];
631 667
632 /** 668 /**
633 * Check that the arguments to a call to fromEnvironment() are correct. The 669 * Check that the arguments to a call to fromEnvironment() are correct. The
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 return false; 726 return false;
691 } 727 }
692 String name = argumentValues[0].stringValue; 728 String name = argumentValues[0].stringValue;
693 return isValidPublicSymbol(name); 729 return isValidPublicSymbol(name);
694 } 730 }
695 731
696 /** 732 /**
697 * Compute a value for the given [constNode]. 733 * Compute a value for the given [constNode].
698 */ 734 */
699 void _computeValueFor(AstNode constNode) { 735 void _computeValueFor(AstNode constNode) {
700 beforeComputeValue(constNode); 736 validator.beforeComputeValue(constNode);
701 if (constNode is VariableDeclaration) { 737 if (constNode is VariableDeclaration) {
702 VariableElement element = constNode.element; 738 VariableElement element = constNode.element;
703 RecordingErrorListener errorListener = new RecordingErrorListener(); 739 RecordingErrorListener errorListener = new RecordingErrorListener();
704 ErrorReporter errorReporter = 740 ErrorReporter errorReporter =
705 new ErrorReporter(errorListener, element.source); 741 new ErrorReporter(errorListener, element.source);
706 DartObjectImpl dartObject = 742 DartObjectImpl dartObject =
707 (element as PotentiallyConstVariableElement).constantInitializer 743 (element as PotentiallyConstVariableElement).constantInitializer
708 .accept(createConstantVisitor(errorReporter)); 744 .accept(
745 new ConstantVisitor(typeProvider, errorReporter, validator));
709 if (dartObject != null) { 746 if (dartObject != null) {
710 if (!_runtimeTypeMatch(dartObject, element.type)) { 747 if (!_runtimeTypeMatch(dartObject, element.type)) {
711 errorReporter.reportErrorForElement( 748 errorReporter.reportErrorForElement(
712 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [ 749 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [
713 dartObject.type, 750 dartObject.type,
714 element.type 751 element.type
715 ]); 752 ]);
716 } 753 }
717 } 754 }
718 (element as VariableElementImpl).evaluationResult = 755 (element as VariableElementImpl).evaluationResult =
719 new EvaluationResultImpl.con2(dartObject, errorListener.errors); 756 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
720 } else if (constNode is InstanceCreationExpression) { 757 } else if (constNode is InstanceCreationExpression) {
721 InstanceCreationExpression expression = constNode; 758 InstanceCreationExpression expression = constNode;
722 ConstructorElement constructor = expression.staticElement; 759 ConstructorElement constructor = expression.staticElement;
723 if (constructor == null) { 760 if (constructor == null) {
724 // Couldn't resolve the constructor so we can't compute a value. 761 // Couldn't resolve the constructor so we can't compute a value.
725 // No problem - the error has already been reported. 762 // No problem - the error has already been reported.
726 // But we still need to store an evaluation result. 763 // But we still need to store an evaluation result.
727 expression.constantHandle.evaluationResult = 764 expression.constantHandle.evaluationResult =
728 new EvaluationResultImpl.con1(null); 765 new EvaluationResultImpl.con1(null);
729 return; 766 return;
730 } 767 }
731 RecordingErrorListener errorListener = new RecordingErrorListener(); 768 RecordingErrorListener errorListener = new RecordingErrorListener();
732 CompilationUnit sourceCompilationUnit = 769 CompilationUnit sourceCompilationUnit =
733 expression.getAncestor((node) => node is CompilationUnit); 770 expression.getAncestor((node) => node is CompilationUnit);
734 ErrorReporter errorReporter = new ErrorReporter( 771 ErrorReporter errorReporter = new ErrorReporter(
735 errorListener, sourceCompilationUnit.element.source); 772 errorListener, sourceCompilationUnit.element.source);
736 ConstantVisitor constantVisitor = createConstantVisitor(errorReporter); 773 ConstantVisitor constantVisitor =
774 new ConstantVisitor(typeProvider, errorReporter, validator);
737 DartObjectImpl result = _evaluateConstructorCall(constNode, 775 DartObjectImpl result = _evaluateConstructorCall(constNode,
738 expression.argumentList.arguments, constructor, constantVisitor, 776 expression.argumentList.arguments, constructor, constantVisitor,
739 errorReporter); 777 errorReporter);
740 expression.constantHandle.evaluationResult = 778 expression.constantHandle.evaluationResult =
741 new EvaluationResultImpl.con2(result, errorListener.errors); 779 new EvaluationResultImpl.con2(result, errorListener.errors);
742 } else if (constNode is ConstructorDeclaration) { 780 } else if (constNode is ConstructorDeclaration) {
743 // No evaluation needs to be done; constructor declarations are only in 781 // No evaluation needs to be done; constructor declarations are only in
744 // the dependency graph to ensure that any constants referred to in 782 // the dependency graph to ensure that any constants referred to in
745 // initializer lists and parameter defaults are evaluated before 783 // initializer lists and parameter defaults are evaluated before
746 // invocations of the constructor. However we do need to annotate the 784 // invocations of the constructor. However we do need to annotate the
747 // element as being free of constant evaluation cycles so that later code 785 // element as being free of constant evaluation cycles so that later code
748 // will know that it is safe to evaluate. 786 // will know that it is safe to evaluate.
749 ConstructorElementImpl constructor = constNode.element; 787 ConstructorElementImpl constructor = constNode.element;
750 constructor.isCycleFree = true; 788 constructor.isCycleFree = true;
751 } else if (constNode is FormalParameter) { 789 } else if (constNode is FormalParameter) {
752 if (constNode is DefaultFormalParameter) { 790 if (constNode is DefaultFormalParameter) {
753 DefaultFormalParameter parameter = constNode; 791 DefaultFormalParameter parameter = constNode;
754 ParameterElement element = parameter.element; 792 ParameterElement element = parameter.element;
755 Expression defaultValue = parameter.defaultValue; 793 Expression defaultValue = parameter.defaultValue;
756 if (defaultValue != null) { 794 if (defaultValue != null) {
757 RecordingErrorListener errorListener = new RecordingErrorListener(); 795 RecordingErrorListener errorListener = new RecordingErrorListener();
758 ErrorReporter errorReporter = 796 ErrorReporter errorReporter =
759 new ErrorReporter(errorListener, element.source); 797 new ErrorReporter(errorListener, element.source);
760 DartObjectImpl dartObject = 798 DartObjectImpl dartObject = defaultValue.accept(
761 defaultValue.accept(createConstantVisitor(errorReporter)); 799 new ConstantVisitor(typeProvider, errorReporter, validator));
762 (element as ParameterElementImpl).evaluationResult = 800 (element as ParameterElementImpl).evaluationResult =
763 new EvaluationResultImpl.con2(dartObject, errorListener.errors); 801 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
764 } 802 }
765 } 803 }
766 } else if (constNode is Annotation) { 804 } else if (constNode is Annotation) {
767 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 805 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
768 // elementAnnotation is null if the annotation couldn't be resolved, in 806 // elementAnnotation is null if the annotation couldn't be resolved, in
769 // which case we skip it. 807 // which case we skip it.
770 if (elementAnnotation != null) { 808 if (elementAnnotation != null) {
771 Element element = elementAnnotation.element; 809 Element element = elementAnnotation.element;
772 if (element is PropertyAccessorElement && 810 if (element is PropertyAccessorElement &&
773 element.variable is VariableElementImpl) { 811 element.variable is VariableElementImpl) {
774 // The annotation is a reference to a compile-time constant variable. 812 // The annotation is a reference to a compile-time constant variable.
775 // Just copy the evaluation result. 813 // Just copy the evaluation result.
776 VariableElementImpl variableElement = 814 VariableElementImpl variableElement =
777 element.variable as VariableElementImpl; 815 element.variable as VariableElementImpl;
778 elementAnnotation.evaluationResult = variableElement.evaluationResult; 816 elementAnnotation.evaluationResult = variableElement.evaluationResult;
779 } else if (element is ConstructorElementImpl && 817 } else if (element is ConstructorElementImpl &&
780 constNode.arguments != null) { 818 constNode.arguments != null) {
781 RecordingErrorListener errorListener = new RecordingErrorListener(); 819 RecordingErrorListener errorListener = new RecordingErrorListener();
782 CompilationUnit sourceCompilationUnit = 820 CompilationUnit sourceCompilationUnit =
783 constNode.getAncestor((node) => node is CompilationUnit); 821 constNode.getAncestor((node) => node is CompilationUnit);
784 ErrorReporter errorReporter = new ErrorReporter( 822 ErrorReporter errorReporter = new ErrorReporter(
785 errorListener, sourceCompilationUnit.element.source); 823 errorListener, sourceCompilationUnit.element.source);
786 ConstantVisitor constantVisitor = 824 ConstantVisitor constantVisitor =
787 createConstantVisitor(errorReporter); 825 new ConstantVisitor(typeProvider, errorReporter, validator);
788 DartObjectImpl result = _evaluateConstructorCall(constNode, 826 DartObjectImpl result = _evaluateConstructorCall(constNode,
789 constNode.arguments.arguments, element, constantVisitor, 827 constNode.arguments.arguments, element, constantVisitor,
790 errorReporter); 828 errorReporter);
791 elementAnnotation.evaluationResult = 829 elementAnnotation.evaluationResult =
792 new EvaluationResultImpl.con2(result, errorListener.errors); 830 new EvaluationResultImpl.con2(result, errorListener.errors);
793 } else { 831 } else {
794 // This may happen for invalid code (e.g. failing to pass arguments 832 // This may happen for invalid code (e.g. failing to pass arguments
795 // to an annotation which references a const constructor). The error 833 // to an annotation which references a const constructor). The error
796 // is detected elsewhere, so just silently ignore it here. 834 // is detected elsewhere, so just silently ignore it here.
797 elementAnnotation.evaluationResult = 835 elementAnnotation.evaluationResult =
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 definingClass, new SymbolState(argumentValue)); 963 definingClass, new SymbolState(argumentValue));
926 } 964 }
927 // Either it's an external const factory constructor that we can't 965 // Either it's an external const factory constructor that we can't
928 // emulate, or an error occurred (a cycle, or a const constructor trying 966 // emulate, or an error occurred (a cycle, or a const constructor trying
929 // to delegate to a non-const constructor). 967 // to delegate to a non-const constructor).
930 // In the former case, the best we can do is consider it an unknown value. 968 // In the former case, the best we can do is consider it an unknown value.
931 // In the latter case, the error has already been reported, so considering 969 // In the latter case, the error has already been reported, so considering
932 // it an unknown value will suppress further errors. 970 // it an unknown value will suppress further errors.
933 return new DartObjectImpl.validWithUnknownValue(definingClass); 971 return new DartObjectImpl.validWithUnknownValue(definingClass);
934 } 972 }
935 beforeGetConstantInitializers(constructor); 973 validator.beforeGetConstantInitializers(constructor);
936 ConstructorElementImpl constructorBase = _getConstructorBase(constructor); 974 ConstructorElementImpl constructorBase = _getConstructorBase(constructor);
937 List<ConstructorInitializer> initializers = 975 List<ConstructorInitializer> initializers =
938 constructorBase.constantInitializers; 976 constructorBase.constantInitializers;
939 if (initializers == null) { 977 if (initializers == null) {
940 // This can happen in some cases where there are compile errors in the 978 // This can happen in some cases where there are compile errors in the
941 // code being analyzed (for example if the code is trying to create a 979 // code being analyzed (for example if the code is trying to create a
942 // const instance using a non-const constructor, or the node we're 980 // const instance using a non-const constructor, or the node we're
943 // visiting is involved in a cycle). The error has already been reported, 981 // visiting is involved in a cycle). The error has already been reported,
944 // so consider it an unknown value to suppress further errors. 982 // so consider it an unknown value to suppress further errors.
945 return new DartObjectImpl.validWithUnknownValue(definingClass); 983 return new DartObjectImpl.validWithUnknownValue(definingClass);
946 } 984 }
947 HashMap<String, DartObjectImpl> fieldMap = 985 HashMap<String, DartObjectImpl> fieldMap =
948 new HashMap<String, DartObjectImpl>(); 986 new HashMap<String, DartObjectImpl>();
949 // Start with final fields that are initialized at their declaration site. 987 // Start with final fields that are initialized at their declaration site.
950 for (FieldElement field in constructor.enclosingElement.fields) { 988 for (FieldElement field in constructor.enclosingElement.fields) {
951 if ((field.isFinal || field.isConst) && 989 if ((field.isFinal || field.isConst) &&
952 !field.isStatic && 990 !field.isStatic &&
953 field is ConstFieldElementImpl) { 991 field is ConstFieldElementImpl) {
954 beforeGetFieldEvaluationResult(field); 992 validator.beforeGetFieldEvaluationResult(field);
955 EvaluationResultImpl evaluationResult = field.evaluationResult; 993 EvaluationResultImpl evaluationResult = field.evaluationResult;
956 DartType fieldType = 994 DartType fieldType =
957 FieldMember.from(field, constructor.returnType).type; 995 FieldMember.from(field, constructor.returnType).type;
958 DartObjectImpl fieldValue = evaluationResult.value; 996 DartObjectImpl fieldValue = evaluationResult.value;
959 if (fieldValue != null && !_runtimeTypeMatch(fieldValue, fieldType)) { 997 if (fieldValue != null && !_runtimeTypeMatch(fieldValue, fieldType)) {
960 errorReporter.reportErrorForNode( 998 errorReporter.reportErrorForNode(
961 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMA TCH, 999 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMA TCH,
962 node, [fieldValue.type, field.name, fieldType]); 1000 node, [fieldValue.type, field.name, fieldType]);
963 } 1001 }
964 fieldMap[field.name] = evaluationResult.value; 1002 fieldMap[field.name] = evaluationResult.value;
(...skipping 21 matching lines...) Expand all
986 } 1024 }
987 if (errorTarget == null) { 1025 if (errorTarget == null) {
988 // No argument node that we can direct error messages to, because we 1026 // No argument node that we can direct error messages to, because we
989 // are handling an optional parameter that wasn't specified. So just 1027 // are handling an optional parameter that wasn't specified. So just
990 // direct error messages to the constructor call. 1028 // direct error messages to the constructor call.
991 errorTarget = node; 1029 errorTarget = node;
992 } 1030 }
993 if (argumentValue == null && baseParameter is ParameterElementImpl) { 1031 if (argumentValue == null && baseParameter is ParameterElementImpl) {
994 // The parameter is an optional positional parameter for which no value 1032 // The parameter is an optional positional parameter for which no value
995 // was provided, so use the default value. 1033 // was provided, so use the default value.
996 beforeGetParameterDefault(baseParameter); 1034 validator.beforeGetParameterDefault(baseParameter);
997 EvaluationResultImpl evaluationResult = baseParameter.evaluationResult; 1035 EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
998 if (evaluationResult == null) { 1036 if (evaluationResult == null) {
999 // No default was provided, so the default value is null. 1037 // No default was provided, so the default value is null.
1000 argumentValue = typeProvider.nullObject; 1038 argumentValue = typeProvider.nullObject;
1001 } else if (evaluationResult.value != null) { 1039 } else if (evaluationResult.value != null) {
1002 argumentValue = evaluationResult.value; 1040 argumentValue = evaluationResult.value;
1003 } 1041 }
1004 } 1042 }
1005 if (argumentValue != null) { 1043 if (argumentValue != null) {
1006 if (!_runtimeTypeMatch(argumentValue, parameter.type)) { 1044 if (!_runtimeTypeMatch(argumentValue, parameter.type)) {
(...skipping 17 matching lines...) Expand all
1024 } 1062 }
1025 String fieldName = field.name; 1063 String fieldName = field.name;
1026 fieldMap[fieldName] = argumentValue; 1064 fieldMap[fieldName] = argumentValue;
1027 } 1065 }
1028 } else { 1066 } else {
1029 String name = baseParameter.name; 1067 String name = baseParameter.name;
1030 parameterMap[name] = argumentValue; 1068 parameterMap[name] = argumentValue;
1031 } 1069 }
1032 } 1070 }
1033 } 1071 }
1034 ConstantVisitor initializerVisitor = 1072 ConstantVisitor initializerVisitor = new ConstantVisitor(
1035 new ConstantVisitor.con2(typeProvider, parameterMap, errorReporter); 1073 typeProvider, errorReporter, validator, parameterMap);
1036 String superName = null; 1074 String superName = null;
1037 NodeList<Expression> superArguments = null; 1075 NodeList<Expression> superArguments = null;
1038 for (ConstructorInitializer initializer in initializers) { 1076 for (ConstructorInitializer initializer in initializers) {
1039 if (initializer is ConstructorFieldInitializer) { 1077 if (initializer is ConstructorFieldInitializer) {
1040 ConstructorFieldInitializer constructorFieldInitializer = initializer; 1078 ConstructorFieldInitializer constructorFieldInitializer = initializer;
1041 Expression initializerExpression = 1079 Expression initializerExpression =
1042 constructorFieldInitializer.expression; 1080 constructorFieldInitializer.expression;
1043 DartObjectImpl evaluationResult = 1081 DartObjectImpl evaluationResult =
1044 initializerExpression.accept(initializerVisitor); 1082 initializerExpression.accept(initializerVisitor);
1045 if (evaluationResult != null) { 1083 if (evaluationResult != null) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i> 1300 * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
1263 * evaluates to a boolean value. 1301 * evaluates to a boolean value.
1264 * </blockquote> 1302 * </blockquote>
1265 */ 1303 */
1266 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> { 1304 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
1267 /** 1305 /**
1268 * The type provider used to access the known types. 1306 * The type provider used to access the known types.
1269 */ 1307 */
1270 final TypeProvider _typeProvider; 1308 final TypeProvider _typeProvider;
1271 1309
1272 HashMap<String, DartObjectImpl> _lexicalEnvironment; 1310 final HashMap<String, DartObjectImpl> _lexicalEnvironment;
1311
1312 /**
1313 * Validator used to verify correct dependency analysis when running unit
1314 * tests.
1315 */
1316 final ConstantEvaluationValidator validator;
1273 1317
1274 /** 1318 /**
1275 * Error reporter that we use to report errors accumulated while computing the 1319 * Error reporter that we use to report errors accumulated while computing the
1276 * constant. 1320 * constant.
1277 */ 1321 */
1278 final ErrorReporter _errorReporter; 1322 final ErrorReporter _errorReporter;
1279 1323
1280 /** 1324 /**
1281 * Helper class used to compute constant values. 1325 * Helper class used to compute constant values.
1282 */ 1326 */
1283 DartObjectComputer _dartObjectComputer; 1327 DartObjectComputer _dartObjectComputer;
1284 1328
1285 /** 1329 /**
1286 * Initialize a newly created constant visitor. The [_typeProvider] is the 1330 * Initialize a newly created constant visitor. The [_typeProvider] is the
1287 * type provider used to access known types. The [_errorReporter] is used to 1331 * type provider used to access known types. The [_lexicalEnvironment] is a
1288 * report errors found during evaluation. 1332 * map containing values which should override identifiers, or `null` if no
1333 * overriding is necessary. The [_errorReporter] is used to report errors
1334 * found during evaluation. The [validator] is used by unit tests to verify
1335 * correct dependency analysis.
1289 */ 1336 */
1290 ConstantVisitor.con1(this._typeProvider, this._errorReporter) { 1337 ConstantVisitor(this._typeProvider, this._errorReporter,
1291 this._lexicalEnvironment = null; 1338 [ConstantEvaluationValidator validator, this._lexicalEnvironment])
Brian Wilkerson 2015/05/05 00:22:47 It might be better to make these named parameters,
Paul Berry 2015/05/05 14:16:21 Done.
1339 : validator = validator != null
1340 ? validator
1341 : new ConstantEvaluationValidator_ForProduction() {
1292 this._dartObjectComputer = 1342 this._dartObjectComputer =
1293 new DartObjectComputer(_errorReporter, _typeProvider); 1343 new DartObjectComputer(_errorReporter, _typeProvider);
1294 } 1344 }
1295 1345
1296 /** 1346 /**
1297 * Initialize a newly created constant visitor. The [_typeProvider] is the
1298 * type provider used to access known types. The [lexicalEnvironment] is a map
1299 * containing values which should override identifiers, or `null` if no
1300 * overriding is necessary. The [_errorReporter] is used to report errors
1301 * found during evaluation.
1302 */
1303 ConstantVisitor.con2(this._typeProvider,
1304 HashMap<String, DartObjectImpl> lexicalEnvironment, this._errorReporter) {
1305 this._lexicalEnvironment = lexicalEnvironment;
1306 this._dartObjectComputer =
1307 new DartObjectComputer(_errorReporter, _typeProvider);
1308 }
1309
1310 /**
1311 * This method is called just before retrieving an evaluation result from an
1312 * AST node. Unit tests will override it to introduce additional error
1313 * checking.
1314 */
1315 void beforeGetEvaluationResult(AstNode node) {}
1316
1317 /**
1318 * Return `true` if the given [element] represents the `length` getter in 1347 * Return `true` if the given [element] represents the `length` getter in
1319 * class 'String'. 1348 * class 'String'.
1320 */ 1349 */
1321 bool isStringLength(Element element) { 1350 bool isStringLength(Element element) {
1322 if (element is PropertyAccessorElement) { 1351 if (element is PropertyAccessorElement) {
1323 if (element.isGetter && element.name == 'length') { 1352 if (element.isGetter && element.name == 'length') {
1324 return element.enclosingElement == _typeProvider.stringType.element; 1353 return element.enclosingElement == _typeProvider.stringType.element;
1325 } 1354 }
1326 } 1355 }
1327 return false; 1356 return false;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value)); 1476 new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
1448 1477
1449 @override 1478 @override
1450 DartObjectImpl visitInstanceCreationExpression( 1479 DartObjectImpl visitInstanceCreationExpression(
1451 InstanceCreationExpression node) { 1480 InstanceCreationExpression node) {
1452 if (!node.isConst) { 1481 if (!node.isConst) {
1453 // TODO(brianwilkerson) Figure out which error to report. 1482 // TODO(brianwilkerson) Figure out which error to report.
1454 _error(node, null); 1483 _error(node, null);
1455 return null; 1484 return null;
1456 } 1485 }
1457 beforeGetEvaluationResult(node); 1486 validator.beforeGetEvaluationResult(node);
1458 EvaluationResultImpl result = node.evaluationResult; 1487 EvaluationResultImpl result = node.evaluationResult;
1459 if (result != null) { 1488 if (result != null) {
1460 return result.value; 1489 return result.value;
1461 } 1490 }
1462 // TODO(brianwilkerson) Figure out which error to report. 1491 // TODO(brianwilkerson) Figure out which error to report.
1463 _error(node, null); 1492 _error(node, null);
1464 return null; 1493 return null;
1465 } 1494 }
1466 1495
1467 @override 1496 @override
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 * Return the constant value of the static constant represented by the given 1740 * Return the constant value of the static constant represented by the given
1712 * [element]. The [node] is the node to be used if an error needs to be 1741 * [element]. The [node] is the node to be used if an error needs to be
1713 * reported. 1742 * reported.
1714 */ 1743 */
1715 DartObjectImpl _getConstantValue(AstNode node, Element element) { 1744 DartObjectImpl _getConstantValue(AstNode node, Element element) {
1716 if (element is PropertyAccessorElement) { 1745 if (element is PropertyAccessorElement) {
1717 element = (element as PropertyAccessorElement).variable; 1746 element = (element as PropertyAccessorElement).variable;
1718 } 1747 }
1719 if (element is VariableElementImpl) { 1748 if (element is VariableElementImpl) {
1720 VariableElementImpl variableElementImpl = element; 1749 VariableElementImpl variableElementImpl = element;
1721 beforeGetEvaluationResult(node); 1750 validator.beforeGetEvaluationResult(node);
1722 EvaluationResultImpl value = variableElementImpl.evaluationResult; 1751 EvaluationResultImpl value = variableElementImpl.evaluationResult;
1723 if (variableElementImpl.isConst && value != null) { 1752 if (variableElementImpl.isConst && value != null) {
1724 return value.value; 1753 return value.value;
1725 } 1754 }
1726 } else if (element is ExecutableElement) { 1755 } else if (element is ExecutableElement) {
1727 ExecutableElement function = element; 1756 ExecutableElement function = element;
1728 if (function.isStatic) { 1757 if (function.isStatic) {
1729 ParameterizedType functionType = function.type; 1758 ParameterizedType functionType = function.type;
1730 if (functionType == null) { 1759 if (functionType == null) {
1731 functionType = _typeProvider.functionType; 1760 functionType = _typeProvider.functionType;
(...skipping 3437 matching lines...) Expand 10 before | Expand all | Expand 10 after
5169 return BoolState.from(_element == rightElement); 5198 return BoolState.from(_element == rightElement);
5170 } else if (rightOperand is DynamicState) { 5199 } else if (rightOperand is DynamicState) {
5171 return BoolState.UNKNOWN_VALUE; 5200 return BoolState.UNKNOWN_VALUE;
5172 } 5201 }
5173 return BoolState.FALSE_STATE; 5202 return BoolState.FALSE_STATE;
5174 } 5203 }
5175 5204
5176 @override 5205 @override
5177 String toString() => _element == null ? "-unknown-" : _element.name; 5206 String toString() => _element == null ? "-unknown-" : _element.name;
5178 } 5207 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698