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'; |
11 | 11 |
12 import 'package:analyzer/src/generated/utilities_general.dart'; | 12 import 'package:analyzer/src/generated/utilities_general.dart'; |
13 | 13 |
14 import 'ast.dart'; | 14 import 'ast.dart'; |
15 import 'element.dart'; | 15 import 'element.dart'; |
16 import 'engine.dart' show AnalysisEngine, RecordingErrorListener; | 16 import 'engine.dart' show AnalysisEngine, RecordingErrorListener; |
17 import 'error.dart'; | 17 import 'error.dart'; |
18 import 'java_core.dart'; | 18 import 'java_core.dart'; |
19 import 'resolver.dart' show TypeProvider; | 19 import 'resolver.dart' show TypeProvider; |
20 import 'scanner.dart' show Token, TokenType; | 20 import 'scanner.dart' show Token, TokenType; |
21 import 'source.dart' show Source; | 21 import 'source.dart' show Source; |
22 import 'utilities_collection.dart'; | 22 import 'utilities_collection.dart'; |
23 import 'utilities_dart.dart' show ParameterKind; | 23 import 'utilities_dart.dart' show ParameterKind; |
24 | 24 |
25 /** | 25 /** |
| 26 * Callback used by [ReferenceFinder] to report that a dependency was found. |
| 27 */ |
| 28 typedef void ReferenceFinderCallback(Element dependency); |
| 29 |
| 30 /** |
26 * The state of an object representing a boolean value. | 31 * The state of an object representing a boolean value. |
27 */ | 32 */ |
28 class BoolState extends InstanceState { | 33 class BoolState extends InstanceState { |
29 /** | 34 /** |
30 * An instance representing the boolean value 'false'. | 35 * An instance representing the boolean value 'false'. |
31 */ | 36 */ |
32 static BoolState FALSE_STATE = new BoolState(false); | 37 static BoolState FALSE_STATE = new BoolState(false); |
33 | 38 |
34 /** | 39 /** |
35 * An instance representing the boolean value 'true'. | 40 * An instance representing the boolean value 'true'. |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 SuperConstructorInvocation visitSuperConstructorInvocation( | 184 SuperConstructorInvocation visitSuperConstructorInvocation( |
180 SuperConstructorInvocation node) { | 185 SuperConstructorInvocation node) { |
181 SuperConstructorInvocation invocation = | 186 SuperConstructorInvocation invocation = |
182 super.visitSuperConstructorInvocation(node); | 187 super.visitSuperConstructorInvocation(node); |
183 invocation.staticElement = node.staticElement; | 188 invocation.staticElement = node.staticElement; |
184 return invocation; | 189 return invocation; |
185 } | 190 } |
186 } | 191 } |
187 | 192 |
188 /** | 193 /** |
189 * Helper class encapsulating the methods for evaluating constant instance | 194 * Helper class encapsulating the methods for evaluating constants and |
190 * constant instance creation expressions. | 195 * constant instance creation expressions. |
191 */ | 196 */ |
192 class ConstantEvaluationEngine { | 197 class ConstantEvaluationEngine { |
193 /** | 198 /** |
194 * Parameter to "fromEnvironment" methods that denotes the default value. | 199 * Parameter to "fromEnvironment" methods that denotes the default value. |
195 */ | 200 */ |
196 static String _DEFAULT_VALUE_PARAM = "defaultValue"; | 201 static String _DEFAULT_VALUE_PARAM = "defaultValue"; |
197 | 202 |
198 /** | 203 /** |
199 * Source of RegExp matching any public identifier. | 204 * Source of RegExp matching any public identifier. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 return false; | 301 return false; |
297 } | 302 } |
298 if (!identical(argumentValues[0].type, typeProvider.stringType)) { | 303 if (!identical(argumentValues[0].type, typeProvider.stringType)) { |
299 return false; | 304 return false; |
300 } | 305 } |
301 String name = argumentValues[0].stringValue; | 306 String name = argumentValues[0].stringValue; |
302 return isValidPublicSymbol(name); | 307 return isValidPublicSymbol(name); |
303 } | 308 } |
304 | 309 |
305 /** | 310 /** |
| 311 * Determine which constant elements need to have their values computed |
| 312 * prior to computing the value of [element], and report them using |
| 313 * [callback]. |
| 314 */ |
| 315 void computeDependencies(Element element, ReferenceFinderCallback callback) { |
| 316 ReferenceFinder referenceFinder = new ReferenceFinder(callback); |
| 317 if (element is ParameterElement) { |
| 318 if (element.initializer != null) { |
| 319 Expression defaultValue = |
| 320 (element as ConstVariableElement).constantInitializer; |
| 321 if (defaultValue != null) { |
| 322 defaultValue.accept(referenceFinder); |
| 323 } |
| 324 } |
| 325 } else if (element is PotentiallyConstVariableElement) { |
| 326 element.constantInitializer.accept(referenceFinder); |
| 327 } else if (element is ConstructorElementImpl) { |
| 328 element.isCycleFree = false; |
| 329 ConstructorElement redirectedConstructor = |
| 330 getConstRedirectedConstructor(element); |
| 331 if (redirectedConstructor != null) { |
| 332 ConstructorElement redirectedConstructorBase = |
| 333 ConstantEvaluationEngine._getConstructorBase(redirectedConstructor); |
| 334 callback(redirectedConstructorBase); |
| 335 return; |
| 336 } |
| 337 bool superInvocationFound = false; |
| 338 List<ConstructorInitializer> initializers = element.constantInitializers; |
| 339 for (ConstructorInitializer initializer in initializers) { |
| 340 if (initializer is SuperConstructorInvocation) { |
| 341 superInvocationFound = true; |
| 342 } |
| 343 initializer.accept(referenceFinder); |
| 344 } |
| 345 if (!superInvocationFound) { |
| 346 // No explicit superconstructor invocation found, so we need to |
| 347 // manually insert a reference to the implicit superconstructor. |
| 348 InterfaceType superclass = |
| 349 (element.returnType as InterfaceType).superclass; |
| 350 if (superclass != null && !superclass.isObject) { |
| 351 ConstructorElement unnamedConstructor = ConstantEvaluationEngine |
| 352 ._getConstructorBase(superclass.element.unnamedConstructor); |
| 353 if (unnamedConstructor != null) { |
| 354 callback(unnamedConstructor); |
| 355 } |
| 356 } |
| 357 } |
| 358 for (FieldElement field in element.enclosingElement.fields) { |
| 359 // Note: non-static const isn't allowed but we handle it anyway so that |
| 360 // we won't be confused by incorrect code. |
| 361 if ((field.isFinal || field.isConst) && |
| 362 !field.isStatic && |
| 363 field.initializer != null) { |
| 364 callback(field); |
| 365 } |
| 366 } |
| 367 for (ParameterElement parameterElement in element.parameters) { |
| 368 callback(parameterElement); |
| 369 } |
| 370 } else { |
| 371 // Should not happen. |
| 372 assert(false); |
| 373 AnalysisEngine.instance.logger.logError( |
| 374 "Constant value computer trying to compute the value of a node of type
${element.runtimeType}"); |
| 375 } |
| 376 } |
| 377 |
| 378 /** |
306 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The | 379 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The |
307 * [environmentValue] is the value fetched from the environment. The | 380 * [environmentValue] is the value fetched from the environment. The |
308 * [builtInDefaultValue] is the value that should be used as the default if no | 381 * [builtInDefaultValue] is the value that should be used as the default if no |
309 * "defaultValue" argument appears in [namedArgumentValues]. The | 382 * "defaultValue" argument appears in [namedArgumentValues]. The |
310 * [namedArgumentValues] are the values of the named parameters passed to | 383 * [namedArgumentValues] are the values of the named parameters passed to |
311 * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the | 384 * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the |
312 * evaluated result. | 385 * evaluated result. |
313 */ | 386 */ |
314 DartObjectImpl computeValueFromEnvironment(DartObject environmentValue, | 387 DartObjectImpl computeValueFromEnvironment(DartObject environmentValue, |
315 DartObjectImpl builtInDefaultValue, | 388 DartObjectImpl builtInDefaultValue, |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 | 1071 |
999 /** | 1072 /** |
1000 * Compute values for all of the constants in the compilation units that were | 1073 * Compute values for all of the constants in the compilation units that were |
1001 * added. | 1074 * added. |
1002 */ | 1075 */ |
1003 void computeValues() { | 1076 void computeValues() { |
1004 _constantsToCompute = _constantFinder.constantsToCompute; | 1077 _constantsToCompute = _constantFinder.constantsToCompute; |
1005 _annotations = _constantFinder.annotations; | 1078 _annotations = _constantFinder.annotations; |
1006 for (Element element in _constantsToCompute) { | 1079 for (Element element in _constantsToCompute) { |
1007 referenceGraph.addNode(element); | 1080 referenceGraph.addNode(element); |
1008 if (element is ParameterElement) { | 1081 evaluationEngine.computeDependencies(element, (Element dependency) { |
1009 if (element.initializer != null) { | 1082 referenceGraph.addEdge(element, dependency); |
1010 Expression defaultValue = | 1083 }); |
1011 (element as ConstVariableElement).constantInitializer; | |
1012 if (defaultValue != null) { | |
1013 ReferenceFinder parameterReferenceFinder = | |
1014 new ReferenceFinder(element, referenceGraph); | |
1015 defaultValue.accept(parameterReferenceFinder); | |
1016 } | |
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}"); | |
1074 } | |
1075 } | 1084 } |
1076 List<List<Element>> topologicalSort = | 1085 List<List<Element>> topologicalSort = |
1077 referenceGraph.computeTopologicalSort(); | 1086 referenceGraph.computeTopologicalSort(); |
1078 for (List<Element> constantsInCycle in topologicalSort) { | 1087 for (List<Element> constantsInCycle in topologicalSort) { |
1079 if (constantsInCycle.length == 1) { | 1088 if (constantsInCycle.length == 1) { |
1080 _computeValueFor(constantsInCycle[0]); | 1089 _computeValueFor(constantsInCycle[0]); |
1081 } else { | 1090 } else { |
1082 for (Element constant in constantsInCycle) { | 1091 for (Element constant in constantsInCycle) { |
1083 _generateCycleError(constantsInCycle, constant); | 1092 _generateCycleError(constantsInCycle, constant); |
1084 } | 1093 } |
(...skipping 3773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4858 @override | 4867 @override |
4859 String toString() => "-unknown-"; | 4868 String toString() => "-unknown-"; |
4860 } | 4869 } |
4861 | 4870 |
4862 /** | 4871 /** |
4863 * An object used to add reference information for a given variable to the | 4872 * An object used to add reference information for a given variable to the |
4864 * bi-directional mapping used to order the evaluation of constants. | 4873 * bi-directional mapping used to order the evaluation of constants. |
4865 */ | 4874 */ |
4866 class ReferenceFinder extends RecursiveAstVisitor<Object> { | 4875 class ReferenceFinder extends RecursiveAstVisitor<Object> { |
4867 /** | 4876 /** |
4868 * The element representing the construct that will be visited. | 4877 * The callback which should be used to report any dependencies that were |
| 4878 * found. |
4869 */ | 4879 */ |
4870 final Element _source; | 4880 final ReferenceFinderCallback _callback; |
4871 | |
4872 /** | |
4873 * A graph in which the nodes are the constant variables and the edges are | |
4874 * from each variable to the other constant variables that are referenced in | |
4875 * the head's initializer. | |
4876 */ | |
4877 final DirectedGraph<Element> _referenceGraph; | |
4878 | 4881 |
4879 /** | 4882 /** |
4880 * Initialize a newly created reference finder to find references from a given | 4883 * Initialize a newly created reference finder to find references from a given |
4881 * variable to other variables and to add those references to the given graph. | 4884 * variable to other variables and to add those references to the given graph. |
4882 * The [source] is the element representing the variable whose initializer | 4885 * The [_callback] will be invoked for every dependency found. |
4883 * will be visited. The [referenceGraph] is a graph recording which variables | |
4884 * (heads) reference which other variables (tails) in their initializers. | |
4885 */ | 4886 */ |
4886 ReferenceFinder(this._source, this._referenceGraph); | 4887 ReferenceFinder(this._callback); |
4887 | 4888 |
4888 @override | 4889 @override |
4889 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 4890 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
4890 if (node.isConst) { | 4891 if (node.isConst) { |
4891 ConstructorElement constructor = | 4892 ConstructorElement constructor = |
4892 ConstantEvaluationEngine._getConstructorBase(node.staticElement); | 4893 ConstantEvaluationEngine._getConstructorBase(node.staticElement); |
4893 if (constructor != null) { | 4894 if (constructor != null) { |
4894 _referenceGraph.addEdge(_source, constructor); | 4895 _callback(constructor); |
4895 } | 4896 } |
4896 } | 4897 } |
4897 return super.visitInstanceCreationExpression(node); | 4898 return super.visitInstanceCreationExpression(node); |
4898 } | 4899 } |
4899 | 4900 |
4900 @override | 4901 @override |
4901 Object visitRedirectingConstructorInvocation( | 4902 Object visitRedirectingConstructorInvocation( |
4902 RedirectingConstructorInvocation node) { | 4903 RedirectingConstructorInvocation node) { |
4903 super.visitRedirectingConstructorInvocation(node); | 4904 super.visitRedirectingConstructorInvocation(node); |
4904 ConstructorElement target = | 4905 ConstructorElement target = |
4905 ConstantEvaluationEngine._getConstructorBase(node.staticElement); | 4906 ConstantEvaluationEngine._getConstructorBase(node.staticElement); |
4906 if (target != null && target.isConst) { | 4907 if (target != null && target.isConst) { |
4907 _referenceGraph.addEdge(_source, target); | 4908 _callback(target); |
4908 } | 4909 } |
4909 return null; | 4910 return null; |
4910 } | 4911 } |
4911 | 4912 |
4912 @override | 4913 @override |
4913 Object visitSimpleIdentifier(SimpleIdentifier node) { | 4914 Object visitSimpleIdentifier(SimpleIdentifier node) { |
4914 Element element = node.staticElement; | 4915 Element element = node.staticElement; |
4915 if (element is PropertyAccessorElement) { | 4916 if (element is PropertyAccessorElement) { |
4916 element = (element as PropertyAccessorElement).variable; | 4917 element = (element as PropertyAccessorElement).variable; |
4917 } | 4918 } |
4918 if (element is VariableElement) { | 4919 if (element is VariableElement) { |
4919 if (element.isConst) { | 4920 if (element.isConst) { |
4920 _referenceGraph.addEdge(_source, element); | 4921 _callback(element); |
4921 } | 4922 } |
4922 } | 4923 } |
4923 return null; | 4924 return null; |
4924 } | 4925 } |
4925 | 4926 |
4926 @override | 4927 @override |
4927 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 4928 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
4928 super.visitSuperConstructorInvocation(node); | 4929 super.visitSuperConstructorInvocation(node); |
4929 ConstructorElement constructor = | 4930 ConstructorElement constructor = |
4930 ConstantEvaluationEngine._getConstructorBase(node.staticElement); | 4931 ConstantEvaluationEngine._getConstructorBase(node.staticElement); |
4931 if (constructor != null && constructor.isConst) { | 4932 if (constructor != null && constructor.isConst) { |
4932 _referenceGraph.addEdge(_source, constructor); | 4933 _callback(constructor); |
4933 } | 4934 } |
4934 return null; | 4935 return null; |
4935 } | 4936 } |
4936 } | 4937 } |
4937 | 4938 |
4938 /** | 4939 /** |
4939 * The state of an object representing a string. | 4940 * The state of an object representing a string. |
4940 */ | 4941 */ |
4941 class StringState extends InstanceState { | 4942 class StringState extends InstanceState { |
4942 /** | 4943 /** |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5144 return BoolState.from(_element == rightElement); | 5145 return BoolState.from(_element == rightElement); |
5145 } else if (rightOperand is DynamicState) { | 5146 } else if (rightOperand is DynamicState) { |
5146 return BoolState.UNKNOWN_VALUE; | 5147 return BoolState.UNKNOWN_VALUE; |
5147 } | 5148 } |
5148 return BoolState.FALSE_STATE; | 5149 return BoolState.FALSE_STATE; |
5149 } | 5150 } |
5150 | 5151 |
5151 @override | 5152 @override |
5152 String toString() => _element == null ? "-unknown-" : _element.name; | 5153 String toString() => _element == null ? "-unknown-" : _element.name; |
5153 } | 5154 } |
OLD | NEW |