| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.dart.constant.evaluation; | 5 library analyzer.src.dart.constant.evaluation; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/context/declared_variables.dart'; | 9 import 'package:analyzer/context/declared_variables.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 if (argumentCount < 1 || argumentCount > 2) { | 108 if (argumentCount < 1 || argumentCount > 2) { |
| 109 return false; | 109 return false; |
| 110 } | 110 } |
| 111 if (arguments[0] is NamedExpression) { | 111 if (arguments[0] is NamedExpression) { |
| 112 return false; | 112 return false; |
| 113 } | 113 } |
| 114 if (!identical(argumentValues[0].type, typeProvider.stringType)) { | 114 if (!identical(argumentValues[0].type, typeProvider.stringType)) { |
| 115 return false; | 115 return false; |
| 116 } | 116 } |
| 117 if (argumentCount == 2) { | 117 if (argumentCount == 2) { |
| 118 if (arguments[1] is! NamedExpression) { | 118 Expression secondArgument = arguments[1]; |
| 119 return false; | 119 if (secondArgument is NamedExpression) { |
| 120 } | 120 if (!(secondArgument.name.label.name == _DEFAULT_VALUE_PARAM)) { |
| 121 if (!((arguments[1] as NamedExpression).name.label.name == | 121 return false; |
| 122 _DEFAULT_VALUE_PARAM)) { | 122 } |
| 123 return false; | 123 ParameterizedType defaultValueType = |
| 124 } | 124 namedArgumentValues[_DEFAULT_VALUE_PARAM].type; |
| 125 ParameterizedType defaultValueType = | 125 if (!(identical(defaultValueType, expectedDefaultValueType) || |
| 126 namedArgumentValues[_DEFAULT_VALUE_PARAM].type; | 126 identical(defaultValueType, typeProvider.nullType))) { |
| 127 if (!(identical(defaultValueType, expectedDefaultValueType) || | 127 return false; |
| 128 identical(defaultValueType, typeProvider.nullType))) { | 128 } |
| 129 } else { |
| 129 return false; | 130 return false; |
| 130 } | 131 } |
| 131 } | 132 } |
| 132 return true; | 133 return true; |
| 133 } | 134 } |
| 134 | 135 |
| 135 /** | 136 /** |
| 136 * Check that the arguments to a call to Symbol() are correct. The [arguments] | 137 * Check that the arguments to a call to Symbol() are correct. The [arguments] |
| 137 * are the AST nodes of the arguments. The [argumentValues] are the values of | 138 * are the AST nodes of the arguments. The [argumentValues] are the values of |
| 138 * the unnamed arguments. The [namedArgumentValues] are the values of the | 139 * the unnamed arguments. The [namedArgumentValues] are the values of the |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 } | 614 } |
| 614 } | 615 } |
| 615 } | 616 } |
| 616 ConstantVisitor initializerVisitor = new ConstantVisitor( | 617 ConstantVisitor initializerVisitor = new ConstantVisitor( |
| 617 this, errorReporter, | 618 this, errorReporter, |
| 618 lexicalEnvironment: parameterMap); | 619 lexicalEnvironment: parameterMap); |
| 619 String superName = null; | 620 String superName = null; |
| 620 NodeList<Expression> superArguments = null; | 621 NodeList<Expression> superArguments = null; |
| 621 for (ConstructorInitializer initializer in initializers) { | 622 for (ConstructorInitializer initializer in initializers) { |
| 622 if (initializer is ConstructorFieldInitializer) { | 623 if (initializer is ConstructorFieldInitializer) { |
| 623 ConstructorFieldInitializer constructorFieldInitializer = initializer; | 624 Expression initializerExpression = initializer.expression; |
| 624 Expression initializerExpression = | |
| 625 constructorFieldInitializer.expression; | |
| 626 DartObjectImpl evaluationResult = | 625 DartObjectImpl evaluationResult = |
| 627 initializerExpression.accept(initializerVisitor); | 626 initializerExpression.accept(initializerVisitor); |
| 628 if (evaluationResult != null) { | 627 if (evaluationResult != null) { |
| 629 String fieldName = constructorFieldInitializer.fieldName.name; | 628 String fieldName = initializer.fieldName.name; |
| 630 if (fieldMap.containsKey(fieldName)) { | 629 if (fieldMap.containsKey(fieldName)) { |
| 631 errorReporter.reportErrorForNode( | 630 errorReporter.reportErrorForNode( |
| 632 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); | 631 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); |
| 633 } | 632 } |
| 634 fieldMap[fieldName] = evaluationResult; | 633 fieldMap[fieldName] = evaluationResult; |
| 635 PropertyAccessorElement getter = definingClass.getGetter(fieldName); | 634 PropertyAccessorElement getter = definingClass.getGetter(fieldName); |
| 636 if (getter != null) { | 635 if (getter != null) { |
| 637 PropertyInducingElement field = getter.variable; | 636 PropertyInducingElement field = getter.variable; |
| 638 if (!runtimeTypeMatch(evaluationResult, field.type)) { | 637 if (!runtimeTypeMatch(evaluationResult, field.type)) { |
| 639 errorReporter.reportErrorForNode( | 638 errorReporter.reportErrorForNode( |
| 640 CheckedModeCompileTimeErrorCode | 639 CheckedModeCompileTimeErrorCode |
| 641 .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, | 640 .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
| 642 node, | 641 node, |
| 643 [evaluationResult.type, fieldName, field.type]); | 642 [evaluationResult.type, fieldName, field.type]); |
| 644 } | 643 } |
| 645 } | 644 } |
| 646 } | 645 } |
| 647 } else if (initializer is SuperConstructorInvocation) { | 646 } else if (initializer is SuperConstructorInvocation) { |
| 648 SuperConstructorInvocation superConstructorInvocation = initializer; | 647 SimpleIdentifier name = initializer.constructorName; |
| 649 SimpleIdentifier name = superConstructorInvocation.constructorName; | |
| 650 if (name != null) { | 648 if (name != null) { |
| 651 superName = name.name; | 649 superName = name.name; |
| 652 } | 650 } |
| 653 superArguments = superConstructorInvocation.argumentList.arguments; | 651 superArguments = initializer.argumentList.arguments; |
| 654 } else if (initializer is RedirectingConstructorInvocation) { | 652 } else if (initializer is RedirectingConstructorInvocation) { |
| 655 // This is a redirecting constructor, so just evaluate the constructor | 653 // This is a redirecting constructor, so just evaluate the constructor |
| 656 // it redirects to. | 654 // it redirects to. |
| 657 ConstructorElement constructor = initializer.staticElement; | 655 ConstructorElement constructor = initializer.staticElement; |
| 658 if (constructor != null && constructor.isConst) { | 656 if (constructor != null && constructor.isConst) { |
| 659 return evaluateConstructorCall( | 657 return evaluateConstructorCall( |
| 660 node, | 658 node, |
| 661 initializer.argumentList.arguments, | 659 initializer.argumentList.arguments, |
| 662 constructor, | 660 constructor, |
| 663 initializerVisitor, | 661 initializerVisitor, |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 } | 1324 } |
| 1327 InterfaceType mapType = | 1325 InterfaceType mapType = |
| 1328 _typeProvider.mapType.instantiate([keyType, valueType]); | 1326 _typeProvider.mapType.instantiate([keyType, valueType]); |
| 1329 return new DartObjectImpl(mapType, new MapState(map)); | 1327 return new DartObjectImpl(mapType, new MapState(map)); |
| 1330 } | 1328 } |
| 1331 | 1329 |
| 1332 @override | 1330 @override |
| 1333 DartObjectImpl visitMethodInvocation(MethodInvocation node) { | 1331 DartObjectImpl visitMethodInvocation(MethodInvocation node) { |
| 1334 Element element = node.methodName.staticElement; | 1332 Element element = node.methodName.staticElement; |
| 1335 if (element is FunctionElement) { | 1333 if (element is FunctionElement) { |
| 1336 FunctionElement function = element; | 1334 if (element.name == "identical") { |
| 1337 if (function.name == "identical") { | |
| 1338 NodeList<Expression> arguments = node.argumentList.arguments; | 1335 NodeList<Expression> arguments = node.argumentList.arguments; |
| 1339 if (arguments.length == 2) { | 1336 if (arguments.length == 2) { |
| 1340 Element enclosingElement = function.enclosingElement; | 1337 Element enclosingElement = element.enclosingElement; |
| 1341 if (enclosingElement is CompilationUnitElement) { | 1338 if (enclosingElement is CompilationUnitElement) { |
| 1342 LibraryElement library = enclosingElement.library; | 1339 LibraryElement library = enclosingElement.library; |
| 1343 if (library.isDartCore) { | 1340 if (library.isDartCore) { |
| 1344 DartObjectImpl leftArgument = arguments[0].accept(this); | 1341 DartObjectImpl leftArgument = arguments[0].accept(this); |
| 1345 DartObjectImpl rightArgument = arguments[1].accept(this); | 1342 DartObjectImpl rightArgument = arguments[1].accept(this); |
| 1346 return _dartObjectComputer.isIdentical( | 1343 return _dartObjectComputer.isIdentical( |
| 1347 node, leftArgument, rightArgument); | 1344 node, leftArgument, rightArgument); |
| 1348 } | 1345 } |
| 1349 } | 1346 } |
| 1350 } | 1347 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 _errorReporter.reportErrorForNode( | 1478 _errorReporter.reportErrorForNode( |
| 1482 code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node); | 1479 code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node); |
| 1483 } | 1480 } |
| 1484 | 1481 |
| 1485 /** | 1482 /** |
| 1486 * Return the constant value of the static constant represented by the given | 1483 * Return the constant value of the static constant represented by the given |
| 1487 * [element]. The [node] is the node to be used if an error needs to be | 1484 * [element]. The [node] is the node to be used if an error needs to be |
| 1488 * reported. | 1485 * reported. |
| 1489 */ | 1486 */ |
| 1490 DartObjectImpl _getConstantValue(AstNode node, Element element) { | 1487 DartObjectImpl _getConstantValue(AstNode node, Element element) { |
| 1491 if (element is PropertyAccessorElement) { | 1488 Element variableElement = |
| 1492 element = (element as PropertyAccessorElement).variable; | 1489 element is PropertyAccessorElement ? element.variable : element; |
| 1493 } | 1490 if (variableElement is VariableElementImpl) { |
| 1494 if (element is VariableElementImpl) { | 1491 evaluationEngine.validator.beforeGetEvaluationResult(variableElement); |
| 1495 VariableElementImpl variableElementImpl = element; | 1492 EvaluationResultImpl value = variableElement.evaluationResult; |
| 1496 evaluationEngine.validator.beforeGetEvaluationResult(element); | 1493 if (variableElement.isConst && value != null) { |
| 1497 EvaluationResultImpl value = variableElementImpl.evaluationResult; | |
| 1498 if (variableElementImpl.isConst && value != null) { | |
| 1499 return value.value; | 1494 return value.value; |
| 1500 } | 1495 } |
| 1501 } else if (element is ExecutableElement) { | 1496 } else if (variableElement is ExecutableElement) { |
| 1502 ExecutableElement function = element; | 1497 ExecutableElement function = element; |
| 1503 if (function.isStatic) { | 1498 if (function.isStatic) { |
| 1504 ParameterizedType functionType = function.type; | 1499 ParameterizedType functionType = function.type; |
| 1505 if (functionType == null) { | 1500 if (functionType == null) { |
| 1506 functionType = _typeProvider.functionType; | 1501 functionType = _typeProvider.functionType; |
| 1507 } | 1502 } |
| 1508 return new DartObjectImpl(functionType, new FunctionState(function)); | 1503 return new DartObjectImpl(functionType, new FunctionState(function)); |
| 1509 } | 1504 } |
| 1510 } else if (element is ClassElement || | 1505 } else if (variableElement is ClassElement || |
| 1511 element is FunctionTypeAliasElement || | 1506 variableElement is FunctionTypeAliasElement || |
| 1512 element is DynamicElementImpl) { | 1507 variableElement is DynamicElementImpl) { |
| 1513 return new DartObjectImpl(_typeProvider.typeType, new TypeState(element)); | 1508 return new DartObjectImpl(_typeProvider.typeType, new TypeState(element)); |
| 1514 } | 1509 } |
| 1515 // TODO(brianwilkerson) Figure out which error to report. | 1510 // TODO(brianwilkerson) Figure out which error to report. |
| 1516 _error(node, null); | 1511 _error(node, null); |
| 1517 return null; | 1512 return null; |
| 1518 } | 1513 } |
| 1519 | 1514 |
| 1520 /** | 1515 /** |
| 1521 * Return `true` if the given [targetResult] represents a string and the | 1516 * Return `true` if the given [targetResult] represents a string and the |
| 1522 * [identifier] is "length". | 1517 * [identifier] is "length". |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1995 } | 1990 } |
| 1996 | 1991 |
| 1997 @override | 1992 @override |
| 1998 String toString() { | 1993 String toString() { |
| 1999 if (value == null) { | 1994 if (value == null) { |
| 2000 return "error"; | 1995 return "error"; |
| 2001 } | 1996 } |
| 2002 return value.toString(); | 1997 return value.toString(); |
| 2003 } | 1998 } |
| 2004 } | 1999 } |
| OLD | NEW |