Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(963)

Side by Side Diff: lib/src/checker/resolver.dart

Issue 1055923002: Don't call dinvoke on Object methods (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Refactor dynamic target logic Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698