| 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 : rules = rules, | 110 : rules = rules, |
| 111 reporter = reporter, | 111 reporter = reporter, |
| 112 _hints = hints, | 112 _hints = hints, |
| 113 _overrideChecker = new _OverrideChecker(rules, reporter); | 113 _overrideChecker = new _OverrideChecker(rules, reporter); |
| 114 | 114 |
| 115 bool get failure => _failure || _overrideChecker._failure; | 115 bool get failure => _failure || _overrideChecker._failure; |
| 116 | 116 |
| 117 void checkArgument(Expression arg, DartType expectedType) { | 117 void checkArgument(Expression arg, DartType expectedType) { |
| 118 // Preserve named argument structure, so their immediate parent is the | 118 // Preserve named argument structure, so their immediate parent is the |
| 119 // method invocation. | 119 // method invocation. |
| 120 if (arg is NamedExpression) { | 120 Expression baseExpression = arg is NamedExpression ? arg.expression : arg; |
| 121 arg = (arg as NamedExpression).expression; | 121 checkAssignment(baseExpression, expectedType); |
| 122 } | |
| 123 checkAssignment(arg, expectedType); | |
| 124 } | 122 } |
| 125 | 123 |
| 126 void checkArgumentList(ArgumentList node, FunctionType type) { | 124 void checkArgumentList(ArgumentList node, FunctionType type) { |
| 127 NodeList<Expression> list = node.arguments; | 125 NodeList<Expression> list = node.arguments; |
| 128 int len = list.length; | 126 int len = list.length; |
| 129 for (int i = 0; i < len; ++i) { | 127 for (int i = 0; i < len; ++i) { |
| 130 Expression arg = list[i]; | 128 Expression arg = list[i]; |
| 131 ParameterElement element = arg.staticParameterElement; | 129 ParameterElement element = arg.staticParameterElement; |
| 132 if (element == null) { | 130 if (element == null) { |
| 133 // We found an argument mismatch, the analyzer will report this too, | 131 // We found an argument mismatch, the analyzer will report this too, |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 } | 418 } |
| 421 | 419 |
| 422 @override | 420 @override |
| 423 void visitIsExpression(IsExpression node) { | 421 void visitIsExpression(IsExpression node) { |
| 424 _checkRuntimeTypeCheck(node, node.type); | 422 _checkRuntimeTypeCheck(node, node.type); |
| 425 node.visitChildren(this); | 423 node.visitChildren(this); |
| 426 } | 424 } |
| 427 | 425 |
| 428 @override | 426 @override |
| 429 void visitListLiteral(ListLiteral node) { | 427 void visitListLiteral(ListLiteral node) { |
| 430 var type = DynamicTypeImpl.instance; | 428 DartType type = DynamicTypeImpl.instance; |
| 431 if (node.typeArguments != null) { | 429 if (node.typeArguments != null) { |
| 432 var targs = node.typeArguments.arguments; | 430 NodeList<TypeName> targs = node.typeArguments.arguments; |
| 433 if (targs.length > 0) type = targs[0].type; | 431 if (targs.length > 0) { |
| 434 } else if (node.staticType is InterfaceType) { | 432 type = targs[0].type; |
| 435 InterfaceType listT = node.staticType; | 433 } |
| 436 var targs = listT.typeArguments; | 434 } else { |
| 437 if (targs != null && targs.length > 0) type = targs[0]; | 435 DartType staticType = node.staticType; |
| 436 if (staticType is InterfaceType) { |
| 437 List<DartType> targs = staticType.typeArguments; |
| 438 if (targs != null && targs.length > 0) { |
| 439 type = targs[0]; |
| 440 } |
| 441 } |
| 438 } | 442 } |
| 439 var elements = node.elements; | 443 NodeList<Expression> elements = node.elements; |
| 440 for (int i = 0; i < elements.length; i++) { | 444 for (int i = 0; i < elements.length; i++) { |
| 441 checkArgument(elements[i], type); | 445 checkArgument(elements[i], type); |
| 442 } | 446 } |
| 443 super.visitListLiteral(node); | 447 super.visitListLiteral(node); |
| 444 } | 448 } |
| 445 | 449 |
| 446 @override | 450 @override |
| 447 void visitMapLiteral(MapLiteral node) { | 451 void visitMapLiteral(MapLiteral node) { |
| 448 var ktype = DynamicTypeImpl.instance; | 452 DartType ktype = DynamicTypeImpl.instance; |
| 449 var vtype = DynamicTypeImpl.instance; | 453 DartType vtype = DynamicTypeImpl.instance; |
| 450 if (node.typeArguments != null) { | 454 if (node.typeArguments != null) { |
| 451 var targs = node.typeArguments.arguments; | 455 NodeList<TypeName> targs = node.typeArguments.arguments; |
| 452 if (targs.length > 0) ktype = targs[0].type; | 456 if (targs.length > 0) { |
| 453 if (targs.length > 1) vtype = targs[1].type; | 457 ktype = targs[0].type; |
| 454 } else if (node.staticType is InterfaceType) { | 458 } |
| 455 InterfaceType mapT = node.staticType; | 459 if (targs.length > 1) { |
| 456 var targs = mapT.typeArguments; | 460 vtype = targs[1].type; |
| 457 if (targs != null) { | 461 } |
| 458 if (targs.length > 0) ktype = targs[0]; | 462 } else { |
| 459 if (targs.length > 1) vtype = targs[1]; | 463 DartType staticType = node.staticType; |
| 464 if (staticType is InterfaceType) { |
| 465 List<DartType> targs = staticType.typeArguments; |
| 466 if (targs != null) { |
| 467 if (targs.length > 0) { |
| 468 ktype = targs[0]; |
| 469 } |
| 470 if (targs.length > 1) { |
| 471 vtype = targs[1]; |
| 472 } |
| 473 } |
| 460 } | 474 } |
| 461 } | 475 } |
| 462 var entries = node.entries; | 476 NodeList<MapLiteralEntry> entries = node.entries; |
| 463 for (int i = 0; i < entries.length; i++) { | 477 for (int i = 0; i < entries.length; i++) { |
| 464 var entry = entries[i]; | 478 MapLiteralEntry entry = entries[i]; |
| 465 checkArgument(entry.key, ktype); | 479 checkArgument(entry.key, ktype); |
| 466 checkArgument(entry.value, vtype); | 480 checkArgument(entry.value, vtype); |
| 467 } | 481 } |
| 468 super.visitMapLiteral(node); | 482 super.visitMapLiteral(node); |
| 469 } | 483 } |
| 470 | 484 |
| 471 @override | 485 @override |
| 472 visitMethodInvocation(MethodInvocation node) { | 486 visitMethodInvocation(MethodInvocation node) { |
| 473 var target = node.realTarget; | 487 var target = node.realTarget; |
| 474 if (_isDynamicTarget(target) && !_isObjectMethod(node, node.methodName)) { | 488 if (_isDynamicTarget(target) && !_isObjectMethod(node, node.methodName)) { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 DartType t = node.staticType; | 827 DartType t = node.staticType; |
| 814 if (node is SimpleIdentifier) { | 828 if (node is SimpleIdentifier) { |
| 815 Expression parent = node.parent; | 829 Expression parent = node.parent; |
| 816 if (parent is MethodInvocation) { | 830 if (parent is MethodInvocation) { |
| 817 t = parent.staticInvokeType; | 831 t = parent.staticInvokeType; |
| 818 } | 832 } |
| 819 } | 833 } |
| 820 if (t is InterfaceType) { | 834 if (t is InterfaceType) { |
| 821 return rules.getCallMethodType(t); | 835 return rules.getCallMethodType(t); |
| 822 } | 836 } |
| 823 if (t is FunctionType) return t; | 837 if (t is FunctionType) { |
| 838 return t; |
| 839 } |
| 824 return null; | 840 return null; |
| 825 } | 841 } |
| 826 | 842 |
| 827 /// Returns `true` if the expression is a dynamic function call or method | 843 /// Returns `true` if the expression is a dynamic function call or method |
| 828 /// invocation. | 844 /// invocation. |
| 829 bool _isDynamicCall(Expression call) { | 845 bool _isDynamicCall(Expression call) { |
| 830 var ft = _getTypeAsCaller(call); | 846 var ft = _getTypeAsCaller(call); |
| 831 // TODO(leafp): This will currently return true if t is Function | 847 // TODO(leafp): This will currently return true if t is Function |
| 832 // This is probably the most correct thing to do for now, since | 848 // This is probably the most correct thing to do for now, since |
| 833 // this code is also used by the back end. Maybe revisit at some | 849 // this code is also used by the back end. Maybe revisit at some |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 | 1020 |
| 1005 /// Check that individual methods and fields in [subType] correctly override | 1021 /// Check that individual methods and fields in [subType] correctly override |
| 1006 /// the declarations in [baseType]. | 1022 /// the declarations in [baseType]. |
| 1007 /// | 1023 /// |
| 1008 /// The [errorLocation] node indicates where errors are reported, see | 1024 /// The [errorLocation] node indicates where errors are reported, see |
| 1009 /// [_checkSingleOverride] for more details. | 1025 /// [_checkSingleOverride] for more details. |
| 1010 _checkIndividualOverridesFromClass(ClassDeclaration node, | 1026 _checkIndividualOverridesFromClass(ClassDeclaration node, |
| 1011 InterfaceType baseType, Set<String> seen, bool isSubclass) { | 1027 InterfaceType baseType, Set<String> seen, bool isSubclass) { |
| 1012 for (var member in node.members) { | 1028 for (var member in node.members) { |
| 1013 if (member is FieldDeclaration) { | 1029 if (member is FieldDeclaration) { |
| 1014 if (member.isStatic) continue; | 1030 if (member.isStatic) { |
| 1031 continue; |
| 1032 } |
| 1015 for (var variable in member.fields.variables) { | 1033 for (var variable in member.fields.variables) { |
| 1016 var element = variable.element as PropertyInducingElement; | 1034 var element = variable.element as PropertyInducingElement; |
| 1017 var name = element.name; | 1035 var name = element.name; |
| 1018 if (seen.contains(name)) continue; | 1036 if (seen.contains(name)) { |
| 1037 continue; |
| 1038 } |
| 1019 var getter = element.getter; | 1039 var getter = element.getter; |
| 1020 var setter = element.setter; | 1040 var setter = element.setter; |
| 1021 bool found = _checkSingleOverride( | 1041 bool found = _checkSingleOverride( |
| 1022 getter, baseType, variable.name, member, isSubclass); | 1042 getter, baseType, variable.name, member, isSubclass); |
| 1023 if (!variable.isFinal && | 1043 if (!variable.isFinal && |
| 1024 !variable.isConst && | 1044 !variable.isConst && |
| 1025 _checkSingleOverride( | 1045 _checkSingleOverride( |
| 1026 setter, baseType, variable.name, member, isSubclass)) { | 1046 setter, baseType, variable.name, member, isSubclass)) { |
| 1027 found = true; | 1047 found = true; |
| 1028 } | 1048 } |
| 1029 if (found) seen.add(name); | 1049 if (found) { |
| 1050 seen.add(name); |
| 1051 } |
| 1030 } | 1052 } |
| 1031 } else if (member is MethodDeclaration) { | 1053 } else if (member is MethodDeclaration) { |
| 1032 if (member.isStatic) continue; | 1054 if (member.isStatic) { |
| 1055 continue; |
| 1056 } |
| 1033 var method = member.element; | 1057 var method = member.element; |
| 1034 if (seen.contains(method.name)) continue; | 1058 if (seen.contains(method.name)) { |
| 1059 continue; |
| 1060 } |
| 1035 if (_checkSingleOverride( | 1061 if (_checkSingleOverride( |
| 1036 method, baseType, member.name, member, isSubclass)) { | 1062 method, baseType, member.name, member, isSubclass)) { |
| 1037 seen.add(method.name); | 1063 seen.add(method.name); |
| 1038 } | 1064 } |
| 1039 } else { | 1065 } else { |
| 1040 assert(member is ConstructorDeclaration); | 1066 assert(member is ConstructorDeclaration); |
| 1041 } | 1067 } |
| 1042 } | 1068 } |
| 1043 } | 1069 } |
| 1044 | 1070 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1252 } while (!current.isObject && !visited.contains(current)); | 1278 } while (!current.isObject && !visited.contains(current)); |
| 1253 } | 1279 } |
| 1254 | 1280 |
| 1255 void _recordMessage(StaticInfo info) { | 1281 void _recordMessage(StaticInfo info) { |
| 1256 if (info == null) return; | 1282 if (info == null) return; |
| 1257 var error = info.toAnalysisError(); | 1283 var error = info.toAnalysisError(); |
| 1258 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; | 1284 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; |
| 1259 _reporter.onError(error); | 1285 _reporter.onError(error); |
| 1260 } | 1286 } |
| 1261 } | 1287 } |
| OLD | NEW |