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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 } | 415 } |
416 } | 416 } |
417 return value; | 417 return value; |
418 } | 418 } |
419 | 419 |
420 DartObjectImpl evaluateConstructorCall( | 420 DartObjectImpl evaluateConstructorCall( |
421 AstNode node, | 421 AstNode node, |
422 List<Expression> arguments, | 422 List<Expression> arguments, |
423 ConstructorElement constructor, | 423 ConstructorElement constructor, |
424 ConstantVisitor constantVisitor, | 424 ConstantVisitor constantVisitor, |
425 ErrorReporter errorReporter) { | 425 ErrorReporter errorReporter, |
| 426 {ConstructorElement originalConstructor, |
| 427 List<DartObjectImpl> originalArguments, |
| 428 Map<String, DartObjectImpl> originalNamedArguments}) { |
426 if (!getConstructorImpl(constructor).isCycleFree) { | 429 if (!getConstructorImpl(constructor).isCycleFree) { |
427 // It's not safe to evaluate this constructor, so bail out. | 430 // It's not safe to evaluate this constructor, so bail out. |
428 // TODO(paulberry): ensure that a reasonable error message is produced | 431 // TODO(paulberry): ensure that a reasonable error message is produced |
429 // in this case, as well as other cases involving constant expression | 432 // in this case, as well as other cases involving constant expression |
430 // circularities (e.g. "compile-time constant expression depends on | 433 // circularities (e.g. "compile-time constant expression depends on |
431 // itself") | 434 // itself") |
432 return new DartObjectImpl.validWithUnknownValue(constructor.returnType); | 435 return new DartObjectImpl.validWithUnknownValue(constructor.returnType); |
433 } | 436 } |
434 int argumentCount = arguments.length; | 437 int argumentCount = arguments.length; |
435 List<DartObjectImpl> argumentValues = | 438 List<DartObjectImpl> argumentValues = |
436 new List<DartObjectImpl>(argumentCount); | 439 new List<DartObjectImpl>(argumentCount); |
| 440 List<DartObjectImpl> positionalArguments = <DartObjectImpl>[]; |
437 List<Expression> argumentNodes = new List<Expression>(argumentCount); | 441 List<Expression> argumentNodes = new List<Expression>(argumentCount); |
438 HashMap<String, DartObjectImpl> namedArgumentValues = | 442 HashMap<String, DartObjectImpl> namedArgumentValues = |
439 new HashMap<String, DartObjectImpl>(); | 443 new HashMap<String, DartObjectImpl>(); |
440 HashMap<String, NamedExpression> namedArgumentNodes = | 444 HashMap<String, NamedExpression> namedArgumentNodes = |
441 new HashMap<String, NamedExpression>(); | 445 new HashMap<String, NamedExpression>(); |
442 for (int i = 0; i < argumentCount; i++) { | 446 for (int i = 0; i < argumentCount; i++) { |
443 Expression argument = arguments[i]; | 447 Expression argument = arguments[i]; |
444 if (argument is NamedExpression) { | 448 if (argument is NamedExpression) { |
445 String name = argument.name.label.name; | 449 String name = argument.name.label.name; |
446 namedArgumentValues[name] = | 450 namedArgumentValues[name] = |
447 constantVisitor._valueOf(argument.expression); | 451 constantVisitor._valueOf(argument.expression); |
448 namedArgumentNodes[name] = argument; | 452 namedArgumentNodes[name] = argument; |
449 argumentValues[i] = typeProvider.nullObject; | 453 argumentValues[i] = typeProvider.nullObject; |
450 } else { | 454 } else { |
451 argumentValues[i] = constantVisitor._valueOf(argument); | 455 var argumentValue = constantVisitor._valueOf(argument); |
| 456 argumentValues[i] = argumentValue; |
| 457 positionalArguments.add(argumentValue); |
452 argumentNodes[i] = argument; | 458 argumentNodes[i] = argument; |
453 } | 459 } |
454 } | 460 } |
| 461 if (originalConstructor == null) { |
| 462 originalConstructor = constructor; |
| 463 originalArguments = positionalArguments; |
| 464 originalNamedArguments = namedArgumentValues; |
| 465 } |
455 constructor = followConstantRedirectionChain(constructor); | 466 constructor = followConstantRedirectionChain(constructor); |
456 InterfaceType definingClass = constructor.returnType as InterfaceType; | 467 InterfaceType definingClass = constructor.returnType as InterfaceType; |
457 if (constructor.isFactory) { | 468 if (constructor.isFactory) { |
458 // We couldn't find a non-factory constructor. | 469 // We couldn't find a non-factory constructor. |
459 // See if it's because we reached an external const factory constructor | 470 // See if it's because we reached an external const factory constructor |
460 // that we can emulate. | 471 // that we can emulate. |
461 if (constructor.name == "fromEnvironment") { | 472 if (constructor.name == "fromEnvironment") { |
462 if (!checkFromEnvironmentArguments( | 473 if (!checkFromEnvironmentArguments( |
463 arguments, argumentValues, namedArgumentValues, definingClass)) { | 474 arguments, argumentValues, namedArgumentValues, definingClass)) { |
464 errorReporter.reportErrorForNode( | 475 errorReporter.reportErrorForNode( |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 } else if (initializer is RedirectingConstructorInvocation) { | 713 } else if (initializer is RedirectingConstructorInvocation) { |
703 // This is a redirecting constructor, so just evaluate the constructor | 714 // This is a redirecting constructor, so just evaluate the constructor |
704 // it redirects to. | 715 // it redirects to. |
705 ConstructorElement constructor = initializer.staticElement; | 716 ConstructorElement constructor = initializer.staticElement; |
706 if (constructor != null && constructor.isConst) { | 717 if (constructor != null && constructor.isConst) { |
707 return evaluateConstructorCall( | 718 return evaluateConstructorCall( |
708 node, | 719 node, |
709 initializer.argumentList.arguments, | 720 initializer.argumentList.arguments, |
710 constructor, | 721 constructor, |
711 initializerVisitor, | 722 initializerVisitor, |
712 errorReporter); | 723 errorReporter, |
| 724 originalConstructor: originalConstructor, |
| 725 originalArguments: originalArguments, |
| 726 originalNamedArguments: originalNamedArguments); |
713 } | 727 } |
714 } | 728 } |
715 } | 729 } |
716 // Evaluate explicit or implicit call to super(). | 730 // Evaluate explicit or implicit call to super(). |
717 InterfaceType superclass = definingClass.superclass; | 731 InterfaceType superclass = definingClass.superclass; |
718 if (superclass != null && !superclass.isObject) { | 732 if (superclass != null && !superclass.isObject) { |
719 ConstructorElement superConstructor = | 733 ConstructorElement superConstructor = |
720 superclass.lookUpConstructor(superName, constructor.library); | 734 superclass.lookUpConstructor(superName, constructor.library); |
721 if (superConstructor != null) { | 735 if (superConstructor != null) { |
722 if (superArguments == null) { | 736 if (superArguments == null) { |
723 superArguments = astFactory.nodeList/*<Expression>*/(null); | 737 superArguments = astFactory.nodeList/*<Expression>*/(null); |
724 } | 738 } |
725 | 739 |
726 evaluateSuperConstructorCall(node, fieldMap, superConstructor, | 740 evaluateSuperConstructorCall(node, fieldMap, superConstructor, |
727 superArguments, initializerVisitor, errorReporter); | 741 superArguments, initializerVisitor, errorReporter); |
728 } | 742 } |
729 } | 743 } |
730 return new DartObjectImpl(definingClass, new GenericState(fieldMap)); | 744 return new DartObjectImpl( |
| 745 definingClass, |
| 746 new GenericState(fieldMap, |
| 747 constructor: originalConstructor, |
| 748 positionalArguments: originalArguments, |
| 749 namedArguments: originalNamedArguments)); |
731 } | 750 } |
732 | 751 |
733 void evaluateSuperConstructorCall( | 752 void evaluateSuperConstructorCall( |
734 AstNode node, | 753 AstNode node, |
735 HashMap<String, DartObjectImpl> fieldMap, | 754 HashMap<String, DartObjectImpl> fieldMap, |
736 ConstructorElement superConstructor, | 755 ConstructorElement superConstructor, |
737 List<Expression> superArguments, | 756 List<Expression> superArguments, |
738 ConstantVisitor initializerVisitor, | 757 ConstantVisitor initializerVisitor, |
739 ErrorReporter errorReporter) { | 758 ErrorReporter errorReporter) { |
740 if (superConstructor != null && superConstructor.isConst) { | 759 if (superConstructor != null && superConstructor.isConst) { |
(...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2086 } | 2105 } |
2087 | 2106 |
2088 @override | 2107 @override |
2089 String toString() { | 2108 String toString() { |
2090 if (value == null) { | 2109 if (value == null) { |
2091 return "error"; | 2110 return "error"; |
2092 } | 2111 } |
2093 return value.toString(); | 2112 return value.toString(); |
2094 } | 2113 } |
2095 } | 2114 } |
OLD | NEW |