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

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: Fix for sealed types 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> _nonExtendableTypes = null;
693
694 bool _isExtendable(DartType t) {
695 if (_nonExtendableTypes == null) {
696 // TODO(vsm): Use the analyzer's list - see dartbug.com/23125.
697 _nonExtendableTypes = <DartType>[
698 _typeProvider.nullType,
699 _typeProvider.numType,
700 _typeProvider.intType,
701 _typeProvider.doubleType,
702 _typeProvider.boolType,
703 _typeProvider.stringType
704 ];
705 }
706 return !_nonExtendableTypes.contains(t);
Jennifer Messerly 2015/04/07 19:05:49 whenever you're calling _isExtendable it's being i
vsm 2015/04/07 19:48:46 Done.
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 && objectMap.containsKey(name)) {
719 var target = node.target;
720 if (target is SimpleIdentifier &&
Jennifer Messerly 2015/04/07 19:05:49 why does target need to be a SimpleIdentifier? doe
vsm 2015/04/07 19:48:46 Good point. Fixed and test added.
721 target.staticElement is! PrefixElement) {
Jennifer Messerly 2015/04/07 19:05:49 follow up to above suggestion, I wonder if somethi
vsm 2015/04/07 19:48:46 It cleans it up. Done.
722 var type = objectMap[name];
723 if (type is FunctionType && node.argumentList.arguments.isEmpty) {
724 node.methodName.staticType = type;
725 if (!_isExtendable(type.returnType)) {
726 // Don't infer the type of the overall expression in this case -
727 // it may be too strict.
Jennifer Messerly 2015/04/07 19:05:49 can this actually happen? I thought we didn't allo
vsm 2015/04/07 19:48:46 Note: my comment was in a confusing place - fixed
728 node.staticType = type.returnType;
729 }
730 }
731 }
732 }
733
673 var e = node.methodName.staticElement; 734 var e = node.methodName.staticElement;
674 if (e is FunctionElement && 735 if (e is FunctionElement &&
675 e.library.name == '_foreign_helper' && 736 e.library.name == '_foreign_helper' &&
676 e.name == 'JS') { 737 e.name == 'JS') {
677 // Fix types for JS builtin calls. 738 // Fix types for JS builtin calls.
678 // 739 //
679 // This code was taken from analyzer. It's not super sophisticated: 740 // 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. 741 // only looks for the type name in dart:core, so we just copy it here.
681 // 742 //
682 // TODO(jmesserly): we'll likely need something that can handle a wider 743 // TODO(jmesserly): we'll likely need something that can handle a wider
683 // variety of types, especially when we get to JS interop. 744 // variety of types, especially when we get to JS interop.
684 var args = node.argumentList.arguments; 745 var args = node.argumentList.arguments;
685 if (args.isNotEmpty && args.first is SimpleStringLiteral) { 746 if (args.isNotEmpty && args.first is SimpleStringLiteral) {
686 var coreLib = _typeProvider.objectType.element.library; 747 var coreLib = _typeProvider.objectType.element.library;
687 var classElem = coreLib.getType(args.first.stringValue); 748 var classElem = coreLib.getType(args.first.stringValue);
688 if (classElem != null) node.staticType = classElem.type; 749 if (classElem != null) node.staticType = classElem.type;
689 } 750 }
690 } 751 }
691 } 752 }
692 753
754 void _inferObjectAccess(
755 Expression node, Expression target, SimpleIdentifier id) {
756 // Search for Object accesses.
757 var objectMap = _getObjectMemberMap();
758 var name = id.name;
759 if (node.staticType.isDynamic && objectMap.containsKey(name)) {
760 if (target is SimpleIdentifier &&
761 target.staticElement is! PrefixElement) {
762 var type = objectMap[name];
763 id.staticType = type;
764 if (!_isExtendable(type)) {
765 // Don't infer the type of the overall expression in this case -
766 // it may be too strict.
767 node.staticType = type;
768 }
769 }
770 }
771 }
772
773 @override
774 visitPropertyAccess(PropertyAccess node) {
775 super.visitPropertyAccess(node);
776
777 _inferObjectAccess(node, node.target, node.propertyName);
778 }
779
780 @override
781 visitPrefixedIdentifier(PrefixedIdentifier node) {
782 super.visitPrefixedIdentifier(node);
783
784 _inferObjectAccess(node, node.prefix, node.identifier);
785 }
786
693 @override 787 @override
694 visitConditionalExpression(ConditionalExpression node) { 788 visitConditionalExpression(ConditionalExpression node) {
695 // TODO(vsm): The static type of a conditional should be the LUB of the 789 // 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 790 // 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 791 // one or the other is the null literal. Remove this fix once the
698 // corresponding analyzer bug is fixed: 792 // corresponding analyzer bug is fixed:
699 // https://code.google.com/p/dart/issues/detail?id=22854 793 // https://code.google.com/p/dart/issues/detail?id=22854
700 super.visitConditionalExpression(node); 794 super.visitConditionalExpression(node);
701 if (node.staticType.isDynamic) { 795 if (node.staticType.isDynamic) {
702 var thenExpr = node.thenExpression; 796 var thenExpr = node.thenExpression;
703 var elseExpr = node.elseExpression; 797 var elseExpr = node.elseExpression;
704 if (thenExpr.staticType.isBottom) { 798 if (thenExpr.staticType.isBottom) {
705 node.staticType = elseExpr.staticType; 799 node.staticType = elseExpr.staticType;
706 } else if (elseExpr.staticType.isBottom) { 800 } else if (elseExpr.staticType.isBottom) {
707 node.staticType = thenExpr.staticType; 801 node.staticType = thenExpr.staticType;
708 } 802 }
709 } 803 }
710 } 804 }
711 805
712 // Review note: no longer need to override visitFunctionExpression, this is 806 // Review note: no longer need to override visitFunctionExpression, this is
713 // handled by the analyzer internally. 807 // handled by the analyzer internally.
714 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? 808 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result?
715 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression 809 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression
716 // type in a (...) => expr or just the written type? 810 // type in a (...) => expr or just the written type?
717 811
718 } 812 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698