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

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2782533002: Report errors for the new top-level inference rules. (Closed)
Patch Set: Update language_strong status for analyzer. Created 3 years, 8 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 | « pkg/analyzer/lib/src/task/dart.dart ('k') | pkg/analyzer/lib/src/task/strong_mode.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 // 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';
11 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; 11 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
12 import 'package:analyzer/dart/ast/token.dart' show TokenType; 12 import 'package:analyzer/dart/ast/token.dart' show TokenType;
13 import 'package:analyzer/dart/ast/token.dart'; 13 import 'package:analyzer/dart/ast/token.dart';
14 import 'package:analyzer/dart/ast/visitor.dart'; 14 import 'package:analyzer/dart/ast/visitor.dart';
15 import 'package:analyzer/dart/element/element.dart'; 15 import 'package:analyzer/dart/element/element.dart';
16 import 'package:analyzer/dart/element/type.dart'; 16 import 'package:analyzer/dart/element/type.dart';
17 import 'package:analyzer/src/dart/element/element.dart';
17 import 'package:analyzer/src/dart/element/type.dart'; 18 import 'package:analyzer/src/dart/element/type.dart';
18 import 'package:analyzer/src/error/codes.dart' show StrongModeCode; 19 import 'package:analyzer/src/error/codes.dart' show StrongModeCode;
19 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; 20 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
20 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 21 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
21 import 'package:analyzer/src/generated/type_system.dart'; 22 import 'package:analyzer/src/generated/type_system.dart';
23 import 'package:analyzer/src/summary/idl.dart';
22 24
23 import 'ast_properties.dart'; 25 import 'ast_properties.dart';
24 26
25 /// Given an [expression] and a corresponding [typeSystem] and [typeProvider], 27 /// Given an [expression] and a corresponding [typeSystem] and [typeProvider],
26 /// gets the known static type of the expression. 28 /// gets the known static type of the expression.
27 /// 29 ///
28 /// Normally when we ask for an expression's type, we get the type of the 30 /// Normally when we ask for an expression's type, we get the type of the
29 /// storage slot that would contain it. For function types, this is necessarily 31 /// storage slot that would contain it. For function types, this is necessarily
30 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're 32 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're
31 /// interested in the expression's own type, it can often be a "strict arrow" 33 /// interested in the expression's own type, it can often be a "strict arrow"
32 /// because we know it evaluates to a specific, concrete function, and we can 34 /// because we know it evaluates to a specific, concrete function, and we can
33 /// treat "dynamic" as top for that case, which is more permissive. 35 /// treat "dynamic" as top for that case, which is more permissive.
34 DartType getDefiniteType( 36 DartType getDefiniteType(
35 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) { 37 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) {
36 DartType type = expression.staticType ?? DynamicTypeImpl.instance; 38 DartType type = expression.staticType ?? DynamicTypeImpl.instance;
37 if (typeSystem is StrongTypeSystemImpl && 39 if (typeSystem is StrongTypeSystemImpl &&
38 type is FunctionType && 40 type is FunctionType &&
39 hasStrictArrow(expression)) { 41 hasStrictArrow(expression)) {
40 // Remove fuzzy arrow if possible. 42 // Remove fuzzy arrow if possible.
41 return typeSystem.functionTypeToConcreteType(type); 43 return typeSystem.functionTypeToConcreteType(type);
42 } 44 }
43 return type; 45 return type;
44 } 46 }
45 47
48 bool hasStrictArrow(Expression expression) {
49 var element = _getKnownElement(expression);
50 return element is FunctionElement || element is MethodElement;
51 }
52
46 DartType _elementType(Element e) { 53 DartType _elementType(Element e) {
47 if (e == null) { 54 if (e == null) {
48 // Malformed code - just return dynamic. 55 // Malformed code - just return dynamic.
49 return DynamicTypeImpl.instance; 56 return DynamicTypeImpl.instance;
50 } 57 }
51 return (e as dynamic).type; 58 return (e as dynamic).type;
52 } 59 }
53 60
54 Element _getKnownElement(Expression expression) { 61 Element _getKnownElement(Expression expression) {
55 if (expression is ParenthesizedExpression) { 62 if (expression is ParenthesizedExpression) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 } 98 }
92 if (field.isSynthetic) return null; 99 if (field.isSynthetic) return null;
93 return field; 100 return field;
94 } 101 }
95 102
96 /// Looks up the declaration that matches [member] in [type] and returns it's 103 /// Looks up the declaration that matches [member] in [type] and returns it's
97 /// declared type. 104 /// declared type.
98 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) => 105 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) =>
99 _memberTypeGetter(member)(type); 106 _memberTypeGetter(member)(type);
100 107
101 bool hasStrictArrow(Expression expression) {
102 var element = _getKnownElement(expression);
103 return element is FunctionElement || element is MethodElement;
104 }
105
106 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) { 108 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) {
107 String memberName = member.name; 109 String memberName = member.name;
108 final isGetter = member is PropertyAccessorElement && member.isGetter; 110 final isGetter = member is PropertyAccessorElement && member.isGetter;
109 final isSetter = member is PropertyAccessorElement && member.isSetter; 111 final isSetter = member is PropertyAccessorElement && member.isSetter;
110 112
111 FunctionType f(InterfaceType type) { 113 FunctionType f(InterfaceType type) {
112 ExecutableElement baseMethod; 114 ExecutableElement baseMethod;
113 115
114 if (member.isPrivate) { 116 if (member.isPrivate) {
115 var subtypeLibrary = member.library; 117 var subtypeLibrary = member.library;
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 423
422 @override 424 @override
423 void visitForStatement(ForStatement node) { 425 void visitForStatement(ForStatement node) {
424 if (node.condition != null) { 426 if (node.condition != null) {
425 checkBoolean(node.condition); 427 checkBoolean(node.condition);
426 } 428 }
427 node.visitChildren(this); 429 node.visitChildren(this);
428 } 430 }
429 431
430 @override 432 @override
431 void visitFunctionExpression(FunctionExpression node) {
432 _checkForUnsafeBlockClosureInference(node);
433 super.visitFunctionExpression(node);
434 }
435
436 @override
437 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 433 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
438 checkFunctionApplication(node); 434 checkFunctionApplication(node);
439 node.visitChildren(this); 435 node.visitChildren(this);
440 } 436 }
441 437
442 @override 438 @override
443 void visitIfStatement(IfStatement node) { 439 void visitIfStatement(IfStatement node) {
444 checkBoolean(node.condition); 440 checkBoolean(node.condition);
445 node.visitChildren(this); 441 node.visitChildren(this);
446 } 442 }
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 : resolutionMap.elementDeclaredByVariableDeclaration(node); 634 : resolutionMap.elementDeclaredByVariableDeclaration(node);
639 if (!node.isConst && 635 if (!node.isConst &&
640 !node.isFinal && 636 !node.isFinal &&
641 node.initializer == null && 637 node.initializer == null &&
642 rules.isNonNullableType(variableElement?.type)) { 638 rules.isNonNullableType(variableElement?.type)) {
643 _recordMessage( 639 _recordMessage(
644 node, 640 node,
645 StaticTypeWarningCode.NON_NULLABLE_FIELD_NOT_INITIALIZED, 641 StaticTypeWarningCode.NON_NULLABLE_FIELD_NOT_INITIALIZED,
646 [node.name, variableElement?.type]); 642 [node.name, variableElement?.type]);
647 } 643 }
644 AstNode parent = node.parent;
645 if (variableElement != null &&
646 parent is VariableDeclarationList &&
647 parent.type == null &&
648 node.initializer != null) {
649 if (variableElement.kind == ElementKind.TOP_LEVEL_VARIABLE ||
650 variableElement.kind == ElementKind.FIELD) {
651 _validateTopLevelInitializer(variableElement.name, node.initializer);
652 }
653 }
648 return super.visitVariableDeclaration(node); 654 return super.visitVariableDeclaration(node);
649 } 655 }
650 656
651 @override 657 @override
652 void visitVariableDeclarationList(VariableDeclarationList node) { 658 void visitVariableDeclarationList(VariableDeclarationList node) {
653 TypeAnnotation type = node.type; 659 TypeAnnotation type = node.type;
654 if (type == null) { 660 if (type == null) {
655 // No checks are needed when the type is var. Although internally the 661 // No checks are needed when the type is var. Although internally the
656 // typing rules may have inferred a more precise type for the variable 662 // typing rules may have inferred a more precise type for the variable
657 // based on the initializer. 663 // based on the initializer.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 } 723 }
718 724
719 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { 725 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
720 if (field.staticElement == null && 726 if (field.staticElement == null &&
721 !typeProvider.isObjectMember(field.name)) { 727 !typeProvider.isObjectMember(field.name)) {
722 _recordDynamicInvoke(node, target); 728 _recordDynamicInvoke(node, target);
723 } 729 }
724 node.visitChildren(this); 730 node.visitChildren(this);
725 } 731 }
726 732
727 /**
728 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so,
729 * issue a warning.
730 *
731 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed.
732 */
733 void _checkForUnsafeBlockClosureInference(FunctionExpression node) {
734 if (node.body is! BlockFunctionBody) {
735 return;
736 }
737 if (resolutionMap
738 .elementDeclaredByFunctionExpression(node)
739 .returnType
740 .isDynamic) {
741 return;
742 }
743 // Find the enclosing variable declaration whose inferred type might depend
744 // on the inferred return type of the block closure (if any).
745 AstNode prevAncestor = node;
746 AstNode ancestor = node.parent;
747 while (ancestor != null && ancestor is! VariableDeclaration) {
748 if (ancestor is BlockFunctionBody) {
749 // node is inside another block function body; if that block
750 // function body is unsafe, we've already warned about it.
751 return;
752 }
753 if (ancestor is InstanceCreationExpression) {
754 // node appears inside an instance creation expression; we may be safe
755 // if the type of the instance creation expression requires no
756 // inference.
757 TypeName typeName = ancestor.constructorName.type;
758 if (typeName.typeArguments != null) {
759 // Type arguments were explicitly specified. We are safe.
760 return;
761 }
762 DartType type = typeName.type;
763 if (!(type is ParameterizedType && type.typeParameters.isNotEmpty)) {
764 // Type is not generic. We are safe.
765 return;
766 }
767 }
768 if (ancestor is MethodInvocation) {
769 // node appears inside a method or function invocation; we may be safe
770 // if the type of the method or function requires no inference.
771 if (ancestor.typeArguments != null) {
772 // Type arguments were explicitly specified. We are safe.
773 return;
774 }
775 Element methodElement = ancestor.methodName.staticElement;
776 if (!(methodElement is ExecutableElement &&
777 methodElement.typeParameters.isNotEmpty)) {
778 // Method is not generic. We are safe.
779 return;
780 }
781 }
782 if (ancestor is FunctionExpressionInvocation &&
783 !identical(prevAncestor, ancestor.function)) {
784 // node appears inside an argument to a function expression invocation;
785 // we may be safe if the type of the function expression requires no
786 // inference.
787 if (ancestor.typeArguments != null) {
788 // Type arguments were explicitly specified. We are safe.
789 return;
790 }
791 DartType type = ancestor.function.staticType;
792 if (!(type is FunctionTypeImpl && type.typeFormals.isNotEmpty)) {
793 // Type is not generic or has had its type parameters instantiated.
794 // We are safe.
795 return;
796 }
797 }
798 if ((ancestor is ListLiteral && ancestor.typeArguments != null) ||
799 (ancestor is MapLiteral && ancestor.typeArguments != null)) {
800 // node appears inside a list or map literal with an explicit type. We
801 // are safe because no type inference is required.
802 return;
803 }
804 prevAncestor = ancestor;
805 ancestor = ancestor.parent;
806 }
807 if (ancestor == null) {
808 // node is not inside a variable declaration, so it is safe.
809 return;
810 }
811 VariableDeclaration decl = ancestor;
812 VariableElement declElement = decl.element;
813 if (!declElement.hasImplicitType) {
814 // Variable declaration has an explicit type, so it's safe.
815 return;
816 }
817 if (declElement.type.isDynamic) {
818 // No type was successfully inferred for this variable, so it's safe.
819 return;
820 }
821 if (declElement.enclosingElement is ExecutableElement) {
822 // Variable declaration is inside a function or method, so it's safe.
823 return;
824 }
825 _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE,
826 [declElement.name]);
827 }
828
829 /// Checks if an implicit cast of [expr] from [from] type to [to] type is 733 /// Checks if an implicit cast of [expr] from [from] type to [to] type is
830 /// needed, and if so records it. 734 /// needed, and if so records it.
831 /// 735 ///
832 /// If [from] is omitted, uses the static type of [expr]. 736 /// If [from] is omitted, uses the static type of [expr].
833 /// 737 ///
834 /// If [expr] does not require an implicit cast because it is not related to 738 /// If [expr] does not require an implicit cast because it is not related to
835 /// [to] or is already a subtype of it, does nothing. 739 /// [to] or is already a subtype of it, does nothing.
836 void _checkImplicitCast(Expression expr, DartType to, 740 void _checkImplicitCast(Expression expr, DartType to,
837 {DartType from, bool opAssign: false}) { 741 {DartType from, bool opAssign: false}) {
838 from ??= _getDefiniteType(expr); 742 from ??= _getDefiniteType(expr);
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 : node.offset; 1046 : node.offset;
1143 int length = node.end - begin; 1047 int length = node.end - begin;
1144 var source = resolutionMap 1048 var source = resolutionMap
1145 .elementDeclaredByCompilationUnit(node.root as CompilationUnit) 1049 .elementDeclaredByCompilationUnit(node.root as CompilationUnit)
1146 .source; 1050 .source;
1147 var error = 1051 var error =
1148 new AnalysisError(source, begin, length, errorCode, arguments); 1052 new AnalysisError(source, begin, length, errorCode, arguments);
1149 reporter.onError(error); 1053 reporter.onError(error);
1150 } 1054 }
1151 } 1055 }
1056
1057 void _validateTopLevelInitializer(String name, Expression n) {
1058 void validateHasType(PropertyAccessorElement e) {
1059 if (e.hasImplicitReturnType) {
1060 var variable = e.variable as VariableElementImpl;
1061 TopLevelInferenceError error = variable.typeInferenceError;
1062 if (error != null) {
1063 if (error.kind == TopLevelInferenceErrorKind.dependencyCycle) {
1064 _recordMessage(
1065 n, StrongModeCode.TOP_LEVEL_CYCLE, [name, error.arguments]);
1066 } else {
1067 _recordMessage(
1068 n, StrongModeCode.TOP_LEVEL_IDENTIFIER_NO_TYPE, [name, e.name]);
1069 }
1070 }
1071 }
1072 }
1073
1074 void validateIdentifierElement(AstNode n, Element e) {
1075 if (e == null) {
1076 return;
1077 }
1078
1079 Element enclosing = e.enclosingElement;
1080 if (enclosing is CompilationUnitElement) {
1081 if (e is PropertyAccessorElement) {
1082 validateHasType(e);
1083 }
1084 } else if (enclosing is ClassElement) {
1085 if (e is PropertyAccessorElement) {
1086 if (e.isStatic) {
1087 validateHasType(e);
1088 } else {
1089 _recordMessage(
1090 n, StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, [name, e.name]);
1091 }
1092 }
1093 }
1094 }
1095
1096 if (n == null ||
1097 n is NullLiteral ||
1098 n is BooleanLiteral ||
1099 n is DoubleLiteral ||
1100 n is IntegerLiteral ||
1101 n is StringLiteral ||
1102 n is SymbolLiteral) {
1103 // Nothing to validate.
1104 } else if (n is AwaitExpression) {
1105 _validateTopLevelInitializer(name, n.expression);
1106 } else if (n is ThrowExpression) {
1107 // Nothing to validate.
1108 } else if (n is ParenthesizedExpression) {
1109 _validateTopLevelInitializer(name, n.expression);
1110 } else if (n is ConditionalExpression) {
1111 _validateTopLevelInitializer(name, n.thenExpression);
1112 _validateTopLevelInitializer(name, n.elseExpression);
1113 } else if (n is BinaryExpression) {
1114 TokenType operator = n.operator.type;
1115 if (operator == TokenType.AMPERSAND_AMPERSAND ||
1116 operator == TokenType.BAR_BAR ||
1117 operator == TokenType.EQ_EQ ||
1118 operator == TokenType.BANG_EQ) {
1119 // These operators give 'bool', no need to validate operands.
1120 } else if (operator == TokenType.QUESTION_QUESTION) {
1121 _recordMessage(n, StrongModeCode.TOP_LEVEL_UNSUPPORTED,
1122 [name, n.runtimeType.toString()]);
1123 } else {
1124 _validateTopLevelInitializer(name, n.leftOperand);
1125 }
1126 } else if (n is PrefixExpression) {
1127 TokenType operator = n.operator.type;
1128 if (operator == TokenType.BANG) {
1129 // This operator gives 'bool', no need to validate operands.
1130 } else {
1131 _validateTopLevelInitializer(name, n.operand);
1132 }
1133 } else if (n is PostfixExpression) {
1134 _validateTopLevelInitializer(name, n.operand);
1135 } else if (n is ListLiteral) {
1136 if (n.typeArguments == null) {
1137 for (Expression element in n.elements) {
1138 _validateTopLevelInitializer(name, element);
1139 }
1140 }
1141 } else if (n is MapLiteral) {
1142 if (n.typeArguments == null) {
1143 for (MapLiteralEntry entry in n.entries) {
1144 _validateTopLevelInitializer(name, entry.key);
1145 _validateTopLevelInitializer(name, entry.value);
1146 }
1147 }
1148 } else if (n is FunctionExpression) {
1149 for (FormalParameter p in n.parameters.parameters) {
1150 if (p is DefaultFormalParameter) {
1151 p = (p as DefaultFormalParameter).parameter;
1152 }
1153 if (p is SimpleFormalParameter) {
1154 if (p.type == null) {
1155 _recordMessage(
1156 p,
1157 StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_PARAMETER,
1158 [name, p.element?.name]);
1159 }
1160 }
1161 }
1162
1163 FunctionBody body = n.body;
1164 if (body is ExpressionFunctionBody) {
1165 _validateTopLevelInitializer(name, body.expression);
1166 } else {
1167 _recordMessage(n, StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK, []);
1168 }
1169 } else if (n is InstanceCreationExpression) {
1170 ConstructorElement constructor = n.staticElement;
1171 ClassElement clazz = constructor?.enclosingElement;
1172 if (clazz != null && clazz.typeParameters.isNotEmpty) {
1173 TypeName type = n.constructorName.type;
1174 if (type.typeArguments == null) {
1175 _recordMessage(type, StrongModeCode.TOP_LEVEL_TYPE_ARGUMENTS,
1176 [name, clazz.name]);
1177 }
1178 }
1179 } else if (n is AsExpression) {
1180 // Nothing to validate.
1181 } else if (n is IsExpression) {
1182 // Nothing to validate.
1183 } else if (n is Identifier) {
1184 validateIdentifierElement(n, n.staticElement);
1185 } else if (n is PropertyAccess) {
1186 Element element = n.propertyName.staticElement;
1187 validateIdentifierElement(n.propertyName, element);
1188 } else if (n is FunctionExpressionInvocation) {
1189 _validateTopLevelInitializer(name, n.function);
1190 // TODO(scheglov) type arguments
1191 } else if (n is MethodInvocation) {
1192 _validateTopLevelInitializer(name, n.target);
1193 SimpleIdentifier methodName = n.methodName;
1194 Element element = methodName.staticElement;
1195 if (element is ExecutableElement && element.typeParameters.isNotEmpty) {
1196 if (n.typeArguments == null) {
1197 _recordMessage(methodName, StrongModeCode.TOP_LEVEL_TYPE_ARGUMENTS,
1198 [name, methodName.name]);
1199 }
1200 }
1201 } else if (n is CascadeExpression) {
1202 _validateTopLevelInitializer(name, n.target);
1203 } else {
1204 _recordMessage(n, StrongModeCode.TOP_LEVEL_UNSUPPORTED,
1205 [name, n.runtimeType.toString()]);
1206 }
1207 }
1152 } 1208 }
1153 1209
1154 /// Checks for overriding declarations of fields and methods. This is used to 1210 /// Checks for overriding declarations of fields and methods. This is used to
1155 /// check overrides between classes and superclasses, interfaces, and mixin 1211 /// check overrides between classes and superclasses, interfaces, and mixin
1156 /// applications. 1212 /// applications.
1157 class _OverrideChecker { 1213 class _OverrideChecker {
1158 final StrongTypeSystemImpl rules; 1214 final StrongTypeSystemImpl rules;
1159 final CodeChecker _checker; 1215 final CodeChecker _checker;
1160 1216
1161 _OverrideChecker(CodeChecker checker) 1217 _OverrideChecker(CodeChecker checker)
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
1493 var visited = new Set<InterfaceType>(); 1549 var visited = new Set<InterfaceType>();
1494 do { 1550 do {
1495 visited.add(current); 1551 visited.add(current);
1496 current.mixins.reversed.forEach( 1552 current.mixins.reversed.forEach(
1497 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1553 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1498 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1554 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1499 current = current.superclass; 1555 current = current.superclass;
1500 } while (!current.isObject && !visited.contains(current)); 1556 } while (!current.isObject && !visited.contains(current));
1501 } 1557 }
1502 } 1558 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/task/dart.dart ('k') | pkg/analyzer/lib/src/task/strong_mode.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698