| 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; |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 _failure = false; | 333 _failure = false; |
| 334 _overrideChecker._failure = false; | 334 _overrideChecker._failure = false; |
| 335 } | 335 } |
| 336 | 336 |
| 337 CodeChecker(TypeRules rules, AnalysisErrorListener reporter) | 337 CodeChecker(TypeRules rules, AnalysisErrorListener reporter) |
| 338 : rules = rules, | 338 : rules = rules, |
| 339 reporter = reporter, | 339 reporter = reporter, |
| 340 _overrideChecker = new _OverrideChecker(rules, reporter); | 340 _overrideChecker = new _OverrideChecker(rules, reporter); |
| 341 | 341 |
| 342 @override | 342 @override |
| 343 void visitCompilationUnit(CompilationUnit unit) { | |
| 344 void report(Expression expr) { | |
| 345 reporter.onError(new MissingTypeError(expr).toAnalysisError()); | |
| 346 } | |
| 347 var callback = rules.reportMissingType; | |
| 348 rules.reportMissingType = report; | |
| 349 unit.visitChildren(this); | |
| 350 rules.reportMissingType = callback; | |
| 351 } | |
| 352 | |
| 353 @override | |
| 354 void visitComment(Comment node) { | 343 void visitComment(Comment node) { |
| 355 // skip, no need to do typechecking inside comments (they may contain | 344 // skip, no need to do typechecking inside comments (they may contain |
| 356 // comment references which would require resolution). | 345 // comment references which would require resolution). |
| 357 } | 346 } |
| 358 | 347 |
| 359 @override | 348 @override |
| 360 void visitClassDeclaration(ClassDeclaration node) { | 349 void visitClassDeclaration(ClassDeclaration node) { |
| 361 _overrideChecker.check(node); | 350 _overrideChecker.check(node); |
| 362 super.visitClassDeclaration(node); | 351 super.visitClassDeclaration(node); |
| 363 } | 352 } |
| 364 | 353 |
| 365 @override | 354 @override |
| 366 void visitAssignmentExpression(AssignmentExpression node) { | 355 void visitAssignmentExpression(AssignmentExpression node) { |
| 367 var token = node.operator; | 356 var token = node.operator; |
| 368 if (token.type != TokenType.EQ) { | 357 if (token.type != TokenType.EQ) { |
| 369 _checkCompoundAssignment(node); | 358 _checkCompoundAssignment(node); |
| 370 } else { | 359 } else { |
| 371 DartType staticType = rules.getStaticType(node.leftHandSide); | 360 DartType staticType = _getStaticType(node.leftHandSide); |
| 372 checkAssignment(node.rightHandSide, staticType); | 361 checkAssignment(node.rightHandSide, staticType); |
| 373 } | 362 } |
| 374 node.visitChildren(this); | 363 node.visitChildren(this); |
| 375 } | 364 } |
| 376 | 365 |
| 377 /// Check constructor declaration to ensure correct super call placement. | 366 /// Check constructor declaration to ensure correct super call placement. |
| 378 @override | 367 @override |
| 379 void visitConstructorDeclaration(ConstructorDeclaration node) { | 368 void visitConstructorDeclaration(ConstructorDeclaration node) { |
| 380 node.visitChildren(this); | 369 node.visitChildren(this); |
| 381 | 370 |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 // Sanity check the operator | 876 // Sanity check the operator |
| 888 assert(methodElement.isOperator); | 877 assert(methodElement.isOperator); |
| 889 var functionType = methodElement.type; | 878 var functionType = methodElement.type; |
| 890 var paramTypes = functionType.normalParameterTypes; | 879 var paramTypes = functionType.normalParameterTypes; |
| 891 assert(paramTypes.length == 1); | 880 assert(paramTypes.length == 1); |
| 892 assert(functionType.namedParameterTypes.isEmpty); | 881 assert(functionType.namedParameterTypes.isEmpty); |
| 893 assert(functionType.optionalParameterTypes.isEmpty); | 882 assert(functionType.optionalParameterTypes.isEmpty); |
| 894 | 883 |
| 895 // Check the lhs type | 884 // Check the lhs type |
| 896 var staticInfo; | 885 var staticInfo; |
| 897 var rhsType = rules.getStaticType(expr.rightHandSide); | 886 var rhsType = _getStaticType(expr.rightHandSide); |
| 898 var lhsType = rules.getStaticType(expr.leftHandSide); | 887 var lhsType = _getStaticType(expr.leftHandSide); |
| 899 var returnType = _specializedBinaryReturnType( | 888 var returnType = _specializedBinaryReturnType( |
| 900 op, lhsType, rhsType, functionType.returnType); | 889 op, lhsType, rhsType, functionType.returnType); |
| 901 | 890 |
| 902 if (!rules.isSubTypeOf(returnType, lhsType)) { | 891 if (!rules.isSubTypeOf(returnType, lhsType)) { |
| 903 final numType = rules.provider.numType; | 892 final numType = rules.provider.numType; |
| 904 // Try to fix up the numerical case if possible. | 893 // Try to fix up the numerical case if possible. |
| 905 if (rules.isSubTypeOf(lhsType, numType) && | 894 if (rules.isSubTypeOf(lhsType, numType) && |
| 906 rules.isSubTypeOf(lhsType, rhsType)) { | 895 rules.isSubTypeOf(lhsType, rhsType)) { |
| 907 // This is also slightly different from spec, but allows us to keep | 896 // This is also slightly different from spec, but allows us to keep |
| 908 // compound operators in the int += num and num += dynamic cases. | 897 // compound operators in the int += num and num += dynamic cases. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 934 bool _isObjectMethod(Expression target, SimpleIdentifier id) { | 923 bool _isObjectMethod(Expression target, SimpleIdentifier id) { |
| 935 MethodElement element = | 924 MethodElement element = |
| 936 rules.provider.objectType.element.getMethod(id.name); | 925 rules.provider.objectType.element.getMethod(id.name); |
| 937 return (element != null && !element.isStatic); | 926 return (element != null && !element.isStatic); |
| 938 } | 927 } |
| 939 | 928 |
| 940 bool _isObjectProperty(Expression target, SimpleIdentifier id) { | 929 bool _isObjectProperty(Expression target, SimpleIdentifier id) { |
| 941 return _isObjectGetter(target, id) || _isObjectMethod(target, id); | 930 return _isObjectGetter(target, id) || _isObjectMethod(target, id); |
| 942 } | 931 } |
| 943 | 932 |
| 933 DartType _getStaticType(Expression expr) { |
| 934 var type = expr.staticType; |
| 935 if (type == null) { |
| 936 reporter.onError(new MissingTypeError(expr).toAnalysisError()); |
| 937 } |
| 938 return type ?? rules.provider.dynamicType; |
| 939 } |
| 940 |
| 944 void _recordDynamicInvoke(AstNode node, AstNode target) { | 941 void _recordDynamicInvoke(AstNode node, AstNode target) { |
| 945 reporter.onError(new DynamicInvoke(rules, node).toAnalysisError()); | 942 reporter.onError(new DynamicInvoke(rules, node).toAnalysisError()); |
| 946 // TODO(jmesserly): we may eventually want to record if the whole operation | 943 // TODO(jmesserly): we may eventually want to record if the whole operation |
| 947 // (node) was dynamic, rather than the target, but this is an easier fit | 944 // (node) was dynamic, rather than the target, but this is an easier fit |
| 948 // with what we used to do. | 945 // with what we used to do. |
| 949 DynamicInvoke.set(target, true); | 946 DynamicInvoke.set(target, true); |
| 950 } | 947 } |
| 951 | 948 |
| 952 void _recordMessage(StaticInfo info) { | 949 void _recordMessage(StaticInfo info) { |
| 953 if (info == null) return; | 950 if (info == null) return; |
| 954 var error = info.toAnalysisError(); | 951 var error = info.toAnalysisError(); |
| 955 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; | 952 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; |
| 956 reporter.onError(error); | 953 reporter.onError(error); |
| 957 | 954 |
| 958 if (info is CoercionInfo) { | 955 if (info is CoercionInfo) { |
| 959 // TODO(jmesserly): if we're run again on the same AST, we'll produce the | 956 // TODO(jmesserly): if we're run again on the same AST, we'll produce the |
| 960 // same annotations. This should be harmless. This might go away once | 957 // same annotations. This should be harmless. This might go away once |
| 961 // CodeChecker is integrated better with analyzer, as it will know that | 958 // CodeChecker is integrated better with analyzer, as it will know that |
| 962 // checking has already been performed. | 959 // checking has already been performed. |
| 963 // assert(CoercionInfo.get(info.node) == null); | 960 // assert(CoercionInfo.get(info.node) == null); |
| 964 CoercionInfo.set(info.node, info); | 961 CoercionInfo.set(info.node, info); |
| 965 } | 962 } |
| 966 } | 963 } |
| 967 } | 964 } |
| OLD | NEW |