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

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

Issue 1129143003: Store elements in the constant eval dependency graph rather than AST nodes. (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/element.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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 definingClass, new SymbolState(argumentValue)); 421 definingClass, new SymbolState(argumentValue));
422 } 422 }
423 // Either it's an external const factory constructor that we can't 423 // Either it's an external const factory constructor that we can't
424 // emulate, or an error occurred (a cycle, or a const constructor trying 424 // emulate, or an error occurred (a cycle, or a const constructor trying
425 // to delegate to a non-const constructor). 425 // to delegate to a non-const constructor).
426 // In the former case, the best we can do is consider it an unknown value. 426 // In the former case, the best we can do is consider it an unknown value.
427 // In the latter case, the error has already been reported, so considering 427 // In the latter case, the error has already been reported, so considering
428 // it an unknown value will suppress further errors. 428 // it an unknown value will suppress further errors.
429 return new DartObjectImpl.validWithUnknownValue(definingClass); 429 return new DartObjectImpl.validWithUnknownValue(definingClass);
430 } 430 }
431 validator.beforeGetConstantInitializers(constructor);
432 ConstructorElementImpl constructorBase = _getConstructorBase(constructor); 431 ConstructorElementImpl constructorBase = _getConstructorBase(constructor);
432 validator.beforeGetConstantInitializers(constructorBase);
433 List<ConstructorInitializer> initializers = 433 List<ConstructorInitializer> initializers =
434 constructorBase.constantInitializers; 434 constructorBase.constantInitializers;
435 if (initializers == null) { 435 if (initializers == null) {
436 // This can happen in some cases where there are compile errors in the 436 // This can happen in some cases where there are compile errors in the
437 // code being analyzed (for example if the code is trying to create a 437 // code being analyzed (for example if the code is trying to create a
438 // const instance using a non-const constructor, or the node we're 438 // const instance using a non-const constructor, or the node we're
439 // visiting is involved in a cycle). The error has already been reported, 439 // visiting is involved in a cycle). The error has already been reported,
440 // so consider it an unknown value to suppress further errors. 440 // so consider it an unknown value to suppress further errors.
441 return new DartObjectImpl.validWithUnknownValue(definingClass); 441 return new DartObjectImpl.validWithUnknownValue(definingClass);
442 } 442 }
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 } 695 }
696 } 696 }
697 697
698 /** 698 /**
699 * Interface used by unit tests to verify correct dependency analysis during 699 * Interface used by unit tests to verify correct dependency analysis during
700 * constant evaluation. 700 * constant evaluation.
701 */ 701 */
702 abstract class ConstantEvaluationValidator { 702 abstract class ConstantEvaluationValidator {
703 /** 703 /**
704 * This method is called just before computing the constant value associated 704 * This method is called just before computing the constant value associated
705 * with [constNode]. Unit tests will override this method to introduce 705 * with [element]. Unit tests will override this method to introduce
706 * additional error checking. 706 * additional error checking.
707 */ 707 */
708 void beforeComputeValue(AstNode constNode); 708 void beforeComputeValue(Element element);
709 709
710 /** 710 /**
711 * This method is called just before getting the constant initializers 711 * This method is called just before getting the constant initializers
712 * associated with the [constructor]. Unit tests will override this method to 712 * associated with the [constructor]. Unit tests will override this method to
713 * introduce additional error checking. 713 * introduce additional error checking.
714 */ 714 */
715 void beforeGetConstantInitializers(ConstructorElement constructor); 715 void beforeGetConstantInitializers(ConstructorElement constructor);
716 716
717 /** 717 /**
718 * This method is called just before retrieving an evaluation result from an 718 * This method is called just before retrieving an evaluation result from an
719 * AST node. Unit tests will override it to introduce additional error 719 * element. Unit tests will override it to introduce additional error
720 * checking. 720 * checking.
721 */ 721 */
722 void beforeGetEvaluationResult(AstNode node); 722 void beforeGetEvaluationResult(Element element);
723 723
724 /** 724 /**
725 * This method is called just before getting the constant value of a field 725 * This method is called just before getting the constant value of a field
726 * with an initializer. Unit tests will override this method to introduce 726 * with an initializer. Unit tests will override this method to introduce
727 * additional error checking. 727 * additional error checking.
728 */ 728 */
729 void beforeGetFieldEvaluationResult(FieldElementImpl field); 729 void beforeGetFieldEvaluationResult(FieldElementImpl field);
730 730
731 /** 731 /**
732 * This method is called just before getting a parameter's default value. Unit 732 * This method is called just before getting a parameter's default value. Unit
733 * tests will override this method to introduce additional error checking. 733 * tests will override this method to introduce additional error checking.
734 */ 734 */
735 void beforeGetParameterDefault(ParameterElement parameter); 735 void beforeGetParameterDefault(ParameterElement parameter);
736 } 736 }
737 737
738 /** 738 /**
739 * Implementation of [ConstantEvaluationValidator] used in production; does no 739 * Implementation of [ConstantEvaluationValidator] used in production; does no
740 * validation. 740 * validation.
741 */ 741 */
742 class ConstantEvaluationValidator_ForProduction 742 class ConstantEvaluationValidator_ForProduction
743 implements ConstantEvaluationValidator { 743 implements ConstantEvaluationValidator {
744 @override 744 @override
745 void beforeComputeValue(AstNode constNode) {} 745 void beforeComputeValue(Element element) {}
746 746
747 @override 747 @override
748 void beforeGetConstantInitializers(ConstructorElement constructor) {} 748 void beforeGetConstantInitializers(ConstructorElement constructor) {}
749 749
750 @override 750 @override
751 void beforeGetEvaluationResult(AstNode node) {} 751 void beforeGetEvaluationResult(Element element) {}
752 752
753 @override 753 @override
754 void beforeGetFieldEvaluationResult(FieldElementImpl field) {} 754 void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
755 755
756 @override 756 @override
757 void beforeGetParameterDefault(ParameterElement parameter) {} 757 void beforeGetParameterDefault(ParameterElement parameter) {}
758 } 758 }
759 759
760 /** 760 /**
761 * Instances of the class `ConstantEvaluator` evaluate constant expressions to 761 * Instances of the class `ConstantEvaluator` evaluate constant expressions to
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 845 }
846 846
847 /** 847 /**
848 * A visitor used to traverse the AST structures of all of the compilation units 848 * A visitor used to traverse the AST structures of all of the compilation units
849 * being resolved and build tables of the constant variables, constant 849 * being resolved and build tables of the constant variables, constant
850 * constructors, constant constructor invocations, and annotations found in 850 * constructors, constant constructor invocations, and annotations found in
851 * those compilation units. 851 * those compilation units.
852 */ 852 */
853 class ConstantFinder extends RecursiveAstVisitor<Object> { 853 class ConstantFinder extends RecursiveAstVisitor<Object> {
854 /** 854 /**
855 * A table mapping constant variable elements to the declarations of those 855 * The elements whose constant values need to be computed, with the exception
856 * variables. 856 * of annotations.
857 */ 857 */
858 final HashMap<PotentiallyConstVariableElement, VariableDeclaration> variableMa p = 858 HashSet<Element> constantsToCompute = new HashSet<Element>();
859 new HashMap<PotentiallyConstVariableElement, VariableDeclaration>();
860
861 /**
862 * A table mapping constant constructors to the declarations of those
863 * constructors.
864 */
865 final HashMap<ConstructorElement, ConstructorDeclaration> constructorMap =
866 new HashMap<ConstructorElement, ConstructorDeclaration>();
867 859
868 /** 860 /**
869 * A collection of annotations. 861 * A collection of annotations.
870 */ 862 */
871 final List<Annotation> annotations = <Annotation>[]; 863 final List<Annotation> annotations = <Annotation>[];
872 864
873 /** 865 /**
874 * True if instance variables marked as "final" should be treated as "const". 866 * True if instance variables marked as "final" should be treated as "const".
875 */ 867 */
876 bool treatFinalInstanceVarAsConst = false; 868 bool treatFinalInstanceVarAsConst = false;
(...skipping 20 matching lines...) Expand all
897 treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst; 889 treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
898 } 890 }
899 } 891 }
900 892
901 @override 893 @override
902 Object visitConstructorDeclaration(ConstructorDeclaration node) { 894 Object visitConstructorDeclaration(ConstructorDeclaration node) {
903 super.visitConstructorDeclaration(node); 895 super.visitConstructorDeclaration(node);
904 if (node.constKeyword != null) { 896 if (node.constKeyword != null) {
905 ConstructorElement element = node.element; 897 ConstructorElement element = node.element;
906 if (element != null) { 898 if (element != null) {
907 constructorMap[element] = node; 899 constantsToCompute.add(element);
900 constantsToCompute.addAll(element.parameters);
908 } 901 }
909 } 902 }
910 return null; 903 return null;
911 } 904 }
912 905
913 @override 906 @override
914 Object visitVariableDeclaration(VariableDeclaration node) { 907 Object visitVariableDeclaration(VariableDeclaration node) {
915 super.visitVariableDeclaration(node); 908 super.visitVariableDeclaration(node);
916 Expression initializer = node.initializer; 909 Expression initializer = node.initializer;
917 VariableElement element = node.element; 910 VariableElement element = node.element;
918 if (initializer != null && 911 if (initializer != null &&
919 (node.isConst || 912 (node.isConst ||
920 treatFinalInstanceVarAsConst && 913 treatFinalInstanceVarAsConst &&
921 element is FieldElement && 914 element is FieldElement &&
922 node.isFinal && 915 node.isFinal &&
923 !element.isStatic)) { 916 !element.isStatic)) {
924 if (node.element != null) { 917 if (node.element != null) {
925 variableMap[node.element as PotentiallyConstVariableElement] = node; 918 constantsToCompute.add(node.element);
926 } 919 }
927 } 920 }
928 return null; 921 return null;
929 } 922 }
930 } 923 }
931 924
932 /** 925 /**
933 * An object used to compute the values of constant variables and constant 926 * An object used to compute the values of constant variables and constant
934 * constructor invocations in one or more compilation units. The expected usage 927 * constructor invocations in one or more compilation units. The expected usage
935 * pattern is for the compilation units to be added to this computer using the 928 * pattern is for the compilation units to be added to this computer using the
(...skipping 19 matching lines...) Expand all
955 /** 948 /**
956 * The object used to find constant variables and constant constructor 949 * The object used to find constant variables and constant constructor
957 * invocations in the compilation units that were added. 950 * invocations in the compilation units that were added.
958 */ 951 */
959 ConstantFinder _constantFinder = new ConstantFinder(); 952 ConstantFinder _constantFinder = new ConstantFinder();
960 953
961 /** 954 /**
962 * A graph in which the nodes are the constants, and the edges are from each 955 * A graph in which the nodes are the constants, and the edges are from each
963 * constant to the other constants that are referenced by it. 956 * constant to the other constants that are referenced by it.
964 */ 957 */
965 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>(); 958 DirectedGraph<Element> referenceGraph = new DirectedGraph<Element>();
966 959
967 /** 960 /**
968 * A table mapping constant variables to the declarations of those variables. 961 * The elements whose constant values need to be computed. Any elements
962 * which appear in [referenceGraph] but not in this set either belong to a
963 * different library cycle (and hence don't need to be recomputed) or were
964 * computed during a previous stage of resolution stage (e.g. constants
965 * associated with enums).
969 */ 966 */
970 HashMap<PotentiallyConstVariableElement, VariableDeclaration> _variableDeclara tionMap; 967 HashSet<Element> _constantsToCompute;
971
972 /**
973 * A table mapping constant constructors to the declarations of those
974 * constructors.
975 */
976 HashMap<ConstructorElement, ConstructorDeclaration> constructorDeclarationMap;
977 968
978 /** 969 /**
979 * A collection of annotations. 970 * A collection of annotations.
980 */ 971 */
981 List<Annotation> _annotations; 972 List<Annotation> _annotations;
982 973
983 /** 974 /**
984 * The evaluation engine that does the work of evaluating instance creation 975 * The evaluation engine that does the work of evaluating instance creation
985 * expressions. 976 * expressions.
986 */ 977 */
(...skipping 16 matching lines...) Expand all
1003 */ 994 */
1004 void add(CompilationUnit unit) { 995 void add(CompilationUnit unit) {
1005 unit.accept(_constantFinder); 996 unit.accept(_constantFinder);
1006 } 997 }
1007 998
1008 /** 999 /**
1009 * Compute values for all of the constants in the compilation units that were 1000 * Compute values for all of the constants in the compilation units that were
1010 * added. 1001 * added.
1011 */ 1002 */
1012 void computeValues() { 1003 void computeValues() {
1013 _variableDeclarationMap = _constantFinder.variableMap; 1004 _constantsToCompute = _constantFinder.constantsToCompute;
1014 constructorDeclarationMap = _constantFinder.constructorMap;
1015 _annotations = _constantFinder.annotations; 1005 _annotations = _constantFinder.annotations;
1016 _variableDeclarationMap.values.forEach((VariableDeclaration declaration) { 1006 for (Element element in _constantsToCompute) {
1017 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, 1007 referenceGraph.addNode(element);
1018 referenceGraph, _variableDeclarationMap, constructorDeclarationMap); 1008 if (element is ParameterElement) {
1019 referenceGraph.addNode(declaration); 1009 if (element.initializer != null) {
1020 declaration.initializer.accept(referenceFinder); 1010 Expression defaultValue =
1021 }); 1011 (element as ConstVariableElement).constantInitializer;
1022 constructorDeclarationMap.forEach((ConstructorElementImpl element,
1023 ConstructorDeclaration declaration) {
1024 element.isCycleFree = false;
1025 ConstructorElement redirectedConstructor =
1026 evaluationEngine.getConstRedirectedConstructor(element);
1027 if (redirectedConstructor != null) {
1028 ConstructorElement redirectedConstructorBase =
1029 ConstantEvaluationEngine._getConstructorBase(redirectedConstructor);
1030 ConstructorDeclaration redirectedConstructorDeclaration =
1031 findConstructorDeclaration(redirectedConstructorBase);
1032 referenceGraph.addEdge(declaration, redirectedConstructorDeclaration);
1033 return;
1034 }
1035 ReferenceFinder referenceFinder = new ReferenceFinder(declaration,
1036 referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
1037 referenceGraph.addNode(declaration);
1038 bool superInvocationFound = false;
1039 NodeList<ConstructorInitializer> initializers = declaration.initializers;
1040 for (ConstructorInitializer initializer in initializers) {
1041 if (initializer is SuperConstructorInvocation) {
1042 superInvocationFound = true;
1043 }
1044 initializer.accept(referenceFinder);
1045 }
1046 if (!superInvocationFound) {
1047 // No explicit superconstructor invocation found, so we need to
1048 // manually insert a reference to the implicit superconstructor.
1049 InterfaceType superclass =
1050 (element.returnType as InterfaceType).superclass;
1051 if (superclass != null && !superclass.isObject) {
1052 ConstructorElement unnamedConstructor =
1053 superclass.element.unnamedConstructor;
1054 ConstructorDeclaration superConstructorDeclaration =
1055 findConstructorDeclaration(unnamedConstructor);
1056 if (superConstructorDeclaration != null) {
1057 referenceGraph.addEdge(declaration, superConstructorDeclaration);
1058 }
1059 }
1060 }
1061 for (FieldElement field in element.enclosingElement.fields) {
1062 // Note: non-static const isn't allowed but we handle it anyway so that
1063 // we won't be confused by incorrect code.
1064 if ((field.isFinal || field.isConst) && !field.isStatic) {
1065 VariableDeclaration fieldDeclaration = _variableDeclarationMap[field];
1066 if (fieldDeclaration != null) {
1067 referenceGraph.addEdge(declaration, fieldDeclaration);
1068 }
1069 }
1070 }
1071 for (FormalParameter parameter in declaration.parameters.parameters) {
1072 referenceGraph.addNode(parameter);
1073 referenceGraph.addEdge(declaration, parameter);
1074 if (parameter is DefaultFormalParameter) {
1075 Expression defaultValue = parameter.defaultValue;
1076 if (defaultValue != null) { 1012 if (defaultValue != null) {
1077 ReferenceFinder parameterReferenceFinder = new ReferenceFinder( 1013 ReferenceFinder parameterReferenceFinder =
1078 parameter, referenceGraph, _variableDeclarationMap, 1014 new ReferenceFinder(element, referenceGraph);
1079 constructorDeclarationMap);
1080 defaultValue.accept(parameterReferenceFinder); 1015 defaultValue.accept(parameterReferenceFinder);
1081 } 1016 }
1082 } 1017 }
1018 } else if (element is PotentiallyConstVariableElement) {
1019 ReferenceFinder referenceFinder =
1020 new ReferenceFinder(element, referenceGraph);
1021 element.constantInitializer.accept(referenceFinder);
1022 } else if (element is ConstructorElementImpl) {
1023 element.isCycleFree = false;
1024 ConstructorElement redirectedConstructor =
1025 evaluationEngine.getConstRedirectedConstructor(element);
1026 if (redirectedConstructor != null) {
1027 ConstructorElement redirectedConstructorBase =
1028 ConstantEvaluationEngine
1029 ._getConstructorBase(redirectedConstructor);
1030 referenceGraph.addEdge(element, redirectedConstructorBase);
1031 continue;
1032 }
1033 ReferenceFinder referenceFinder =
1034 new ReferenceFinder(element, referenceGraph);
1035 bool superInvocationFound = false;
1036 List<ConstructorInitializer> initializers =
1037 element.constantInitializers;
1038 for (ConstructorInitializer initializer in initializers) {
1039 if (initializer is SuperConstructorInvocation) {
1040 superInvocationFound = true;
1041 }
1042 initializer.accept(referenceFinder);
1043 }
1044 if (!superInvocationFound) {
1045 // No explicit superconstructor invocation found, so we need to
1046 // manually insert a reference to the implicit superconstructor.
1047 InterfaceType superclass =
1048 (element.returnType as InterfaceType).superclass;
1049 if (superclass != null && !superclass.isObject) {
1050 ConstructorElement unnamedConstructor = ConstantEvaluationEngine
1051 ._getConstructorBase(superclass.element.unnamedConstructor);
1052 if (unnamedConstructor != null) {
1053 referenceGraph.addEdge(element, unnamedConstructor);
1054 }
1055 }
1056 }
1057 for (FieldElement field in element.enclosingElement.fields) {
1058 // Note: non-static const isn't allowed but we handle it anyway so tha t
1059 // we won't be confused by incorrect code.
1060 if ((field.isFinal || field.isConst) &&
1061 !field.isStatic &&
1062 field.initializer != null) {
1063 referenceGraph.addEdge(element, field);
1064 }
1065 }
1066 for (ParameterElement parameterElement in element.parameters) {
1067 referenceGraph.addEdge(element, parameterElement);
1068 }
1069 } else {
1070 // Should not happen.
1071 assert(false);
1072 AnalysisEngine.instance.logger.logError(
1073 "Constant value computer trying to compute the value of a node of ty pe ${element.runtimeType}");
1083 } 1074 }
1084 }); 1075 }
1085 List<List<AstNode>> topologicalSort = 1076 List<List<Element>> topologicalSort =
1086 referenceGraph.computeTopologicalSort(); 1077 referenceGraph.computeTopologicalSort();
1087 for (List<AstNode> constantsInCycle in topologicalSort) { 1078 for (List<Element> constantsInCycle in topologicalSort) {
1088 if (constantsInCycle.length == 1) { 1079 if (constantsInCycle.length == 1) {
1089 _computeValueFor(constantsInCycle[0]); 1080 _computeValueFor(constantsInCycle[0]);
1090 } else { 1081 } else {
1091 for (AstNode constant in constantsInCycle) { 1082 for (Element constant in constantsInCycle) {
1092 _generateCycleError(constantsInCycle, constant); 1083 _generateCycleError(constantsInCycle, constant);
1093 } 1084 }
1094 } 1085 }
1095 } 1086 }
1096 // Since no constant can depend on an annotation, we don't waste time 1087 // Since no constant can depend on an annotation, we don't waste time
1097 // including them in the topological sort. We just process all the 1088 // including them in the topological sort. We just process all the
1098 // annotations after all other constants are finished. 1089 // annotations after all other constants are finished.
1099 for (Annotation annotation in _annotations) { 1090 for (Annotation annotation in _annotations) {
1100 _computeValueFor(annotation); 1091 _computeValueForAnnotation(annotation);
1101 } 1092 }
1102 } 1093 }
1103 1094
1104 ConstructorDeclaration findConstructorDeclaration(
1105 ConstructorElement constructor) => constructorDeclarationMap[
1106 ConstantEvaluationEngine._getConstructorBase(constructor)];
1107
1108 VariableDeclaration findVariableDeclaration(
1109 PotentiallyConstVariableElement variable) =>
1110 _variableDeclarationMap[variable];
1111
1112 /** 1095 /**
1113 * Compute a value for the given [constNode]. 1096 * Compute a value for the given [element].
1114 */ 1097 */
1115 void _computeValueFor(AstNode constNode) { 1098 void _computeValueFor(Element element) {
1116 evaluationEngine.validator.beforeComputeValue(constNode); 1099 if (!_constantsToCompute.contains(element)) {
1117 if (constNode is VariableDeclaration) { 1100 // Element is in the dependency graph but should have been computed by
1118 VariableElement element = constNode.element; 1101 // a previous stage of analysis.
1102 return;
1103 }
1104 evaluationEngine.validator.beforeComputeValue(element);
1105 if (element is ParameterElement) {
1106 if (element.initializer != null) {
1107 Expression defaultValue =
1108 (element as PotentiallyConstVariableElement).constantInitializer;
1109 if (defaultValue != null) {
1110 RecordingErrorListener errorListener = new RecordingErrorListener();
1111 ErrorReporter errorReporter =
1112 new ErrorReporter(errorListener, element.source);
1113 DartObjectImpl dartObject = defaultValue
1114 .accept(new ConstantVisitor(evaluationEngine, errorReporter));
1115 (element as ParameterElementImpl).evaluationResult =
1116 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
1117 }
1118 }
1119 } else if (element is VariableElement) {
1119 RecordingErrorListener errorListener = new RecordingErrorListener(); 1120 RecordingErrorListener errorListener = new RecordingErrorListener();
1120 ErrorReporter errorReporter = 1121 ErrorReporter errorReporter =
1121 new ErrorReporter(errorListener, element.source); 1122 new ErrorReporter(errorListener, element.source);
1122 DartObjectImpl dartObject = 1123 DartObjectImpl dartObject =
1123 (element as PotentiallyConstVariableElement).constantInitializer 1124 (element as PotentiallyConstVariableElement).constantInitializer
1124 .accept(new ConstantVisitor(evaluationEngine, errorReporter)); 1125 .accept(new ConstantVisitor(evaluationEngine, errorReporter));
1125 // Only check the type for truly const declarations (don't check final 1126 // Only check the type for truly const declarations (don't check final
1126 // fields with initializers, since their types may be generic. The type 1127 // fields with initializers, since their types may be generic. The type
1127 // of the final field will be checked later, when the constructor is 1128 // of the final field will be checked later, when the constructor is
1128 // invoked). 1129 // invoked).
1129 if (dartObject != null && constNode.isConst) { 1130 if (dartObject != null && element.isConst) {
1130 if (!evaluationEngine.runtimeTypeMatch(dartObject, element.type)) { 1131 if (!evaluationEngine.runtimeTypeMatch(dartObject, element.type)) {
1131 errorReporter.reportErrorForElement( 1132 errorReporter.reportErrorForElement(
1132 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [ 1133 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [
1133 dartObject.type, 1134 dartObject.type,
1134 element.type 1135 element.type
1135 ]); 1136 ]);
1136 } 1137 }
1137 } 1138 }
1138 (element as VariableElementImpl).evaluationResult = 1139 (element as VariableElementImpl).evaluationResult =
1139 new EvaluationResultImpl.con2(dartObject, errorListener.errors); 1140 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
1140 } else if (constNode is ConstructorDeclaration) { 1141 } else if (element is ConstructorElement) {
1141 // No evaluation needs to be done; constructor declarations are only in 1142 // No evaluation needs to be done; constructor declarations are only in
1142 // the dependency graph to ensure that any constants referred to in 1143 // the dependency graph to ensure that any constants referred to in
1143 // initializer lists and parameter defaults are evaluated before 1144 // initializer lists and parameter defaults are evaluated before
1144 // invocations of the constructor. However we do need to annotate the 1145 // invocations of the constructor. However we do need to annotate the
1145 // element as being free of constant evaluation cycles so that later code 1146 // element as being free of constant evaluation cycles so that later code
1146 // will know that it is safe to evaluate. 1147 // will know that it is safe to evaluate.
1147 ConstructorElementImpl constructor = constNode.element; 1148 (element as ConstructorElementImpl).isCycleFree = true;
1148 constructor.isCycleFree = true;
1149 } else if (constNode is FormalParameter) {
1150 if (constNode is DefaultFormalParameter) {
1151 ParameterElement element = constNode.element;
1152 Expression defaultValue =
1153 (element as PotentiallyConstVariableElement).constantInitializer;
1154 if (defaultValue != null) {
1155 RecordingErrorListener errorListener = new RecordingErrorListener();
1156 ErrorReporter errorReporter =
1157 new ErrorReporter(errorListener, element.source);
1158 DartObjectImpl dartObject = defaultValue
1159 .accept(new ConstantVisitor(evaluationEngine, errorReporter));
1160 (element as ParameterElementImpl).evaluationResult =
1161 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
1162 }
1163 }
1164 } else if (constNode is Annotation) {
1165 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
1166 // elementAnnotation is null if the annotation couldn't be resolved, in
1167 // which case we skip it.
1168 if (elementAnnotation != null) {
1169 Element element = elementAnnotation.element;
1170 if (element is PropertyAccessorElement &&
1171 element.variable is VariableElementImpl) {
1172 // The annotation is a reference to a compile-time constant variable.
1173 // Just copy the evaluation result.
1174 VariableElementImpl variableElement =
1175 element.variable as VariableElementImpl;
1176 elementAnnotation.evaluationResult = variableElement.evaluationResult;
1177 } else if (element is ConstructorElementImpl &&
1178 constNode.arguments != null) {
1179 RecordingErrorListener errorListener = new RecordingErrorListener();
1180 CompilationUnit sourceCompilationUnit =
1181 constNode.getAncestor((node) => node is CompilationUnit);
1182 ErrorReporter errorReporter = new ErrorReporter(
1183 errorListener, sourceCompilationUnit.element.source);
1184 ConstantVisitor constantVisitor =
1185 new ConstantVisitor(evaluationEngine, errorReporter);
1186 DartObjectImpl result = evaluationEngine.evaluateConstructorCall(
1187 constNode, constNode.arguments.arguments, element,
1188 constantVisitor, errorReporter);
1189 elementAnnotation.evaluationResult =
1190 new EvaluationResultImpl.con2(result, errorListener.errors);
1191 } else {
1192 // This may happen for invalid code (e.g. failing to pass arguments
1193 // to an annotation which references a const constructor). The error
1194 // is detected elsewhere, so just silently ignore it here.
1195 elementAnnotation.evaluationResult =
1196 new EvaluationResultImpl.con1(null);
1197 }
1198 }
1199 } else { 1149 } else {
1200 // Should not happen. 1150 // Should not happen.
1201 assert(false); 1151 assert(false);
1202 AnalysisEngine.instance.logger.logError( 1152 AnalysisEngine.instance.logger.logError(
1203 "Constant value computer trying to compute the value of a node which i s not a VariableDeclaration, InstanceCreationExpression, FormalParameter, or Con structorDeclaration"); 1153 "Constant value computer trying to compute the value of a node of type ${element.runtimeType}");
1204 return; 1154 return;
1205 } 1155 }
1206 } 1156 }
1207 1157
1208 /** 1158 /**
1159 * Compute a value for the given annotation.
1160 */
1161 void _computeValueForAnnotation(Annotation constNode) {
1162 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
1163 // elementAnnotation is null if the annotation couldn't be resolved, in
1164 // which case we skip it.
1165 if (elementAnnotation != null) {
1166 Element element = elementAnnotation.element;
1167 if (element is PropertyAccessorElement &&
1168 element.variable is VariableElementImpl) {
1169 // The annotation is a reference to a compile-time constant variable.
1170 // Just copy the evaluation result.
1171 VariableElementImpl variableElement =
1172 element.variable as VariableElementImpl;
1173 elementAnnotation.evaluationResult = variableElement.evaluationResult;
1174 } else if (element is ConstructorElementImpl &&
1175 constNode.arguments != null) {
1176 RecordingErrorListener errorListener = new RecordingErrorListener();
1177 CompilationUnit sourceCompilationUnit =
1178 constNode.getAncestor((node) => node is CompilationUnit);
1179 ErrorReporter errorReporter = new ErrorReporter(
1180 errorListener, sourceCompilationUnit.element.source);
1181 ConstantVisitor constantVisitor =
1182 new ConstantVisitor(evaluationEngine, errorReporter);
1183 DartObjectImpl result = evaluationEngine.evaluateConstructorCall(
1184 constNode, constNode.arguments.arguments, element, constantVisitor,
1185 errorReporter);
1186 elementAnnotation.evaluationResult =
1187 new EvaluationResultImpl.con2(result, errorListener.errors);
1188 } else {
1189 // This may happen for invalid code (e.g. failing to pass arguments
1190 // to an annotation which references a const constructor). The error
1191 // is detected elsewhere, so just silently ignore it here.
1192 elementAnnotation.evaluationResult =
1193 new EvaluationResultImpl.con1(null);
1194 }
1195 }
1196 }
1197
1198 /**
1209 * Generate an error indicating that the given [constNode] is not a valid 1199 * Generate an error indicating that the given [constNode] is not a valid
1210 * compile-time constant because it references at least one of the constants 1200 * compile-time constant because it references at least one of the constants
1211 * in the given [cycle], each of which directly or indirectly references the 1201 * in the given [cycle], each of which directly or indirectly references the
1212 * constant. 1202 * constant.
1213 */ 1203 */
1214 void _generateCycleError(List<AstNode> cycle, AstNode constNode) { 1204 void _generateCycleError(List<Element> cycle, Element element) {
1215 if (constNode is VariableDeclaration) { 1205 if (element is VariableElement) {
1216 VariableElement element = constNode.element;
1217 RecordingErrorListener errorListener = new RecordingErrorListener(); 1206 RecordingErrorListener errorListener = new RecordingErrorListener();
1218 ErrorReporter errorReporter = 1207 ErrorReporter errorReporter =
1219 new ErrorReporter(errorListener, element.source); 1208 new ErrorReporter(errorListener, element.source);
1220 // TODO(paulberry): It would be really nice if we could extract enough 1209 // TODO(paulberry): It would be really nice if we could extract enough
1221 // information from the 'cycle' argument to provide the user with a 1210 // information from the 'cycle' argument to provide the user with a
1222 // description of the cycle. 1211 // description of the cycle.
1223 errorReporter.reportErrorForElement( 1212 errorReporter.reportErrorForElement(
1224 CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, element, []); 1213 CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, element, []);
1225 (element as VariableElementImpl).evaluationResult = 1214 (element as VariableElementImpl).evaluationResult =
1226 new EvaluationResultImpl.con2(null, errorListener.errors); 1215 new EvaluationResultImpl.con2(null, errorListener.errors);
1227 } else if (constNode is ConstructorDeclaration) { 1216 } else if (element is ConstructorElement) {
1228 // We don't report cycle errors on constructor declarations since there 1217 // We don't report cycle errors on constructor declarations since there
1229 // is nowhere to put the error information. 1218 // is nowhere to put the error information.
1230 } else { 1219 } else {
1231 // Should not happen. Formal parameter defaults and annotations should 1220 // Should not happen. Formal parameter defaults and annotations should
1232 // never appear as part of a cycle because they can't be referred to. 1221 // never appear as part of a cycle because they can't be referred to.
1233 assert(false); 1222 assert(false);
1234 AnalysisEngine.instance.logger.logError( 1223 AnalysisEngine.instance.logger.logError(
1235 "Constant value computer trying to report a cycle error for a node of type ${constNode.runtimeType}"); 1224 "Constant value computer trying to report a cycle error for a node of type ${element.runtimeType}");
1236 } 1225 }
1237 } 1226 }
1238 } 1227 }
1239 1228
1240 /** 1229 /**
1241 * A visitor used to evaluate constant expressions to produce their compile-time 1230 * A visitor used to evaluate constant expressions to produce their compile-time
1242 * value. According to the Dart Language Specification: <blockquote> A constant 1231 * value. According to the Dart Language Specification: <blockquote> A constant
1243 * expression is one of the following: 1232 * expression is one of the following:
1244 * 1233 *
1245 * * A literal number. 1234 * * A literal number.
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 * Return the constant value of the static constant represented by the given 1705 * Return the constant value of the static constant represented by the given
1717 * [element]. The [node] is the node to be used if an error needs to be 1706 * [element]. The [node] is the node to be used if an error needs to be
1718 * reported. 1707 * reported.
1719 */ 1708 */
1720 DartObjectImpl _getConstantValue(AstNode node, Element element) { 1709 DartObjectImpl _getConstantValue(AstNode node, Element element) {
1721 if (element is PropertyAccessorElement) { 1710 if (element is PropertyAccessorElement) {
1722 element = (element as PropertyAccessorElement).variable; 1711 element = (element as PropertyAccessorElement).variable;
1723 } 1712 }
1724 if (element is VariableElementImpl) { 1713 if (element is VariableElementImpl) {
1725 VariableElementImpl variableElementImpl = element; 1714 VariableElementImpl variableElementImpl = element;
1726 evaluationEngine.validator.beforeGetEvaluationResult(node); 1715 evaluationEngine.validator.beforeGetEvaluationResult(element);
1727 EvaluationResultImpl value = variableElementImpl.evaluationResult; 1716 EvaluationResultImpl value = variableElementImpl.evaluationResult;
1728 if (variableElementImpl.isConst && value != null) { 1717 if (variableElementImpl.isConst && value != null) {
1729 return value.value; 1718 return value.value;
1730 } 1719 }
1731 } else if (element is ExecutableElement) { 1720 } else if (element is ExecutableElement) {
1732 ExecutableElement function = element; 1721 ExecutableElement function = element;
1733 if (function.isStatic) { 1722 if (function.isStatic) {
1734 ParameterizedType functionType = function.type; 1723 ParameterizedType functionType = function.type;
1735 if (functionType == null) { 1724 if (functionType == null) {
1736 functionType = _typeProvider.functionType; 1725 functionType = _typeProvider.functionType;
(...skipping 3134 matching lines...) Expand 10 before | Expand all | Expand 10 after
4871 } 4860 }
4872 4861
4873 /** 4862 /**
4874 * An object used to add reference information for a given variable to the 4863 * An object used to add reference information for a given variable to the
4875 * bi-directional mapping used to order the evaluation of constants. 4864 * bi-directional mapping used to order the evaluation of constants.
4876 */ 4865 */
4877 class ReferenceFinder extends RecursiveAstVisitor<Object> { 4866 class ReferenceFinder extends RecursiveAstVisitor<Object> {
4878 /** 4867 /**
4879 * The element representing the construct that will be visited. 4868 * The element representing the construct that will be visited.
4880 */ 4869 */
4881 final AstNode _source; 4870 final Element _source;
4882 4871
4883 /** 4872 /**
4884 * A graph in which the nodes are the constant variables and the edges are 4873 * A graph in which the nodes are the constant variables and the edges are
4885 * from each variable to the other constant variables that are referenced in 4874 * from each variable to the other constant variables that are referenced in
4886 * the head's initializer. 4875 * the head's initializer.
4887 */ 4876 */
4888 final DirectedGraph<AstNode> _referenceGraph; 4877 final DirectedGraph<Element> _referenceGraph;
4889
4890 /**
4891 * A table mapping constant variables to the declarations of those variables.
4892 */
4893 final HashMap<PotentiallyConstVariableElement, VariableDeclaration> _variableD eclarationMap;
4894
4895 /**
4896 * A table mapping constant constructors to the declarations of those
4897 * constructors.
4898 */
4899 final HashMap<ConstructorElement, ConstructorDeclaration> _constructorDeclarat ionMap;
4900 4878
4901 /** 4879 /**
4902 * Initialize a newly created reference finder to find references from a given 4880 * Initialize a newly created reference finder to find references from a given
4903 * variable to other variables and to add those references to the given graph. 4881 * variable to other variables and to add those references to the given graph.
4904 * The [source] is the element representing the variable whose initializer 4882 * The [source] is the element representing the variable whose initializer
4905 * will be visited. The [referenceGraph] is a graph recording which variables 4883 * will be visited. The [referenceGraph] is a graph recording which variables
4906 * (heads) reference which other variables (tails) in their initializers. The 4884 * (heads) reference which other variables (tails) in their initializers.
4907 * [variableDeclarationMap] is a table mapping constant variables to the
4908 * declarations of those variables. The [constructorDeclarationMap] is a table
4909 * mapping constant constructors to the declarations of those constructors.
4910 */ 4885 */
4911 ReferenceFinder(this._source, this._referenceGraph, 4886 ReferenceFinder(this._source, this._referenceGraph);
4912 this._variableDeclarationMap, this._constructorDeclarationMap);
4913
4914 ConstructorDeclaration findConstructorDeclaration(
4915 ConstructorElement constructor) => _constructorDeclarationMap[
4916 ConstantEvaluationEngine._getConstructorBase(constructor)];
4917 4887
4918 @override 4888 @override
4919 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 4889 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
4920 if (node.isConst) { 4890 if (node.isConst) {
4921 ConstructorElement constructor = node.staticElement; 4891 ConstructorElement constructor =
4892 ConstantEvaluationEngine._getConstructorBase(node.staticElement);
4922 if (constructor != null) { 4893 if (constructor != null) {
4923 ConstructorDeclaration declaration = 4894 _referenceGraph.addEdge(_source, constructor);
4924 findConstructorDeclaration(constructor);
4925 if (declaration != null) {
4926 _referenceGraph.addEdge(_source, declaration);
4927 }
4928 } 4895 }
4929 } 4896 }
4930 return super.visitInstanceCreationExpression(node); 4897 return super.visitInstanceCreationExpression(node);
4931 } 4898 }
4932 4899
4933 @override 4900 @override
4934 Object visitRedirectingConstructorInvocation( 4901 Object visitRedirectingConstructorInvocation(
4935 RedirectingConstructorInvocation node) { 4902 RedirectingConstructorInvocation node) {
4936 super.visitRedirectingConstructorInvocation(node); 4903 super.visitRedirectingConstructorInvocation(node);
4937 ConstructorElement target = node.staticElement; 4904 ConstructorElement target =
4905 ConstantEvaluationEngine._getConstructorBase(node.staticElement);
4938 if (target != null && target.isConst) { 4906 if (target != null && target.isConst) {
4939 ConstructorDeclaration targetDeclaration = 4907 _referenceGraph.addEdge(_source, target);
4940 _constructorDeclarationMap[target];
4941 if (targetDeclaration != null) {
4942 _referenceGraph.addEdge(_source, targetDeclaration);
4943 }
4944 } 4908 }
4945 return null; 4909 return null;
4946 } 4910 }
4947 4911
4948 @override 4912 @override
4949 Object visitSimpleIdentifier(SimpleIdentifier node) { 4913 Object visitSimpleIdentifier(SimpleIdentifier node) {
4950 Element element = node.staticElement; 4914 Element element = node.staticElement;
4951 if (element is PropertyAccessorElement) { 4915 if (element is PropertyAccessorElement) {
4952 element = (element as PropertyAccessorElement).variable; 4916 element = (element as PropertyAccessorElement).variable;
4953 } 4917 }
4954 if (element is VariableElement) { 4918 if (element is VariableElement) {
4955 if (element.isConst) { 4919 if (element.isConst) {
4956 VariableDeclaration variableDeclaration = 4920 _referenceGraph.addEdge(_source, element);
4957 _variableDeclarationMap[element];
4958 // The declaration will be null when the variable is not defined in the
4959 // compilation units that were used to produce the
4960 // variableDeclarationMap. In such cases, the variable should already
4961 // have a value associated with it, but we don't bother to check because
4962 // there's nothing we can do about it at this point.
4963 if (variableDeclaration != null) {
4964 _referenceGraph.addEdge(_source, variableDeclaration);
4965 }
4966 } 4921 }
4967 } 4922 }
4968 return null; 4923 return null;
4969 } 4924 }
4970 4925
4971 @override 4926 @override
4972 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { 4927 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
4973 super.visitSuperConstructorInvocation(node); 4928 super.visitSuperConstructorInvocation(node);
4974 ConstructorElement constructor = node.staticElement; 4929 ConstructorElement constructor =
4930 ConstantEvaluationEngine._getConstructorBase(node.staticElement);
4975 if (constructor != null && constructor.isConst) { 4931 if (constructor != null && constructor.isConst) {
4976 ConstructorDeclaration constructorDeclaration = 4932 _referenceGraph.addEdge(_source, constructor);
4977 _constructorDeclarationMap[constructor];
4978 // The declaration will be null when the constructor is not defined in the
4979 // compilation units that were used to produce the
4980 // constructorDeclarationMap. In such cases, the constructor should
4981 // already have its initializer AST's stored in it, but we don't bother
4982 // to check because there's nothing we can do about it at this point.
4983 if (constructorDeclaration != null) {
4984 _referenceGraph.addEdge(_source, constructorDeclaration);
4985 }
4986 } 4933 }
4987 return null; 4934 return null;
4988 } 4935 }
4989 } 4936 }
4990 4937
4991 /** 4938 /**
4992 * The state of an object representing a string. 4939 * The state of an object representing a string.
4993 */ 4940 */
4994 class StringState extends InstanceState { 4941 class StringState extends InstanceState {
4995 /** 4942 /**
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
5197 return BoolState.from(_element == rightElement); 5144 return BoolState.from(_element == rightElement);
5198 } else if (rightOperand is DynamicState) { 5145 } else if (rightOperand is DynamicState) {
5199 return BoolState.UNKNOWN_VALUE; 5146 return BoolState.UNKNOWN_VALUE;
5200 } 5147 }
5201 return BoolState.FALSE_STATE; 5148 return BoolState.FALSE_STATE;
5202 } 5149 }
5203 5150
5204 @override 5151 @override
5205 String toString() => _element == null ? "-unknown-" : _element.name; 5152 String toString() => _element == null ? "-unknown-" : _element.name;
5206 } 5153 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698