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

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2252183002: Fix calling object methods and properties on function types (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix calling object methods and properties on function types Created 4 years, 4 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
6 // refactored to fit into analyzer. 6 // refactored to fit into analyzer.
7 library analyzer.src.task.strong.checker; 7 library analyzer.src.task.strong.checker;
8 8
9 import 'package:analyzer/analyzer.dart'; 9 import 'package:analyzer/analyzer.dart';
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 checkArgument(entry.key, ktype); 547 checkArgument(entry.key, ktype);
548 checkArgument(entry.value, vtype); 548 checkArgument(entry.value, vtype);
549 } 549 }
550 super.visitMapLiteral(node); 550 super.visitMapLiteral(node);
551 } 551 }
552 552
553 @override 553 @override
554 visitMethodInvocation(MethodInvocation node) { 554 visitMethodInvocation(MethodInvocation node) {
555 var target = node.realTarget; 555 var target = node.realTarget;
556 var element = node.methodName.staticElement; 556 var element = node.methodName.staticElement;
557 if (element == null && !_isObjectMethod(node, node.methodName)) { 557 if (element == null && !typeProvider.isObjectMethod(node.methodName)) {
558 _recordDynamicInvoke(node, target); 558 _recordDynamicInvoke(node, target);
559 559
560 // Mark the tear-off as being dynamic, too. This lets us distinguish 560 // Mark the tear-off as being dynamic, too. This lets us distinguish
561 // cases like: 561 // cases like:
562 // 562 //
563 // dynamic d; 563 // dynamic d;
564 // d.someMethod(...); // the whole method call must be a dynamic send. 564 // d.someMethod(...); // the whole method call must be a dynamic send.
565 // 565 //
566 // ... from case like: 566 // ... from case like:
567 // 567 //
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 _recordImplicitCast(expr, from, to); 761 _recordImplicitCast(expr, from, to);
762 return; 762 return;
763 } 763 }
764 764
765 // Anything else is an illegal sideways cast. 765 // Anything else is an illegal sideways cast.
766 // However, these will have been reported already in error_verifier, so we 766 // However, these will have been reported already in error_verifier, so we
767 // don't need to report them again. 767 // don't need to report them again.
768 } 768 }
769 769
770 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { 770 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
771 if (field.staticElement == null && !_isObjectProperty(target, field)) { 771 if (field.staticElement == null && !typeProvider.isObjectProperty(field)) {
772 _recordDynamicInvoke(node, target); 772 _recordDynamicInvoke(node, target);
773 } 773 }
774 node.visitChildren(this); 774 node.visitChildren(this);
775 } 775 }
776 776
777 /** 777 /**
778 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so, 778 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so,
779 * issue a warning. 779 * issue a warning.
780 * 780 *
781 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed. 781 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 } 901 }
902 902
903 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { 903 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) {
904 var type = getType(typeName); 904 var type = getType(typeName);
905 if (!rules.isGroundType(type)) { 905 if (!rules.isGroundType(type)) {
906 _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]); 906 _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]);
907 } 907 }
908 } 908 }
909 909
910 void _checkUnary( 910 void _checkUnary(
911 /*PrefixExpression|PostfixExpression*/ node, Element element) { 911 /*PrefixExpression|PostfixExpression*/ node,
912 Element element) {
912 var op = node.operator; 913 var op = node.operator;
913 if (op.isUserDefinableOperator || 914 if (op.isUserDefinableOperator ||
914 op.type == TokenType.PLUS_PLUS || 915 op.type == TokenType.PLUS_PLUS ||
915 op.type == TokenType.MINUS_MINUS) { 916 op.type == TokenType.MINUS_MINUS) {
916 if (element == null) { 917 if (element == null) {
917 _recordDynamicInvoke(node, node.operand); 918 _recordDynamicInvoke(node, node.operand);
918 } 919 }
919 // For ++ and --, even if it is not dynamic, we still need to check 920 // For ++ and --, even if it is not dynamic, we still need to check
920 // that the user defined method accepts an `int` as the RHS. 921 // that the user defined method accepts an `int` as the RHS.
921 // We assume Analyzer has done this already. 922 // We assume Analyzer has done this already.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 // Dynamic as the parameter type is treated as bottom. A function with 1005 // Dynamic as the parameter type is treated as bottom. A function with
1005 // a dynamic parameter type requires a dynamic call in general. 1006 // a dynamic parameter type requires a dynamic call in general.
1006 // However, as an optimization, if we have an original definition, we know 1007 // However, as an optimization, if we have an original definition, we know
1007 // dynamic is reified as Object - in this case a regular call is fine. 1008 // dynamic is reified as Object - in this case a regular call is fine.
1008 if (_hasStrictArrow(call.function)) { 1009 if (_hasStrictArrow(call.function)) {
1009 return false; 1010 return false;
1010 } 1011 }
1011 return rules.anyParameterType(ft, (pt) => pt.isDynamic); 1012 return rules.anyParameterType(ft, (pt) => pt.isDynamic);
1012 } 1013 }
1013 1014
1014 bool _isObjectGetter(Expression target, SimpleIdentifier id) {
1015 PropertyAccessorElement element =
1016 typeProvider.objectType.element.getGetter(id.name);
1017 return (element != null && !element.isStatic);
1018 }
1019
1020 bool _isObjectMethod(Expression target, SimpleIdentifier id) {
1021 MethodElement element = typeProvider.objectType.element.getMethod(id.name);
1022 return (element != null && !element.isStatic);
1023 }
1024
1025 bool _isObjectProperty(Expression target, SimpleIdentifier id) {
1026 return _isObjectGetter(target, id) || _isObjectMethod(target, id);
1027 }
1028
1029 void _recordDynamicInvoke(AstNode node, Expression target) { 1015 void _recordDynamicInvoke(AstNode node, Expression target) {
1030 _recordMessage(node, StrongModeCode.DYNAMIC_INVOKE, [node]); 1016 _recordMessage(node, StrongModeCode.DYNAMIC_INVOKE, [node]);
1031 // TODO(jmesserly): we may eventually want to record if the whole operation 1017 // TODO(jmesserly): we may eventually want to record if the whole operation
1032 // (node) was dynamic, rather than the target, but this is an easier fit 1018 // (node) was dynamic, rather than the target, but this is an easier fit
1033 // with what we used to do. 1019 // with what we used to do.
1034 if (target != null) setIsDynamicInvoke(target, true); 1020 if (target != null) setIsDynamicInvoke(target, true);
1035 } 1021 }
1036 1022
1037 /// Records an implicit cast for the [expression] from [fromType] to [toType]. 1023 /// Records an implicit cast for the [expression] from [fromType] to [toType].
1038 /// 1024 ///
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 var visited = new Set<InterfaceType>(); 1476 var visited = new Set<InterfaceType>();
1491 do { 1477 do {
1492 visited.add(current); 1478 visited.add(current);
1493 current.mixins.reversed.forEach( 1479 current.mixins.reversed.forEach(
1494 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1480 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1495 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1481 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1496 current = current.superclass; 1482 current = current.superclass;
1497 } while (!current.isObject && !visited.contains(current)); 1483 } while (!current.isObject && !visited.contains(current));
1498 } 1484 }
1499 } 1485 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698