Chromium Code Reviews| 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 // 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |