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

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

Issue 1184843002: fixes #192, encode dynamic info in checker (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « no previous file | lib/src/codegen/js_codegen.dart » ('j') | lib/src/codegen/js_codegen.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 library dev_compiler.src.checker.checker; 5 library dev_compiler.src.checker.checker;
6 6
7 import 'package:analyzer/analyzer.dart'; 7 import 'package:analyzer/analyzer.dart';
8 import 'package:analyzer/src/generated/ast.dart'; 8 import 'package:analyzer/src/generated/ast.dart';
9 import 'package:analyzer/src/generated/element.dart'; 9 import 'package:analyzer/src/generated/element.dart';
10 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType; 10 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 arg = (arg as NamedExpression).expression; 538 arg = (arg as NamedExpression).expression;
539 } 539 }
540 checkAssignment(arg, expectedType); 540 checkAssignment(arg, expectedType);
541 } 541 }
542 542
543 void checkFunctionApplication( 543 void checkFunctionApplication(
544 Expression node, Expression f, ArgumentList list) { 544 Expression node, Expression f, ArgumentList list) {
545 if (_rules.isDynamicCall(f)) { 545 if (_rules.isDynamicCall(f)) {
546 // If f is Function and this is a method invocation, we should have 546 // If f is Function and this is a method invocation, we should have
547 // gotten an analyzer error, so no need to issue another error. 547 // gotten an analyzer error, so no need to issue another error.
548 _recordDynamicInvoke(node); 548 _recordDynamicInvoke(node, f);
549 } else { 549 } else {
550 checkArgumentList(list, _rules.getTypeAsCaller(f)); 550 checkArgumentList(list, _rules.getTypeAsCaller(f));
551 } 551 }
552 } 552 }
553 553
554 @override 554 @override
555 void visitMethodInvocation(MethodInvocation node) { 555 visitMethodInvocation(MethodInvocation node) {
556 checkFunctionApplication(node, node.methodName, node.argumentList); 556 var target = node.realTarget;
557 if (_rules.isDynamicTarget(target)) {
558 _recordDynamicInvoke(node, target);
559 // Mark the call as being dynamic as well.
560 DynamicInvoke.set(node.methodName, true);
Jennifer Messerly 2015/06/12 18:18:09 we are interesting both in whether the method call
Leaf 2015/06/12 20:13:23 This is a little obscure, maybe worth a bit more e
Jennifer Messerly 2015/06/12 20:22:28 sure. will add. For your info, what happens is we
561 } else {
562 checkFunctionApplication(node, node.methodName, node.argumentList);
563 }
557 node.visitChildren(this); 564 node.visitChildren(this);
558 } 565 }
559 566
560 @override 567 @override
561 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 568 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
562 checkFunctionApplication(node, node.function, node.argumentList); 569 checkFunctionApplication(node, node.function, node.argumentList);
563 node.visitChildren(this); 570 node.visitChildren(this);
564 } 571 }
565 572
566 @override 573 @override
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 } 622 }
616 623
617 @override 624 @override
618 void visitReturnStatement(ReturnStatement node) { 625 void visitReturnStatement(ReturnStatement node) {
619 _checkReturn(node.expression, node); 626 _checkReturn(node.expression, node);
620 node.visitChildren(this); 627 node.visitChildren(this);
621 } 628 }
622 629
623 @override 630 @override
624 void visitPropertyAccess(PropertyAccess node) { 631 void visitPropertyAccess(PropertyAccess node) {
625 if (node.staticType.isDynamic && _rules.isDynamicTarget(node.realTarget)) { 632 var target = node.realTarget;
Jennifer Messerly 2015/06/12 18:18:09 bug fix: cascade dinvoke not reported
626 _recordDynamicInvoke(node); 633 if (_rules.isDynamicTarget(target)) {
634 _recordDynamicInvoke(node, target);
627 } 635 }
628 node.visitChildren(this); 636 node.visitChildren(this);
629 } 637 }
630 638
631 @override 639 @override
632 void visitPrefixedIdentifier(PrefixedIdentifier node) { 640 void visitPrefixedIdentifier(PrefixedIdentifier node) {
633 final target = node.prefix; 641 final target = node.prefix;
634 if (_rules.isDynamicTarget(target)) { 642 if (_rules.isDynamicTarget(target)) {
635 _recordDynamicInvoke(node); 643 _recordDynamicInvoke(node, target);
636 } 644 }
637 node.visitChildren(this); 645 node.visitChildren(this);
638 } 646 }
639 647
640 @override 648 @override
641 void visitDefaultFormalParameter(DefaultFormalParameter node) { 649 void visitDefaultFormalParameter(DefaultFormalParameter node) {
642 _visitMaybeConst(node, (node) { 650 _visitMaybeConst(node, (node) {
643 // Check that defaults have the proper subtype. 651 // Check that defaults have the proper subtype.
644 var parameter = node.parameter; 652 var parameter = node.parameter;
645 var parameterType = _rules.elementType(parameter.element); 653 var parameterType = _rules.elementType(parameter.element);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 _checkUnary(node); 775 _checkUnary(node);
768 node.visitChildren(this); 776 node.visitChildren(this);
769 } 777 }
770 778
771 void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) { 779 void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
772 var op = node.operator; 780 var op = node.operator;
773 if (op.isUserDefinableOperator || 781 if (op.isUserDefinableOperator ||
774 op.type == TokenType.PLUS_PLUS || 782 op.type == TokenType.PLUS_PLUS ||
775 op.type == TokenType.MINUS_MINUS) { 783 op.type == TokenType.MINUS_MINUS) {
776 if (_rules.isDynamicTarget(node.operand)) { 784 if (_rules.isDynamicTarget(node.operand)) {
777 _recordDynamicInvoke(node); 785 _recordDynamicInvoke(node, node.operand);
778 } 786 }
779 // For ++ and --, even if it is not dynamic, we still need to check 787 // For ++ and --, even if it is not dynamic, we still need to check
780 // that the user defined method accepts an `int` as the RHS. 788 // that the user defined method accepts an `int` as the RHS.
781 // We assume Analyzer has done this already. 789 // We assume Analyzer has done this already.
782 } 790 }
783 } 791 }
784 792
785 @override 793 @override
786 void visitBinaryExpression(BinaryExpression node) { 794 void visitBinaryExpression(BinaryExpression node) {
787 var op = node.operator; 795 var op = node.operator;
788 if (op.isUserDefinableOperator) { 796 if (op.isUserDefinableOperator) {
789 if (_rules.isDynamicTarget(node.leftOperand)) { 797 if (_rules.isDynamicTarget(node.leftOperand)) {
790 // Dynamic invocation 798 // Dynamic invocation
791 // TODO(vsm): Move this logic to the resolver? 799 // TODO(vsm): Move this logic to the resolver?
792 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) { 800 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
793 _recordDynamicInvoke(node); 801 _recordDynamicInvoke(node, node.leftOperand);
794 } 802 }
795 } else { 803 } else {
796 var element = node.staticElement; 804 var element = node.staticElement;
797 // Method invocation. 805 // Method invocation.
798 if (element is MethodElement) { 806 if (element is MethodElement) {
799 var type = element.type as FunctionType; 807 var type = element.type as FunctionType;
800 // Analyzer should enforce number of parameter types, but check in 808 // Analyzer should enforce number of parameter types, but check in
801 // case we have erroneous input. 809 // case we have erroneous input.
802 if (type.normalParameterTypes.isNotEmpty) { 810 if (type.normalParameterTypes.isNotEmpty) {
803 checkArgument(node.rightOperand, type.normalParameterTypes[0]); 811 checkArgument(node.rightOperand, type.normalParameterTypes[0]);
(...skipping 20 matching lines...) Expand all
824 } 832 }
825 833
826 @override 834 @override
827 void visitConditionalExpression(ConditionalExpression node) { 835 void visitConditionalExpression(ConditionalExpression node) {
828 checkBoolean(node.condition); 836 checkBoolean(node.condition);
829 node.visitChildren(this); 837 node.visitChildren(this);
830 } 838 }
831 839
832 @override 840 @override
833 void visitIndexExpression(IndexExpression node) { 841 void visitIndexExpression(IndexExpression node) {
834 if (_rules.isDynamicTarget(node.target)) { 842 var target = node.realTarget;
Jennifer Messerly 2015/06/12 18:18:09 bug fix: cascade dinvoke not reported
835 _recordDynamicInvoke(node); 843 if (_rules.isDynamicTarget(target)) {
844 _recordDynamicInvoke(node, target);
836 } else { 845 } else {
837 var element = node.staticElement; 846 var element = node.staticElement;
838 if (element is MethodElement) { 847 if (element is MethodElement) {
839 var type = element.type as FunctionType; 848 var type = element.type as FunctionType;
840 // Analyzer should enforce number of parameter types, but check in 849 // Analyzer should enforce number of parameter types, but check in
841 // case we have erroneous input. 850 // case we have erroneous input.
842 if (type.normalParameterTypes.isNotEmpty) { 851 if (type.normalParameterTypes.isNotEmpty) {
843 checkArgument(node.index, type.normalParameterTypes[0]); 852 checkArgument(node.index, type.normalParameterTypes[0]);
844 } 853 }
845 } else { 854 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 899 }
891 return normalReturnType; 900 return normalReturnType;
892 } 901 }
893 902
894 void _checkCompoundAssignment(AssignmentExpression expr) { 903 void _checkCompoundAssignment(AssignmentExpression expr) {
895 var op = expr.operator.type; 904 var op = expr.operator.type;
896 assert(op.isAssignmentOperator && op != TokenType.EQ); 905 assert(op.isAssignmentOperator && op != TokenType.EQ);
897 var methodElement = expr.staticElement; 906 var methodElement = expr.staticElement;
898 if (methodElement == null) { 907 if (methodElement == null) {
899 // Dynamic invocation 908 // Dynamic invocation
900 _recordDynamicInvoke(expr); 909 _recordDynamicInvoke(expr, expr.leftHandSide);
901 } else { 910 } else {
902 // Sanity check the operator 911 // Sanity check the operator
903 assert(methodElement.isOperator); 912 assert(methodElement.isOperator);
904 var functionType = methodElement.type; 913 var functionType = methodElement.type;
905 var paramTypes = functionType.normalParameterTypes; 914 var paramTypes = functionType.normalParameterTypes;
906 assert(paramTypes.length == 1); 915 assert(paramTypes.length == 1);
907 assert(functionType.namedParameterTypes.isEmpty); 916 assert(functionType.namedParameterTypes.isEmpty);
908 assert(functionType.optionalParameterTypes.isEmpty); 917 assert(functionType.optionalParameterTypes.isEmpty);
909 918
910 // Check the lhs type 919 // Check the lhs type
(...skipping 23 matching lines...) Expand all
934 // Check the rhs type 943 // Check the rhs type
935 if (staticInfo is! CoercionInfo) { 944 if (staticInfo is! CoercionInfo) {
936 var paramType = paramTypes.first; 945 var paramType = paramTypes.first;
937 staticInfo = _rules.checkAssignment( 946 staticInfo = _rules.checkAssignment(
938 expr.rightHandSide, paramType, _constantContext); 947 expr.rightHandSide, paramType, _constantContext);
939 _recordMessage(staticInfo); 948 _recordMessage(staticInfo);
940 } 949 }
941 } 950 }
942 } 951 }
943 952
944 void _recordDynamicInvoke(AstNode node) { 953 void _recordDynamicInvoke(AstNode node, AstNode target) {
945 _reporter.log(new DynamicInvoke(_rules, node)); 954 var dinvoke = new DynamicInvoke(_rules, node);
955 _reporter.log(dinvoke);
956 // TODO(jmesserly): we may eventually want to record if the whole operation
957 // (node) was dynamic, rather than the target, but this is an easier fit
958 // with what we used to do.
959 DynamicInvoke.set(target, true);
946 } 960 }
947 961
948 void _recordMessage(StaticInfo info) { 962 void _recordMessage(StaticInfo info) {
949 if (info == null) return; 963 if (info == null) return;
950 if (info.level >= logger.Level.SEVERE) _failure = true; 964 if (info.level >= logger.Level.SEVERE) _failure = true;
951 _reporter.log(info); 965 _reporter.log(info);
952 if (info is CoercionInfo) { 966 if (info is CoercionInfo) {
953 assert(CoercionInfo.get(info.node) == null); 967 assert(CoercionInfo.get(info.node) == null);
954 CoercionInfo.set(info.node, info); 968 CoercionInfo.set(info.node, info);
955 } 969 }
956 } 970 }
957 } 971 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/codegen/js_codegen.dart » ('j') | lib/src/codegen/js_codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698