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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 if (interfaceType == null || interfaceType.isObject) return; | 113 if (interfaceType == null || interfaceType.isObject) return; |
114 if (result.contains(interfaceType)) return; | 114 if (result.contains(interfaceType)) return; |
115 result.add(interfaceType); | 115 result.add(interfaceType); |
116 find(interfaceType.superclass, result); | 116 find(interfaceType.superclass, result); |
117 interfaceType.mixins.forEach((i) => find(i, result)); | 117 interfaceType.mixins.forEach((i) => find(i, result)); |
118 interfaceType.interfaces.forEach((i) => find(i, result)); | 118 interfaceType.interfaces.forEach((i) => find(i, result)); |
119 } | 119 } |
120 | 120 |
121 // Check all interfaces reachable from the `implements` clause in the | 121 // Check all interfaces reachable from the `implements` clause in the |
122 // current class against definitions here and in superclasses. | 122 // current class against definitions here and in superclasses. |
123 var localInterfaces = new Set(); | 123 var localInterfaces = new Set<InterfaceType>(); |
124 var type = node.element.type; | 124 var type = node.element.type; |
125 type.interfaces.forEach((i) => find(i, localInterfaces)); | 125 type.interfaces.forEach((i) => find(i, localInterfaces)); |
126 _checkInterfacesOverrides(node, localInterfaces, seen, | 126 _checkInterfacesOverrides(node, localInterfaces, seen, |
127 includeParents: true); | 127 includeParents: true); |
128 | 128 |
129 // Check also how we override locally the interfaces from parent classes if | 129 // Check also how we override locally the interfaces from parent classes if |
130 // the parent class is abstract. Otherwise, these will be checked as | 130 // the parent class is abstract. Otherwise, these will be checked as |
131 // overrides on the concrete superclass. | 131 // overrides on the concrete superclass. |
132 var superInterfaces = new Set(); | 132 var superInterfaces = new Set<InterfaceType>(); |
133 var parent = type.superclass; | 133 var parent = type.superclass; |
134 // TODO(sigmund): we don't seem to be reporting the analyzer error that a | 134 // TODO(sigmund): we don't seem to be reporting the analyzer error that a |
135 // non-abstract class is not implementing an interface. See | 135 // non-abstract class is not implementing an interface. See |
136 // https://github.com/dart-lang/dart-dev-compiler/issues/25 | 136 // https://github.com/dart-lang/dart-dev-compiler/issues/25 |
137 while (parent != null && parent.element.isAbstract) { | 137 while (parent != null && parent.element.isAbstract) { |
138 parent.interfaces.forEach((i) => find(i, superInterfaces)); | 138 parent.interfaces.forEach((i) => find(i, superInterfaces)); |
139 parent = parent.superclass; | 139 parent = parent.superclass; |
140 } | 140 } |
141 _checkInterfacesOverrides(node, superInterfaces, seen, | 141 _checkInterfacesOverrides(node, superInterfaces, seen, |
142 includeParents: false); | 142 includeParents: false); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 var setter = element.setter; | 232 var setter = element.setter; |
233 bool found = _checkSingleOverride(getter, baseType, variable, member); | 233 bool found = _checkSingleOverride(getter, baseType, variable, member); |
234 if (!variable.isFinal && | 234 if (!variable.isFinal && |
235 _checkSingleOverride(setter, baseType, variable, member)) { | 235 _checkSingleOverride(setter, baseType, variable, member)) { |
236 found = true; | 236 found = true; |
237 } | 237 } |
238 if (found) seen.add(name); | 238 if (found) seen.add(name); |
239 } | 239 } |
240 } else { | 240 } else { |
241 if ((member as MethodDeclaration).isStatic) continue; | 241 if ((member as MethodDeclaration).isStatic) continue; |
242 var method = member.element; | 242 var method = (member as MethodDeclaration).element; |
243 if (seen.contains(method.name)) continue; | 243 if (seen.contains(method.name)) continue; |
244 if (_checkSingleOverride(method, baseType, member, member)) { | 244 if (_checkSingleOverride(method, baseType, member, member)) { |
245 seen.add(method.name); | 245 seen.add(method.name); |
246 } | 246 } |
247 } | 247 } |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 /// Checks that [element] correctly overrides its corresponding member in | 251 /// Checks that [element] correctly overrides its corresponding member in |
252 /// [type]. Returns `true` if an override was found, that is, if [element] has | 252 /// [type]. Returns `true` if an override was found, that is, if [element] has |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 if (rules.isDynamicTarget(node.leftOperand)) { | 834 if (rules.isDynamicTarget(node.leftOperand)) { |
835 // Dynamic invocation | 835 // Dynamic invocation |
836 // TODO(vsm): Move this logic to the resolver? | 836 // TODO(vsm): Move this logic to the resolver? |
837 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) { | 837 if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) { |
838 _recordDynamicInvoke(node, node.leftOperand); | 838 _recordDynamicInvoke(node, node.leftOperand); |
839 } | 839 } |
840 } else { | 840 } else { |
841 var element = node.staticElement; | 841 var element = node.staticElement; |
842 // Method invocation. | 842 // Method invocation. |
843 if (element is MethodElement) { | 843 if (element is MethodElement) { |
844 var type = element.type as FunctionType; | 844 var type = element.type; |
845 // Analyzer should enforce number of parameter types, but check in | 845 // Analyzer should enforce number of parameter types, but check in |
846 // case we have erroneous input. | 846 // case we have erroneous input. |
847 if (type.normalParameterTypes.isNotEmpty) { | 847 if (type.normalParameterTypes.isNotEmpty) { |
848 checkArgument(node.rightOperand, type.normalParameterTypes[0]); | 848 checkArgument(node.rightOperand, type.normalParameterTypes[0]); |
849 } | 849 } |
850 } else { | 850 } else { |
851 // TODO(vsm): Assert that the analyzer found an error here? | 851 // TODO(vsm): Assert that the analyzer found an error here? |
852 } | 852 } |
853 } | 853 } |
854 } else { | 854 } else { |
(...skipping 20 matching lines...) Expand all Loading... |
875 } | 875 } |
876 | 876 |
877 @override | 877 @override |
878 void visitIndexExpression(IndexExpression node) { | 878 void visitIndexExpression(IndexExpression node) { |
879 var target = node.realTarget; | 879 var target = node.realTarget; |
880 if (rules.isDynamicTarget(target)) { | 880 if (rules.isDynamicTarget(target)) { |
881 _recordDynamicInvoke(node, target); | 881 _recordDynamicInvoke(node, target); |
882 } else { | 882 } else { |
883 var element = node.staticElement; | 883 var element = node.staticElement; |
884 if (element is MethodElement) { | 884 if (element is MethodElement) { |
885 var type = element.type as FunctionType; | 885 var type = element.type; |
886 // Analyzer should enforce number of parameter types, but check in | 886 // Analyzer should enforce number of parameter types, but check in |
887 // case we have erroneous input. | 887 // case we have erroneous input. |
888 if (type.normalParameterTypes.isNotEmpty) { | 888 if (type.normalParameterTypes.isNotEmpty) { |
889 checkArgument(node.index, type.normalParameterTypes[0]); | 889 checkArgument(node.index, type.normalParameterTypes[0]); |
890 } | 890 } |
891 } else { | 891 } else { |
892 // TODO(vsm): Assert that the analyzer found an error here? | 892 // TODO(vsm): Assert that the analyzer found an error here? |
893 } | 893 } |
894 } | 894 } |
895 node.visitChildren(this); | 895 node.visitChildren(this); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 var error = info.toAnalysisError(); | 999 var error = info.toAnalysisError(); |
1000 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; | 1000 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; |
1001 reporter.onError(error); | 1001 reporter.onError(error); |
1002 | 1002 |
1003 if (info is CoercionInfo) { | 1003 if (info is CoercionInfo) { |
1004 assert(CoercionInfo.get(info.node) == null); | 1004 assert(CoercionInfo.get(info.node) == null); |
1005 CoercionInfo.set(info.node, info); | 1005 CoercionInfo.set(info.node, info); |
1006 } | 1006 } |
1007 } | 1007 } |
1008 } | 1008 } |
OLD | NEW |