| OLD | NEW | 
|---|
| 1 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Encapsulates how to invoke the analyzer resolver and overrides how it | 5 /// Encapsulates how to invoke the analyzer resolver and overrides how it | 
| 6 /// computes types on expressions to use our restricted set of types. | 6 /// computes types on expressions to use our restricted set of types. | 
| 7 library dev_compiler.src.checker.resolver; | 7 library dev_compiler.src.checker.resolver; | 
| 8 | 8 | 
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; | 
| 10 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; | 
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 657     var element = node.element as LocalVariableElementImpl; | 657     var element = node.element as LocalVariableElementImpl; | 
| 658     var exprType = expr.staticType; | 658     var exprType = expr.staticType; | 
| 659     if (exprType is InterfaceType) { | 659     if (exprType is InterfaceType) { | 
| 660       var iteratedType = _findIteratedType(exprType); | 660       var iteratedType = _findIteratedType(exprType); | 
| 661       if (iteratedType != null) { | 661       if (iteratedType != null) { | 
| 662         element.type = iteratedType; | 662         element.type = iteratedType; | 
| 663       } | 663       } | 
| 664     } | 664     } | 
| 665   } | 665   } | 
| 666 | 666 | 
|  | 667   Map<String, DartType> _objectMemberMap = null; | 
|  | 668 | 
|  | 669   Map<String, DartType> _getObjectMemberMap() { | 
|  | 670     if (_objectMemberMap == null) { | 
|  | 671       _objectMemberMap = new Map<String, DartType>(); | 
|  | 672       var objectType = _typeProvider.objectType; | 
|  | 673       var element = objectType.element; | 
|  | 674       // Only record methods (including getters) with no parameters.  As paramet
     ers are contravariant wrt | 
|  | 675       // type, using Object's version may be too strict. | 
|  | 676       // Add instance methods. | 
|  | 677       element.methods | 
|  | 678           .where((method) => !method.isStatic && method.parameters.isEmpty) | 
|  | 679           .forEach((method) { | 
|  | 680         _objectMemberMap[method.name] = method.type; | 
|  | 681       }); | 
|  | 682       // Add getters. | 
|  | 683       element.accessors | 
|  | 684           .where((member) => !member.isStatic && member.isGetter) | 
|  | 685           .forEach((member) { | 
|  | 686         _objectMemberMap[member.name] = member.type.returnType; | 
|  | 687       }); | 
|  | 688     } | 
|  | 689     return _objectMemberMap; | 
|  | 690   } | 
|  | 691 | 
|  | 692   List<DartType> _sealedTypes = null; | 
|  | 693 | 
|  | 694   bool _isSealed(DartType t) { | 
|  | 695     if (_sealedTypes == null) { | 
|  | 696       // TODO(vsm): Use the analyzer's list - see dartbug.com/23125. | 
|  | 697       _sealedTypes = <DartType>[ | 
|  | 698         _typeProvider.nullType, | 
|  | 699         _typeProvider.numType, | 
|  | 700         _typeProvider.intType, | 
|  | 701         _typeProvider.doubleType, | 
|  | 702         _typeProvider.boolType, | 
|  | 703         _typeProvider.stringType | 
|  | 704       ]; | 
|  | 705     } | 
|  | 706     return _sealedTypes.contains(t); | 
|  | 707   } | 
|  | 708 | 
| 667   @override // to propagate types to identifiers | 709   @override // to propagate types to identifiers | 
| 668   visitMethodInvocation(MethodInvocation node) { | 710   visitMethodInvocation(MethodInvocation node) { | 
| 669     // TODO(sigmund): follow up with analyzer team - why is this needed? | 711     // TODO(sigmund): follow up with analyzer team - why is this needed? | 
| 670     visitSimpleIdentifier(node.methodName); | 712     visitSimpleIdentifier(node.methodName); | 
| 671     super.visitMethodInvocation(node); | 713     super.visitMethodInvocation(node); | 
| 672 | 714 | 
|  | 715     // Search for Object methods. | 
|  | 716     var objectMap = _getObjectMemberMap(); | 
|  | 717     var name = node.methodName.name; | 
|  | 718     if (node.staticType.isDynamic && | 
|  | 719         objectMap.containsKey(name) && | 
|  | 720         isDynamicTarget(node.target)) { | 
|  | 721       var type = objectMap[name]; | 
|  | 722       if (type is FunctionType && node.argumentList.arguments.isEmpty) { | 
|  | 723         node.target.staticType = _typeProvider.objectType; | 
|  | 724         node.methodName.staticType = type; | 
|  | 725         // Only infer the type of the overall expression if we have an exact | 
|  | 726         // type - e.g., a sealed type.  Otherwise, it may be too strict. | 
|  | 727         if (_isSealed(type.returnType)) { | 
|  | 728           node.staticType = type.returnType; | 
|  | 729         } | 
|  | 730       } | 
|  | 731     } | 
|  | 732 | 
| 673     var e = node.methodName.staticElement; | 733     var e = node.methodName.staticElement; | 
| 674     if (e is FunctionElement && | 734     if (e is FunctionElement && | 
| 675         e.library.name == '_foreign_helper' && | 735         e.library.name == '_foreign_helper' && | 
| 676         e.name == 'JS') { | 736         e.name == 'JS') { | 
| 677       // Fix types for JS builtin calls. | 737       // Fix types for JS builtin calls. | 
| 678       // | 738       // | 
| 679       // This code was taken from analyzer. It's not super sophisticated: | 739       // This code was taken from analyzer. It's not super sophisticated: | 
| 680       // only looks for the type name in dart:core, so we just copy it here. | 740       // only looks for the type name in dart:core, so we just copy it here. | 
| 681       // | 741       // | 
| 682       // TODO(jmesserly): we'll likely need something that can handle a wider | 742       // TODO(jmesserly): we'll likely need something that can handle a wider | 
| 683       // variety of types, especially when we get to JS interop. | 743       // variety of types, especially when we get to JS interop. | 
| 684       var args = node.argumentList.arguments; | 744       var args = node.argumentList.arguments; | 
| 685       if (args.isNotEmpty && args.first is SimpleStringLiteral) { | 745       if (args.isNotEmpty && args.first is SimpleStringLiteral) { | 
| 686         var coreLib = _typeProvider.objectType.element.library; | 746         var coreLib = _typeProvider.objectType.element.library; | 
| 687         var classElem = coreLib.getType(args.first.stringValue); | 747         var classElem = coreLib.getType(args.first.stringValue); | 
| 688         if (classElem != null) node.staticType = classElem.type; | 748         if (classElem != null) node.staticType = classElem.type; | 
| 689       } | 749       } | 
| 690     } | 750     } | 
| 691   } | 751   } | 
| 692 | 752 | 
|  | 753   void _inferObjectAccess( | 
|  | 754       Expression node, Expression target, SimpleIdentifier id) { | 
|  | 755     // Search for Object accesses. | 
|  | 756     var objectMap = _getObjectMemberMap(); | 
|  | 757     var name = id.name; | 
|  | 758     if (node.staticType.isDynamic && | 
|  | 759         objectMap.containsKey(name) && | 
|  | 760         isDynamicTarget(target)) { | 
|  | 761       target.staticType = _typeProvider.objectType; | 
|  | 762       var type = objectMap[name]; | 
|  | 763       id.staticType = type; | 
|  | 764       // Only infer the type of the overall expression if we have an exact | 
|  | 765       // type - e.g., a sealed type.  Otherwise, it may be too strict. | 
|  | 766       if (_isSealed(type)) { | 
|  | 767         node.staticType = type; | 
|  | 768       } | 
|  | 769     } | 
|  | 770   } | 
|  | 771 | 
|  | 772   @override | 
|  | 773   visitPropertyAccess(PropertyAccess node) { | 
|  | 774     super.visitPropertyAccess(node); | 
|  | 775 | 
|  | 776     _inferObjectAccess(node, node.target, node.propertyName); | 
|  | 777   } | 
|  | 778 | 
|  | 779   @override | 
|  | 780   visitPrefixedIdentifier(PrefixedIdentifier node) { | 
|  | 781     super.visitPrefixedIdentifier(node); | 
|  | 782 | 
|  | 783     _inferObjectAccess(node, node.prefix, node.identifier); | 
|  | 784   } | 
|  | 785 | 
| 693   @override | 786   @override | 
| 694   visitConditionalExpression(ConditionalExpression node) { | 787   visitConditionalExpression(ConditionalExpression node) { | 
| 695     // TODO(vsm): The static type of a conditional should be the LUB of the | 788     // TODO(vsm): The static type of a conditional should be the LUB of the | 
| 696     // then and else expressions.  The analyzer appears to compute dynamic when | 789     // then and else expressions.  The analyzer appears to compute dynamic when | 
| 697     // one or the other is the null literal.  Remove this fix once the | 790     // one or the other is the null literal.  Remove this fix once the | 
| 698     // corresponding analyzer bug is fixed: | 791     // corresponding analyzer bug is fixed: | 
| 699     // https://code.google.com/p/dart/issues/detail?id=22854 | 792     // https://code.google.com/p/dart/issues/detail?id=22854 | 
| 700     super.visitConditionalExpression(node); | 793     super.visitConditionalExpression(node); | 
| 701     if (node.staticType.isDynamic) { | 794     if (node.staticType.isDynamic) { | 
| 702       var thenExpr = node.thenExpression; | 795       var thenExpr = node.thenExpression; | 
| 703       var elseExpr = node.elseExpression; | 796       var elseExpr = node.elseExpression; | 
| 704       if (thenExpr.staticType.isBottom) { | 797       if (thenExpr.staticType.isBottom) { | 
| 705         node.staticType = elseExpr.staticType; | 798         node.staticType = elseExpr.staticType; | 
| 706       } else if (elseExpr.staticType.isBottom) { | 799       } else if (elseExpr.staticType.isBottom) { | 
| 707         node.staticType = thenExpr.staticType; | 800         node.staticType = thenExpr.staticType; | 
| 708       } | 801       } | 
| 709     } | 802     } | 
| 710   } | 803   } | 
| 711 | 804 | 
| 712   // Review note: no longer need to override visitFunctionExpression, this is | 805   // Review note: no longer need to override visitFunctionExpression, this is | 
| 713   // handled by the analyzer internally. | 806   // handled by the analyzer internally. | 
| 714   // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? | 807   // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? | 
| 715   // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression | 808   // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression | 
| 716   // type in a (...) => expr or just the written type? | 809   // type in a (...) => expr or just the written type? | 
| 717 | 810 | 
| 718 } | 811 } | 
| OLD | NEW | 
|---|