Chromium Code Reviews| 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 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 if (iteratedType != null) { | 598 if (iteratedType != null) { |
| 599 element.type = iteratedType; | 599 element.type = iteratedType; |
| 600 } | 600 } |
| 601 } | 601 } |
| 602 } | 602 } |
| 603 | 603 |
| 604 bool _isSealed(DartType t) { | 604 bool _isSealed(DartType t) { |
| 605 return _typeProvider.nonSubtypableTypes.contains(t); | 605 return _typeProvider.nonSubtypableTypes.contains(t); |
| 606 } | 606 } |
| 607 | 607 |
| 608 List<List> _genericList = null; | |
| 609 | |
| 610 DartType _matchGeneric(MethodInvocation node, Element element) { | |
| 611 var e = node.methodName.staticElement; | |
| 612 | |
| 613 if (_genericList == null) { | |
| 614 var minmax = (DartType tx, DartType ty) => (tx == ty && | |
| 615 (tx == _typeProvider.intType || tx == _typeProvider.doubleType)) | |
| 616 ? tx | |
| 617 : null; | |
| 618 | |
| 619 var map = (DartType tx) => (tx is FunctionType) | |
| 620 ? _typeProvider.iterableType.substitute4([tx.returnType]) | |
|
vsm
2015/08/28 15:48:50
Hmm - rethinking this ... If my target type (stat
| |
| 621 : null; | |
| 622 | |
| 623 // TODO(vsm): LUB? | |
| 624 var fold = (DartType tx, DartType ty) => | |
| 625 (ty is FunctionType && tx == ty.returnType) ? tx : null; | |
| 626 | |
| 627 // TODO(vsm): Flatten? | |
| 628 var then = (DartType tx) => | |
| 629 (tx is FunctionType && !tx.returnType.isDynamic) | |
|
Leaf
2015/08/28 01:05:38
Why are you checking for dynamic here, and not els
| |
| 630 ? _typeProvider.futureType.substitute4([tx.returnType]) | |
| 631 : null; | |
| 632 | |
| 633 var wait = (DartType tx) { | |
| 634 // Iterable<Future<T>> -> Future<List<T>> | |
| 635 var futureType = _findIteratedType(tx); | |
| 636 if (futureType.element.type != _typeProvider.futureType) return null; | |
| 637 var typeArguments = futureType.typeArguments; | |
| 638 if (typeArguments.length != 1) return null; | |
| 639 var baseType = typeArguments[0]; | |
| 640 if (baseType.isDynamic) return null; | |
| 641 return _typeProvider.futureType.substitute4([ | |
| 642 _typeProvider.listType.substitute4([baseType]) | |
| 643 ]); | |
| 644 }; | |
| 645 | |
| 646 _genericList = [ | |
| 647 // Top-level methods | |
| 648 ['dart:math', 'max', 2, minmax], | |
| 649 ['dart:math', 'min', 2, minmax], | |
| 650 // Static methods | |
| 651 [_typeProvider.futureType, 'wait', 1, wait], | |
| 652 // Instance methods | |
| 653 [_typeProvider.iterableDynamicType, 'map', 1, map], | |
| 654 [_typeProvider.iterableDynamicType, 'fold', 2, fold], | |
| 655 [_typeProvider.futureDynamicType, 'then', 1, then], | |
| 656 ]; | |
| 657 } | |
| 658 | |
| 659 var targetType = node.target?.staticType; | |
| 660 var arguments = node.argumentList.arguments; | |
| 661 | |
| 662 for (var generic in _genericList) { | |
| 663 if (e?.name == generic[1]) { | |
| 664 if ((generic[0] is String && | |
| 665 element?.library.source.uri.toString() == generic[0]) || | |
| 666 (targetType == generic[0] || | |
| 667 targetType != null && targetType.isSubtypeOf(generic[0]))) { | |
| 668 if (arguments.length == generic[2]) { | |
| 669 return Function.apply( | |
| 670 generic[3], arguments.map((arg) => arg.staticType).toList()); | |
| 671 } | |
| 672 } | |
| 673 } | |
| 674 } | |
| 675 | |
| 676 return null; | |
| 677 } | |
| 678 | |
| 608 @override // to propagate types to identifiers | 679 @override // to propagate types to identifiers |
| 609 visitMethodInvocation(MethodInvocation node) { | 680 visitMethodInvocation(MethodInvocation node) { |
| 610 // TODO(jmesserly): we rely on having a staticType propagated to the | 681 // TODO(jmesserly): we rely on having a staticType propagated to the |
| 611 // methodName identifier. This shouldn't be necessary for method calls, so | 682 // methodName identifier. This shouldn't be necessary for method calls, so |
| 612 // analyzer doesn't do it by default. Conceptually what we're doing here | 683 // analyzer doesn't do it by default. Conceptually what we're doing here |
| 613 // is asking for a tear off. We need this until we can fix #132, and rely | 684 // is asking for a tear off. We need this until we can fix #132, and rely |
| 614 // on `node.staticElement == null` instead of `rules.isDynamicCall(node)`. | 685 // on `node.staticElement == null` instead of `rules.isDynamicCall(node)`. |
| 615 visitSimpleIdentifier(node.methodName); | 686 visitSimpleIdentifier(node.methodName); |
| 616 | 687 |
| 617 super.visitMethodInvocation(node); | 688 super.visitMethodInvocation(node); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 // | 736 // |
| 666 // T min<T extends num>(T x, T y); | 737 // T min<T extends num>(T x, T y); |
| 667 // | 738 // |
| 668 // and infer T. In practice, this just means if the type of x and y are | 739 // and infer T. In practice, this just means if the type of x and y are |
| 669 // both double or both int, we treat that as the return type. | 740 // both double or both int, we treat that as the return type. |
| 670 // | 741 // |
| 671 // The Dart spec has similar treatment for binary operations on numbers. | 742 // The Dart spec has similar treatment for binary operations on numbers. |
| 672 // | 743 // |
| 673 // TODO(jmesserly): remove this when we have a fix for | 744 // TODO(jmesserly): remove this when we have a fix for |
| 674 // https://github.com/dart-lang/dev_compiler/issues/28 | 745 // https://github.com/dart-lang/dev_compiler/issues/28 |
| 675 if (isDartMathMinMax(e)) { | 746 var inferred = _matchGeneric(node, e); |
| 676 var args = node.argumentList.arguments; | 747 if (inferred != null) node.staticType = inferred; |
| 677 if (args.length == 2) { | |
| 678 var tx = args[0].staticType; | |
| 679 var ty = args[1].staticType; | |
| 680 if (tx == ty && | |
| 681 (tx == _typeProvider.intType || tx == _typeProvider.doubleType)) { | |
| 682 node.staticType = tx; | |
| 683 } | |
| 684 } | |
| 685 } | |
| 686 } | 748 } |
| 687 | 749 |
| 688 void _inferObjectAccess( | 750 void _inferObjectAccess( |
| 689 Expression node, Expression target, SimpleIdentifier id) { | 751 Expression node, Expression target, SimpleIdentifier id) { |
| 690 // Search for Object accesses. | 752 // Search for Object accesses. |
| 691 var name = id.name; | 753 var name = id.name; |
| 692 if (node.staticType.isDynamic && | 754 if (node.staticType.isDynamic && |
| 693 _objectMembers.containsKey(name) && | 755 _objectMembers.containsKey(name) && |
| 694 isDynamicTarget(target)) { | 756 isDynamicTarget(target)) { |
| 695 target.staticType = _typeProvider.objectType; | 757 target.staticType = _typeProvider.objectType; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 } | 798 } |
| 737 } | 799 } |
| 738 | 800 |
| 739 // Review note: no longer need to override visitFunctionExpression, this is | 801 // Review note: no longer need to override visitFunctionExpression, this is |
| 740 // handled by the analyzer internally. | 802 // handled by the analyzer internally. |
| 741 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? | 803 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? |
| 742 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression | 804 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression |
| 743 // type in a (...) => expr or just the written type? | 805 // type in a (...) => expr or just the written type? |
| 744 | 806 |
| 745 } | 807 } |
| OLD | NEW |