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

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') | no next file with comments »
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
560 // Mark the tear-off as being dynamic, too. This lets us distinguish
561 // cases like:
562 //
563 // dynamic d;
564 // d.someMethod(...); // the whole method call must be a dynamic send.
565 //
566 // ... from case like:
567 //
568 // SomeType s;
569 // s.someDynamicField(...); // static get, followed by dynamic call.
570 //
571 // The first case is handled here, the second case is handled below when
572 // we call [checkFunctionApplication].
573 DynamicInvoke.set(node.methodName, true);
574 } else {
575 checkFunctionApplication(node, node.methodName, node.argumentList);
576 }
557 node.visitChildren(this); 577 node.visitChildren(this);
558 } 578 }
559 579
560 @override 580 @override
561 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 581 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
562 checkFunctionApplication(node, node.function, node.argumentList); 582 checkFunctionApplication(node, node.function, node.argumentList);
563 node.visitChildren(this); 583 node.visitChildren(this);
564 } 584 }
565 585
566 @override 586 @override
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 } 635 }
616 636
617 @override 637 @override
618 void visitReturnStatement(ReturnStatement node) { 638 void visitReturnStatement(ReturnStatement node) {
619 _checkReturn(node.expression, node); 639 _checkReturn(node.expression, node);
620 node.visitChildren(this); 640 node.visitChildren(this);
621 } 641 }
622 642
623 @override 643 @override
624 void visitPropertyAccess(PropertyAccess node) { 644 void visitPropertyAccess(PropertyAccess node) {
625 if (node.staticType.isDynamic && _rules.isDynamicTarget(node.realTarget)) { 645 var target = node.realTarget;
626 _recordDynamicInvoke(node); 646 if (_rules.isDynamicTarget(target)) {
647 _recordDynamicInvoke(node, target);
627 } 648 }
628 node.visitChildren(this); 649 node.visitChildren(this);
629 } 650 }
630 651
631 @override 652 @override
632 void visitPrefixedIdentifier(PrefixedIdentifier node) { 653 void visitPrefixedIdentifier(PrefixedIdentifier node) {
633 final target = node.prefix; 654 final target = node.prefix;
634 if (_rules.isDynamicTarget(target)) { 655 if (_rules.isDynamicTarget(target)) {
635 _recordDynamicInvoke(node); 656 _recordDynamicInvoke(node, target);
636 } 657 }
637 node.visitChildren(this); 658 node.visitChildren(this);
638 } 659 }
639 660
640 @override 661 @override
641 void visitDefaultFormalParameter(DefaultFormalParameter node) { 662 void visitDefaultFormalParameter(DefaultFormalParameter node) {
642 _visitMaybeConst(node, (node) { 663 _visitMaybeConst(node, (node) {
643 // Check that defaults have the proper subtype. 664 // Check that defaults have the proper subtype.
644 var parameter = node.parameter; 665 var parameter = node.parameter;
645 var parameterType = _rules.elementType(parameter.element); 666 var parameterType = _rules.elementType(parameter.element);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 _checkUnary(node); 788 _checkUnary(node);
768 node.visitChildren(this); 789 node.visitChildren(this);
769 } 790 }
770 791
771 void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) { 792 void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
772 var op = node.operator; 793 var op = node.operator;
773 if (op.isUserDefinableOperator || 794 if (op.isUserDefinableOperator ||
774 op.type == TokenType.PLUS_PLUS || 795 op.type == TokenType.PLUS_PLUS ||
775 op.type == TokenType.MINUS_MINUS) { 796 op.type == TokenType.MINUS_MINUS) {
776 if (_rules.isDynamicTarget(node.operand)) { 797 if (_rules.isDynamicTarget(node.operand)) {
777 _recordDynamicInvoke(node); 798 _recordDynamicInvoke(node, node.operand);
778 } 799 }
779 // For ++ and --, even if it is not dynamic, we still need to check 800 // 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. 801 // that the user defined method accepts an `int` as the RHS.
781 // We assume Analyzer has done this already. 802 // We assume Analyzer has done this already.
782 } 803 }
783 } 804 }
784 805
785 @override 806 @override
786 void visitBinaryExpression(BinaryExpression node) { 807 void visitBinaryExpression(BinaryExpression node) {
787 var op = node.operator; 808 var op = node.operator;
788 if (op.isUserDefinableOperator) { 809 if (op.isUserDefinableOperator) {
789 if (_rules.isDynamicTarget(node.leftOperand)) { 810 if (_rules.isDynamicTarget(node.leftOperand)) {
790 // Dynamic invocation 811 // Dynamic invocation
791 // TODO(vsm): Move this logic to the resolver? 812 // TODO(vsm): Move this logic to the resolver?
792 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) { 813 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
793 _recordDynamicInvoke(node); 814 _recordDynamicInvoke(node, node.leftOperand);
794 } 815 }
795 } else { 816 } else {
796 var element = node.staticElement; 817 var element = node.staticElement;
797 // Method invocation. 818 // Method invocation.
798 if (element is MethodElement) { 819 if (element is MethodElement) {
799 var type = element.type as FunctionType; 820 var type = element.type as FunctionType;
800 // Analyzer should enforce number of parameter types, but check in 821 // Analyzer should enforce number of parameter types, but check in
801 // case we have erroneous input. 822 // case we have erroneous input.
802 if (type.normalParameterTypes.isNotEmpty) { 823 if (type.normalParameterTypes.isNotEmpty) {
803 checkArgument(node.rightOperand, type.normalParameterTypes[0]); 824 checkArgument(node.rightOperand, type.normalParameterTypes[0]);
(...skipping 20 matching lines...) Expand all
824 } 845 }
825 846
826 @override 847 @override
827 void visitConditionalExpression(ConditionalExpression node) { 848 void visitConditionalExpression(ConditionalExpression node) {
828 checkBoolean(node.condition); 849 checkBoolean(node.condition);
829 node.visitChildren(this); 850 node.visitChildren(this);
830 } 851 }
831 852
832 @override 853 @override
833 void visitIndexExpression(IndexExpression node) { 854 void visitIndexExpression(IndexExpression node) {
834 if (_rules.isDynamicTarget(node.target)) { 855 var target = node.realTarget;
835 _recordDynamicInvoke(node); 856 if (_rules.isDynamicTarget(target)) {
857 _recordDynamicInvoke(node, target);
836 } else { 858 } else {
837 var element = node.staticElement; 859 var element = node.staticElement;
838 if (element is MethodElement) { 860 if (element is MethodElement) {
839 var type = element.type as FunctionType; 861 var type = element.type as FunctionType;
840 // Analyzer should enforce number of parameter types, but check in 862 // Analyzer should enforce number of parameter types, but check in
841 // case we have erroneous input. 863 // case we have erroneous input.
842 if (type.normalParameterTypes.isNotEmpty) { 864 if (type.normalParameterTypes.isNotEmpty) {
843 checkArgument(node.index, type.normalParameterTypes[0]); 865 checkArgument(node.index, type.normalParameterTypes[0]);
844 } 866 }
845 } else { 867 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 912 }
891 return normalReturnType; 913 return normalReturnType;
892 } 914 }
893 915
894 void _checkCompoundAssignment(AssignmentExpression expr) { 916 void _checkCompoundAssignment(AssignmentExpression expr) {
895 var op = expr.operator.type; 917 var op = expr.operator.type;
896 assert(op.isAssignmentOperator && op != TokenType.EQ); 918 assert(op.isAssignmentOperator && op != TokenType.EQ);
897 var methodElement = expr.staticElement; 919 var methodElement = expr.staticElement;
898 if (methodElement == null) { 920 if (methodElement == null) {
899 // Dynamic invocation 921 // Dynamic invocation
900 _recordDynamicInvoke(expr); 922 _recordDynamicInvoke(expr, expr.leftHandSide);
901 } else { 923 } else {
902 // Sanity check the operator 924 // Sanity check the operator
903 assert(methodElement.isOperator); 925 assert(methodElement.isOperator);
904 var functionType = methodElement.type; 926 var functionType = methodElement.type;
905 var paramTypes = functionType.normalParameterTypes; 927 var paramTypes = functionType.normalParameterTypes;
906 assert(paramTypes.length == 1); 928 assert(paramTypes.length == 1);
907 assert(functionType.namedParameterTypes.isEmpty); 929 assert(functionType.namedParameterTypes.isEmpty);
908 assert(functionType.optionalParameterTypes.isEmpty); 930 assert(functionType.optionalParameterTypes.isEmpty);
909 931
910 // Check the lhs type 932 // Check the lhs type
(...skipping 23 matching lines...) Expand all
934 // Check the rhs type 956 // Check the rhs type
935 if (staticInfo is! CoercionInfo) { 957 if (staticInfo is! CoercionInfo) {
936 var paramType = paramTypes.first; 958 var paramType = paramTypes.first;
937 staticInfo = _rules.checkAssignment( 959 staticInfo = _rules.checkAssignment(
938 expr.rightHandSide, paramType, _constantContext); 960 expr.rightHandSide, paramType, _constantContext);
939 _recordMessage(staticInfo); 961 _recordMessage(staticInfo);
940 } 962 }
941 } 963 }
942 } 964 }
943 965
944 void _recordDynamicInvoke(AstNode node) { 966 void _recordDynamicInvoke(AstNode node, AstNode target) {
945 _reporter.log(new DynamicInvoke(_rules, node)); 967 var dinvoke = new DynamicInvoke(_rules, node);
968 _reporter.log(dinvoke);
969 // TODO(jmesserly): we may eventually want to record if the whole operation
970 // (node) was dynamic, rather than the target, but this is an easier fit
971 // with what we used to do.
972 DynamicInvoke.set(target, true);
946 } 973 }
947 974
948 void _recordMessage(StaticInfo info) { 975 void _recordMessage(StaticInfo info) {
949 if (info == null) return; 976 if (info == null) return;
950 if (info.level >= logger.Level.SEVERE) _failure = true; 977 if (info.level >= logger.Level.SEVERE) _failure = true;
951 _reporter.log(info); 978 _reporter.log(info);
952 if (info is CoercionInfo) { 979 if (info is CoercionInfo) {
953 assert(CoercionInfo.get(info.node) == null); 980 assert(CoercionInfo.get(info.node) == null);
954 CoercionInfo.set(info.node, info); 981 CoercionInfo.set(info.node, info);
955 } 982 }
956 } 983 }
957 } 984 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698