| OLD | NEW |
| 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; |
| 11 | 11 |
| 12 import '../../strong_mode.dart' show StrongModeOptions; | |
| 13 import '../info.dart'; | 12 import '../info.dart'; |
| 14 import '../utils.dart' show getMemberType; | 13 import '../utils.dart' show getMemberType; |
| 15 import 'rules.dart'; | 14 import 'rules.dart'; |
| 16 | 15 |
| 17 /// Checks for overriding declarations of fields and methods. This is used to | 16 /// Checks for overriding declarations of fields and methods. This is used to |
| 18 /// check overrides between classes and superclasses, interfaces, and mixin | 17 /// check overrides between classes and superclasses, interfaces, and mixin |
| 19 /// applications. | 18 /// applications. |
| 20 class _OverrideChecker { | 19 class _OverrideChecker { |
| 21 bool _failure = false; | 20 bool _failure = false; |
| 22 final TypeRules _rules; | 21 final TypeRules _rules; |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 node.visitChildren(this); | 619 node.visitChildren(this); |
| 621 } | 620 } |
| 622 | 621 |
| 623 @override | 622 @override |
| 624 void visitDefaultFormalParameter(DefaultFormalParameter node) { | 623 void visitDefaultFormalParameter(DefaultFormalParameter node) { |
| 625 // Check that defaults have the proper subtype. | 624 // Check that defaults have the proper subtype. |
| 626 var parameter = node.parameter; | 625 var parameter = node.parameter; |
| 627 var parameterType = rules.elementType(parameter.element); | 626 var parameterType = rules.elementType(parameter.element); |
| 628 assert(parameterType != null); | 627 assert(parameterType != null); |
| 629 var defaultValue = node.defaultValue; | 628 var defaultValue = node.defaultValue; |
| 630 if (defaultValue == null) { | 629 if (defaultValue != null) { |
| 631 if (rules.maybeNonNullableType(parameterType)) { | |
| 632 var staticInfo = new InvalidVariableDeclaration( | |
| 633 rules, node.identifier, parameterType); | |
| 634 _recordMessage(staticInfo); | |
| 635 } | |
| 636 } else { | |
| 637 checkAssignment(defaultValue, parameterType); | 630 checkAssignment(defaultValue, parameterType); |
| 638 } | 631 } |
| 639 | 632 |
| 640 node.visitChildren(this); | 633 node.visitChildren(this); |
| 641 } | 634 } |
| 642 | 635 |
| 643 @override | 636 @override |
| 644 void visitFieldFormalParameter(FieldFormalParameter node) { | 637 void visitFieldFormalParameter(FieldFormalParameter node) { |
| 645 var element = node.element; | 638 var element = node.element; |
| 646 var typeName = node.type; | 639 var typeName = node.type; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 677 if (type == null) { | 670 if (type == null) { |
| 678 // No checks are needed when the type is var. Although internally the | 671 // No checks are needed when the type is var. Although internally the |
| 679 // typing rules may have inferred a more precise type for the variable | 672 // typing rules may have inferred a more precise type for the variable |
| 680 // based on the initializer. | 673 // based on the initializer. |
| 681 } else { | 674 } else { |
| 682 var dartType = getType(type); | 675 var dartType = getType(type); |
| 683 for (VariableDeclaration variable in node.variables) { | 676 for (VariableDeclaration variable in node.variables) { |
| 684 var initializer = variable.initializer; | 677 var initializer = variable.initializer; |
| 685 if (initializer != null) { | 678 if (initializer != null) { |
| 686 checkAssignment(initializer, dartType); | 679 checkAssignment(initializer, dartType); |
| 687 } else if (rules.maybeNonNullableType(dartType)) { | |
| 688 var element = variable.element; | |
| 689 if (element is FieldElement && !element.isStatic) { | |
| 690 // Initialized - possibly implicitly - during construction. | |
| 691 // Handle this via a runtime check during code generation. | |
| 692 | |
| 693 // TODO(vsm): Detect statically whether this can fail and | |
| 694 // report a static error (must fail) or warning (can fail). | |
| 695 } else { | |
| 696 var staticInfo = | |
| 697 new InvalidVariableDeclaration(rules, variable, dartType); | |
| 698 _recordMessage(staticInfo); | |
| 699 } | |
| 700 } | 680 } |
| 701 } | 681 } |
| 702 } | 682 } |
| 703 node.visitChildren(this); | 683 node.visitChildren(this); |
| 704 } | 684 } |
| 705 | 685 |
| 706 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { | 686 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { |
| 707 var type = getType(typeName); | 687 var type = getType(typeName); |
| 708 if (!rules.isGroundType(type)) { | 688 if (!rules.isGroundType(type)) { |
| 709 _recordMessage(new NonGroundTypeCheckInfo(node, type)); | 689 _recordMessage(new NonGroundTypeCheckInfo(node, type)); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 case TokenType.PLUS: | 830 case TokenType.PLUS: |
| 851 case TokenType.MINUS: | 831 case TokenType.MINUS: |
| 852 case TokenType.STAR: | 832 case TokenType.STAR: |
| 853 case TokenType.TILDE_SLASH: | 833 case TokenType.TILDE_SLASH: |
| 854 case TokenType.PERCENT: | 834 case TokenType.PERCENT: |
| 855 case TokenType.PLUS_EQ: | 835 case TokenType.PLUS_EQ: |
| 856 case TokenType.MINUS_EQ: | 836 case TokenType.MINUS_EQ: |
| 857 case TokenType.STAR_EQ: | 837 case TokenType.STAR_EQ: |
| 858 case TokenType.TILDE_SLASH_EQ: | 838 case TokenType.TILDE_SLASH_EQ: |
| 859 case TokenType.PERCENT_EQ: | 839 case TokenType.PERCENT_EQ: |
| 860 if (t1 == rules.provider.intType && t2 == rules.provider.intType) return
t1; | 840 if (t1 == rules.provider.intType && |
| 861 if (t1 == rules.provider.doubleType && t2 == rules.provider.doubleType)
return t1; | 841 t2 == rules.provider.intType) return t1; |
| 842 if (t1 == rules.provider.doubleType && |
| 843 t2 == rules.provider.doubleType) return t1; |
| 862 // This particular combo is not spelled out in the spec, but all | 844 // This particular combo is not spelled out in the spec, but all |
| 863 // implementations and analyzer seem to follow this. | 845 // implementations and analyzer seem to follow this. |
| 864 if (t1 == rules.provider.doubleType && t2 == rules.provider.intType) ret
urn t1; | 846 if (t1 == rules.provider.doubleType && |
| 847 t2 == rules.provider.intType) return t1; |
| 865 } | 848 } |
| 866 return normalReturnType; | 849 return normalReturnType; |
| 867 } | 850 } |
| 868 | 851 |
| 869 void _checkCompoundAssignment(AssignmentExpression expr) { | 852 void _checkCompoundAssignment(AssignmentExpression expr) { |
| 870 var op = expr.operator.type; | 853 var op = expr.operator.type; |
| 871 assert(op.isAssignmentOperator && op != TokenType.EQ); | 854 assert(op.isAssignmentOperator && op != TokenType.EQ); |
| 872 var methodElement = expr.staticElement; | 855 var methodElement = expr.staticElement; |
| 873 if (methodElement == null) { | 856 if (methodElement == null) { |
| 874 // Dynamic invocation | 857 // Dynamic invocation |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 if (info is CoercionInfo) { | 931 if (info is CoercionInfo) { |
| 949 // TODO(jmesserly): if we're run again on the same AST, we'll produce the | 932 // TODO(jmesserly): if we're run again on the same AST, we'll produce the |
| 950 // same annotations. This should be harmless. This might go away once | 933 // same annotations. This should be harmless. This might go away once |
| 951 // CodeChecker is integrated better with analyzer, as it will know that | 934 // CodeChecker is integrated better with analyzer, as it will know that |
| 952 // checking has already been performed. | 935 // checking has already been performed. |
| 953 // assert(CoercionInfo.get(info.node) == null); | 936 // assert(CoercionInfo.get(info.node) == null); |
| 954 CoercionInfo.set(info.node, info); | 937 CoercionInfo.set(info.node, info); |
| 955 } | 938 } |
| 956 } | 939 } |
| 957 } | 940 } |
| OLD | NEW |