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 |