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 analyzer.src.task.strong_mode; | 5 library analyzer.src.task.strong_mode; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
(...skipping 11 matching lines...) Expand all Loading... |
22 * Return `true` if the given [expression] is an immediately-evident expression, | 22 * Return `true` if the given [expression] is an immediately-evident expression, |
23 * so can be used to infer the type for a top-level variable or a class field. | 23 * so can be used to infer the type for a top-level variable or a class field. |
24 */ | 24 */ |
25 bool isValidForTypeInference(Expression expression) { | 25 bool isValidForTypeInference(Expression expression) { |
26 var visitor = new _IsValidForTypeInferenceVisitor(); | 26 var visitor = new _IsValidForTypeInferenceVisitor(); |
27 expression.accept(visitor); | 27 expression.accept(visitor); |
28 return visitor.isValid; | 28 return visitor.isValid; |
29 } | 29 } |
30 | 30 |
31 /** | 31 /** |
32 * Sets the type of the field. This is stored in the field itself, and the | 32 * Sets the type of the field. The types in implicit accessors are updated |
33 * synthetic getter/setter types. | 33 * implicitly, and the types of explicit accessors should be updated separately. |
34 */ | 34 */ |
35 void setFieldType(VariableElement field, DartType newType) { | 35 void setFieldType(VariableElement field, DartType newType) { |
36 (field as VariableElementImpl).type = newType; | 36 (field as VariableElementImpl).type = newType; |
37 if (field.initializer != null) { | |
38 (field.initializer as ExecutableElementImpl).returnType = newType; | |
39 } | |
40 } | 37 } |
41 | 38 |
42 /** | 39 /** |
43 * Return the element for the single parameter of the given [setter], or `null` | |
44 * if the executable element is not a setter or does not have a single | |
45 * parameter. | |
46 */ | |
47 ParameterElement _getParameter(ExecutableElement setter) { | |
48 if (setter is PropertyAccessorElement && setter.isSetter) { | |
49 List<ParameterElement> parameters = setter.parameters; | |
50 if (parameters.length == 1) { | |
51 return parameters[0]; | |
52 } | |
53 } | |
54 return null; | |
55 } | |
56 | |
57 /** | |
58 * A function that returns `true` if the given [element] passes the filter. | 40 * A function that returns `true` if the given [element] passes the filter. |
59 */ | 41 */ |
60 typedef bool VariableFilter(VariableElement element); | 42 typedef bool VariableFilter(VariableElement element); |
61 | 43 |
62 /** | 44 /** |
63 * An object used to infer the type of instance fields and the return types of | 45 * An object used to infer the type of instance fields and the return types of |
64 * instance methods within a single compilation unit. | 46 * instance methods within a single compilation unit. |
65 */ | 47 */ |
66 class InstanceMemberInferrer { | 48 class InstanceMemberInferrer { |
67 /** | 49 /** |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 103 |
122 /** | 104 /** |
123 * Return `true` if the list of [elements] contains only methods. | 105 * Return `true` if the list of [elements] contains only methods. |
124 */ | 106 */ |
125 bool _allSameElementKind( | 107 bool _allSameElementKind( |
126 ExecutableElement element, List<ExecutableElement> elements) { | 108 ExecutableElement element, List<ExecutableElement> elements) { |
127 return elements.every((e) => e.kind == element.kind); | 109 return elements.every((e) => e.kind == element.kind); |
128 } | 110 } |
129 | 111 |
130 /** | 112 /** |
| 113 * Compute the inferred type for the given property accessor [element]. The |
| 114 * returned value is never `null`, but might be an error, and/or have the |
| 115 * `null` type. |
| 116 */ |
| 117 _FieldOverrideInferenceResult _computeFieldOverrideType( |
| 118 ExecutableElement element) { |
| 119 String name = element.displayName; |
| 120 |
| 121 var overriddenElements = <ExecutableElement>[]; |
| 122 overriddenElements.addAll( |
| 123 inheritanceManager.lookupOverrides(element.enclosingElement, name)); |
| 124 overriddenElements.addAll( |
| 125 inheritanceManager.lookupOverrides(element.enclosingElement, '$name=')); |
| 126 |
| 127 bool isCovariant = false; |
| 128 DartType impliedType; |
| 129 for (ExecutableElement overriddenElement in overriddenElements) { |
| 130 FunctionType overriddenType = |
| 131 _toOverriddenFunctionType(element, overriddenElement); |
| 132 if (overriddenType == null) { |
| 133 return new _FieldOverrideInferenceResult(false, null, true); |
| 134 } |
| 135 |
| 136 DartType type; |
| 137 if (overriddenElement.kind == ElementKind.GETTER) { |
| 138 type = overriddenType.returnType; |
| 139 } else if (overriddenElement.kind == ElementKind.SETTER) { |
| 140 if (overriddenType.parameters.length == 1) { |
| 141 ParameterElement parameter = overriddenType.parameters[0]; |
| 142 type = parameter.type; |
| 143 isCovariant = isCovariant || parameter.isCovariant; |
| 144 } |
| 145 } else { |
| 146 return new _FieldOverrideInferenceResult(false, null, true); |
| 147 } |
| 148 |
| 149 if (impliedType == null) { |
| 150 impliedType = type; |
| 151 } else if (type != impliedType) { |
| 152 return new _FieldOverrideInferenceResult(false, null, true); |
| 153 } |
| 154 } |
| 155 |
| 156 return new _FieldOverrideInferenceResult(isCovariant, impliedType, false); |
| 157 } |
| 158 |
| 159 /** |
131 * Compute the best type for the [parameter] at the given [index] that must be | 160 * Compute the best type for the [parameter] at the given [index] that must be |
132 * compatible with the types of the corresponding parameters of the given | 161 * compatible with the types of the corresponding parameters of the given |
133 * [overriddenMethods]. | 162 * [overriddenTypes]. |
134 * | 163 * |
135 * At the moment, this method will only return a type other than 'dynamic' if | 164 * At the moment, this method will only return a type other than 'dynamic' if |
136 * the types of all of the parameters are the same. In the future we might | 165 * the types of all of the parameters are the same. In the future we might |
137 * want to be smarter about it, such as by returning the least upper bound of | 166 * want to be smarter about it, such as by returning the least upper bound of |
138 * the parameter types. | 167 * the parameter types. |
139 */ | 168 */ |
140 DartType _computeParameterType(ParameterElement parameter, int index, | 169 DartType _computeParameterType(ParameterElement parameter, int index, |
141 List<FunctionType> overriddenTypes) { | 170 List<FunctionType> overriddenTypes) { |
142 DartType parameterType = null; | 171 DartType parameterType = null; |
143 int length = overriddenTypes.length; | 172 int length = overriddenTypes.length; |
144 for (int i = 0; i < length; i++) { | 173 for (int i = 0; i < length; i++) { |
145 ParameterElement matchingParam = _getCorrespondingParameter( | 174 ParameterElement matchingParameter = _getCorrespondingParameter( |
146 parameter, index, overriddenTypes[i].parameters); | 175 parameter, index, overriddenTypes[i].parameters); |
147 var type = matchingParam?.type ?? typeProvider.dynamicType; | 176 DartType type = matchingParameter?.type ?? typeProvider.dynamicType; |
148 if (parameterType == null) { | 177 if (parameterType == null) { |
149 parameterType = type; | 178 parameterType = type; |
150 } else if (parameterType != type) { | 179 } else if (parameterType != type) { |
151 return typeProvider.dynamicType; | 180 return typeProvider.dynamicType; |
152 } | 181 } |
153 } | 182 } |
154 return parameterType ?? typeProvider.dynamicType; | 183 return parameterType ?? typeProvider.dynamicType; |
155 } | 184 } |
156 | 185 |
157 /** | 186 /** |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 if (index < methodParameters.length) { | 235 if (index < methodParameters.length) { |
207 var matchingParameter = methodParameters[index]; | 236 var matchingParameter = methodParameters[index]; |
208 if (matchingParameter.parameterKind != ParameterKind.NAMED) { | 237 if (matchingParameter.parameterKind != ParameterKind.NAMED) { |
209 return matchingParameter; | 238 return matchingParameter; |
210 } | 239 } |
211 } | 240 } |
212 return null; | 241 return null; |
213 } | 242 } |
214 | 243 |
215 /** | 244 /** |
| 245 * If the given [element] represents a non-synthetic instance property |
| 246 * accessor for which no type was provided, infer its types. |
| 247 */ |
| 248 void _inferAccessor(PropertyAccessorElement element) { |
| 249 if (element.isSynthetic || element.isStatic) { |
| 250 return; |
| 251 } |
| 252 |
| 253 if (element.kind == ElementKind.GETTER && !element.hasImplicitReturnType) { |
| 254 return; |
| 255 } |
| 256 |
| 257 _FieldOverrideInferenceResult typeResult = |
| 258 _computeFieldOverrideType(element); |
| 259 if (typeResult.isError == null || typeResult.type == null) { |
| 260 return; |
| 261 } |
| 262 |
| 263 if (element.kind == ElementKind.GETTER) { |
| 264 (element as ExecutableElementImpl).returnType = typeResult.type; |
| 265 } else if (element.kind == ElementKind.SETTER) { |
| 266 var parameter = element.parameters[0] as ParameterElementImpl; |
| 267 if (parameter.hasImplicitType) { |
| 268 parameter.type = typeResult.type; |
| 269 } |
| 270 parameter.inheritsCovariant = typeResult.isCovariant; |
| 271 } |
| 272 setFieldType(element.variable, typeResult.type); |
| 273 } |
| 274 |
| 275 /** |
216 * Infer type information for all of the instance members in the given | 276 * Infer type information for all of the instance members in the given |
217 * [classElement]. | 277 * [classElement]. |
218 */ | 278 */ |
219 void _inferClass(ClassElement classElement) { | 279 void _inferClass(ClassElement classElement) { |
220 if (classElement is ClassElementImpl) { | 280 if (classElement is ClassElementImpl) { |
221 if (classElement.hasBeenInferred) { | 281 if (classElement.hasBeenInferred) { |
222 return; | 282 return; |
223 } | 283 } |
224 if (!elementsBeingInferred.add(classElement)) { | 284 if (!elementsBeingInferred.add(classElement)) { |
225 // We have found a circularity in the class hierarchy. For now we just | 285 // We have found a circularity in the class hierarchy. For now we just |
226 // stop trying to infer any type information for any classes that | 286 // stop trying to infer any type information for any classes that |
227 // inherit from any class in the cycle. We could potentially limit the | 287 // inherit from any class in the cycle. We could potentially limit the |
228 // algorithm to only not inferring types in the classes in the cycle, | 288 // algorithm to only not inferring types in the classes in the cycle, |
229 // but it isn't clear that the results would be significantly better. | 289 // but it isn't clear that the results would be significantly better. |
230 throw new _CycleException(); | 290 throw new _CycleException(); |
231 } | 291 } |
232 try { | 292 try { |
233 // | 293 // |
234 // Ensure that all of instance members in the supertypes have had types | 294 // Ensure that all of instance members in the supertypes have had types |
235 // inferred for them. | 295 // inferred for them. |
236 // | 296 // |
237 _inferType(classElement.supertype); | 297 _inferType(classElement.supertype); |
238 classElement.mixins.forEach(_inferType); | 298 classElement.mixins.forEach(_inferType); |
239 classElement.interfaces.forEach(_inferType); | 299 classElement.interfaces.forEach(_inferType); |
240 // | 300 // |
241 // Then infer the types for the members. | 301 // Then infer the types for the members. |
242 // | 302 // |
243 classElement.fields.forEach(_inferField); | 303 classElement.fields.forEach(_inferField); |
244 classElement.accessors.forEach(_inferExecutable); | 304 classElement.accessors.forEach(_inferAccessor); |
245 classElement.methods.forEach(_inferExecutable); | 305 classElement.methods.forEach(_inferExecutable); |
246 // | 306 // |
247 // Infer initializing formal parameter types. This must happen after | 307 // Infer initializing formal parameter types. This must happen after |
248 // field types are inferred. | 308 // field types are inferred. |
249 // | 309 // |
250 classElement.constructors.forEach(_inferConstructorFieldFormals); | 310 classElement.constructors.forEach(_inferConstructorFieldFormals); |
251 classElement.hasBeenInferred = true; | 311 classElement.hasBeenInferred = true; |
252 } finally { | 312 } finally { |
253 elementsBeingInferred.remove(classElement); | 313 elementsBeingInferred.remove(classElement); |
254 } | 314 } |
255 } | 315 } |
256 } | 316 } |
257 | 317 |
258 void _inferConstructorFieldFormals(ConstructorElement element) { | 318 void _inferConstructorFieldFormals(ConstructorElement constructor) { |
259 for (ParameterElement p in element.parameters) { | 319 for (ParameterElement parameter in constructor.parameters) { |
260 if (p is FieldFormalParameterElementImpl) { | 320 if (parameter.hasImplicitType && |
261 _inferFieldFormalParameter(p); | 321 parameter is FieldFormalParameterElementImpl) { |
| 322 FieldElement field = parameter.field; |
| 323 if (field != null) { |
| 324 parameter.type = field.type; |
| 325 } |
262 } | 326 } |
263 } | 327 } |
264 } | 328 } |
265 | 329 |
266 /** | 330 /** |
267 * If the given [element] represents a non-synthetic instance method, | 331 * If the given [element] represents a non-synthetic instance method, |
268 * getter or setter, infer the return type and any parameter type(s) where | 332 * getter or setter, infer the return type and any parameter type(s) where |
269 * they were not provided. | 333 * they were not provided. |
270 */ | 334 */ |
271 void _inferExecutable(ExecutableElement element) { | 335 void _inferExecutable(ExecutableElement element) { |
272 if (element.isSynthetic || element.isStatic) { | 336 if (element.isSynthetic || element.isStatic) { |
273 return; | 337 return; |
274 } | 338 } |
275 List<ExecutableElement> overriddenMethods = inheritanceManager | 339 List<ExecutableElement> overriddenElements = inheritanceManager |
276 .lookupOverrides(element.enclosingElement, element.name); | 340 .lookupOverrides(element.enclosingElement, element.displayName); |
277 if (overriddenMethods.isEmpty || | 341 if (overriddenElements.isEmpty || |
278 !_allSameElementKind(element, overriddenMethods)) { | 342 !_allSameElementKind(element, overriddenElements)) { |
| 343 return; |
| 344 } |
| 345 |
| 346 List<FunctionType> overriddenTypes = |
| 347 _toOverriddenFunctionTypes(element, overriddenElements); |
| 348 if (overriddenTypes.isEmpty) { |
279 return; | 349 return; |
280 } | 350 } |
281 | 351 |
282 // | 352 // |
283 // Overridden methods must have the same number of generic type parameters | |
284 // as this method, or none. | |
285 // | |
286 // If we do have generic type parameters on the element we're inferring, | |
287 // we must express its parameter and return types in terms of its own | |
288 // parameters. For example, given `m<T>(t)` overriding `m<S>(S s)` we | |
289 // should infer this as `m<T>(T t)`. | |
290 // | |
291 List<DartType> typeFormals = | |
292 TypeParameterTypeImpl.getTypes(element.type.typeFormals); | |
293 | |
294 List<FunctionType> overriddenTypes = new List<FunctionType>(); | |
295 for (ExecutableElement overriddenMethod in overriddenMethods) { | |
296 FunctionType overriddenType = overriddenMethod.type; | |
297 if (overriddenType == null) { | |
298 // TODO(brianwilkerson) I think the overridden method should always have | |
299 // a type, but there appears to be a bug that causes it to sometimes be | |
300 // null, we guard against that case by not performing inference. | |
301 return; | |
302 } | |
303 if (overriddenType.typeFormals.isNotEmpty) { | |
304 if (overriddenType.typeFormals.length != typeFormals.length) { | |
305 return; | |
306 } | |
307 overriddenType = overriddenType.instantiate(typeFormals); | |
308 } | |
309 overriddenTypes.add(overriddenType); | |
310 } | |
311 | |
312 // | |
313 // Infer the return type. | 353 // Infer the return type. |
314 // | 354 // |
315 if (element.hasImplicitReturnType) { | 355 if (element.hasImplicitReturnType) { |
316 (element as ExecutableElementImpl).returnType = | 356 (element as ExecutableElementImpl).returnType = |
317 _computeReturnType(overriddenTypes.map((t) => t.returnType)); | 357 _computeReturnType(overriddenTypes.map((t) => t.returnType)); |
318 if (element is PropertyAccessorElement) { | 358 if (element is PropertyAccessorElement) { |
319 _updateSyntheticVariableType(element); | 359 _updateSyntheticVariableType(element); |
320 } | 360 } |
321 } | 361 } |
322 // | 362 // |
(...skipping 10 matching lines...) Expand all Loading... |
333 parameter.type = _computeParameterType(parameter, i, overriddenTypes); | 373 parameter.type = _computeParameterType(parameter, i, overriddenTypes); |
334 if (element is PropertyAccessorElement) { | 374 if (element is PropertyAccessorElement) { |
335 _updateSyntheticVariableType(element); | 375 _updateSyntheticVariableType(element); |
336 } | 376 } |
337 } | 377 } |
338 } | 378 } |
339 } | 379 } |
340 } | 380 } |
341 | 381 |
342 /** | 382 /** |
343 * If the given [fieldElement] represents a non-synthetic instance field for | 383 * If the given [field] represents a non-synthetic instance field for |
344 * which no type was provided, infer the type of the field. | 384 * which no type was provided, infer the type of the field. |
345 */ | 385 */ |
346 void _inferField(FieldElement fieldElement) { | 386 void _inferField(FieldElement field) { |
347 if (fieldElement.isSynthetic || fieldElement.isStatic) { | 387 if (field.isSynthetic || field.isStatic) { |
348 return; | 388 return; |
349 } | 389 } |
350 List<ExecutableElement> overriddenSetters = | 390 |
351 inheritanceManager.lookupOverrides( | 391 _FieldOverrideInferenceResult typeResult = |
352 fieldElement.enclosingElement, fieldElement.name + '='); | 392 _computeFieldOverrideType(field.getter); |
353 var setter = fieldElement.setter; | 393 if (typeResult.isError) { |
354 if (setter != null && overriddenSetters.isNotEmpty) { | 394 return; |
355 _inferParameterCovariance( | |
356 setter.parameters[0], 0, overriddenSetters.map((s) => s.type)); | |
357 } | 395 } |
358 | 396 |
359 if (fieldElement.hasImplicitType) { | 397 if (field.hasImplicitType) { |
360 // | 398 DartType newType = typeResult.type; |
361 // First look for overridden getters with the same name as the field. | 399 if (newType == null && |
362 // | 400 field.initializer != null && |
363 List<ExecutableElement> overriddenGetters = inheritanceManager | 401 !fieldsWithDisabledInitializerInference.contains(field)) { |
364 .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); | 402 newType = field.initializer.returnType; |
365 DartType newType = null; | 403 } |
366 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { | |
367 newType = | |
368 _computeReturnType(overriddenGetters.map((e) => e.returnType)); | |
369 | 404 |
370 if (!_isCompatible(newType, overriddenSetters)) { | |
371 newType = null; | |
372 } | |
373 } | |
374 // | |
375 // If there is no overridden getter or if the overridden getter's type is | |
376 // dynamic, then we can infer the type from the initialization expression | |
377 // without breaking subtype rules. We could potentially infer a consistent | |
378 // return type even if the overridden getter's type was not dynamic, but | |
379 // choose not to for simplicity. The field is required to be final to | |
380 // prevent choosing a type that is inconsistent with assignments we cannot | |
381 // analyze. | |
382 // | |
383 if (newType == null || newType.isDynamic) { | |
384 FunctionElement initializer = fieldElement.initializer; | |
385 if (initializer != null && | |
386 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | |
387 if (!fieldsWithDisabledInitializerInference.contains(fieldElement)) { | |
388 newType = initializer.returnType; | |
389 } | |
390 } | |
391 } | |
392 if (newType == null || newType.isBottom || newType.isDartCoreNull) { | 405 if (newType == null || newType.isBottom || newType.isDartCoreNull) { |
393 newType = typeProvider.dynamicType; | 406 newType = typeProvider.dynamicType; |
394 } | 407 } |
395 setFieldType(fieldElement, newType); | 408 |
| 409 setFieldType(field, newType); |
| 410 } |
| 411 |
| 412 if (field.setter != null) { |
| 413 var parameter = field.setter.parameters[0] as ParameterElementImpl; |
| 414 parameter.inheritsCovariant = typeResult.isCovariant; |
396 } | 415 } |
397 } | 416 } |
398 | 417 |
399 void _inferFieldFormalParameter(FieldFormalParameterElementImpl element) { | |
400 FieldElement field = element.field; | |
401 if (field != null && element.hasImplicitType) { | |
402 element.type = field.type; | |
403 } | |
404 } | |
405 | |
406 /** | 418 /** |
407 * If a parameter is covariant, any parameters that override it are too. | 419 * If a parameter is covariant, any parameters that override it are too. |
408 */ | 420 */ |
409 void _inferParameterCovariance(ParameterElementImpl parameter, int index, | 421 void _inferParameterCovariance(ParameterElementImpl parameter, int index, |
410 Iterable<FunctionType> overriddenTypes) { | 422 Iterable<FunctionType> overriddenTypes) { |
411 parameter.inheritsCovariant = overriddenTypes.any((f) { | 423 parameter.inheritsCovariant = overriddenTypes.any((f) { |
412 var param = _getCorrespondingParameter(parameter, index, f.parameters); | 424 var param = _getCorrespondingParameter(parameter, index, f.parameters); |
413 return param != null && param.isCovariant; | 425 return param != null && param.isCovariant; |
414 }); | 426 }); |
415 } | 427 } |
416 | 428 |
417 /** | 429 /** |
418 * Infer type information for all of the instance members in the given | 430 * Infer type information for all of the instance members in the given |
419 * interface [type]. | 431 * interface [type]. |
420 */ | 432 */ |
421 void _inferType(InterfaceType type) { | 433 void _inferType(InterfaceType type) { |
422 if (type != null) { | 434 if (type != null) { |
423 ClassElement element = type.element; | 435 ClassElement element = type.element; |
424 if (element != null) { | 436 if (element != null) { |
425 _inferClass(element); | 437 _inferClass(element); |
426 } | 438 } |
427 } | 439 } |
428 } | 440 } |
429 | 441 |
430 /** | 442 /** |
431 * Return `true` if the given [type] is compatible with the argument types of | 443 * TODO |
432 * all of the given [setters]. | 444 * |
| 445 * Return [FunctionType]s of the [overriddenElement] that [element] overrides. |
| 446 * Return `null`, in case of type parameters inconsistency. |
| 447 * |
| 448 * Overridden elements must have the same number of generic type parameters |
| 449 * as the target element, or none. |
| 450 * |
| 451 * If we do have generic type parameters on the element we're inferring, |
| 452 * we must express its parameter and return types in terms of its own |
| 453 * parameters. For example, given `m<T>(t)` overriding `m<S>(S s)` we |
| 454 * should infer this as `m<T>(T t)`. |
433 */ | 455 */ |
434 bool _isCompatible(DartType type, List<ExecutableElement> setters) { | 456 FunctionType _toOverriddenFunctionType( |
435 for (ExecutableElement setter in setters) { | 457 ExecutableElement element, ExecutableElement overriddenElement) { |
436 ParameterElement parameter = _getParameter(setter); | 458 List<DartType> typeFormals = |
437 if (parameter != null && !typeSystem.isSubtypeOf(parameter.type, type)) { | 459 TypeParameterTypeImpl.getTypes(element.type.typeFormals); |
438 return false; | 460 |
| 461 FunctionType overriddenType = overriddenElement.type; |
| 462 if (overriddenType == null) { |
| 463 // TODO(brianwilkerson) I think the overridden method should always have |
| 464 // a type, but there appears to be a bug that causes it to sometimes be |
| 465 // null, we guard against that case by not performing inference. |
| 466 return null; |
| 467 } |
| 468 if (overriddenType.typeFormals.isNotEmpty) { |
| 469 if (overriddenType.typeFormals.length != typeFormals.length) { |
| 470 return null; |
439 } | 471 } |
| 472 overriddenType = overriddenType.instantiate(typeFormals); |
440 } | 473 } |
441 return true; | 474 return overriddenType; |
442 } | 475 } |
443 | 476 |
444 /** | 477 /** |
445 * Return `true` if the list of [elements] contains only getters. | 478 * Return [FunctionType]s of [overriddenElements] that override [element]. |
| 479 * Return the empty list, in case of type parameters inconsistency. |
446 */ | 480 */ |
447 bool _onlyGetters(List<ExecutableElement> elements) { | 481 List<FunctionType> _toOverriddenFunctionTypes( |
448 for (ExecutableElement element in elements) { | 482 ExecutableElement element, List<ExecutableElement> overriddenElements) { |
449 if (!(element is PropertyAccessorElement && element.isGetter)) { | 483 var overriddenTypes = <FunctionType>[]; |
450 return false; | 484 for (ExecutableElement overriddenElement in overriddenElements) { |
| 485 FunctionType overriddenType = |
| 486 _toOverriddenFunctionType(element, overriddenElement); |
| 487 if (overriddenType == null) { |
| 488 return const <FunctionType>[]; |
451 } | 489 } |
| 490 overriddenTypes.add(overriddenType); |
452 } | 491 } |
453 return true; | 492 return overriddenTypes; |
454 } | 493 } |
455 | 494 |
456 /** | 495 /** |
457 * If the given [element] is a non-synthetic getter or setter, update its | 496 * If the given [element] is a non-synthetic getter or setter, update its |
458 * synthetic variable's type to match the getter's return type, or if no | 497 * synthetic variable's type to match the getter's return type, or if no |
459 * corresponding getter exists, use the setter's parameter type. | 498 * corresponding getter exists, use the setter's parameter type. |
460 * | 499 * |
461 * In general, the type of the synthetic variable should not be used, because | 500 * In general, the type of the synthetic variable should not be used, because |
462 * getters and setters are independent methods. But this logic matches what | 501 * getters and setters are independent methods. But this logic matches what |
463 * `TypeResolverVisitor.visitMethodDeclaration` would fill in there. | 502 * `TypeResolverVisitor.visitMethodDeclaration` would fill in there. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 void visitSimpleIdentifier(SimpleIdentifier node) { | 547 void visitSimpleIdentifier(SimpleIdentifier node) { |
509 if (!node.inDeclarationContext()) { | 548 if (!node.inDeclarationContext()) { |
510 Element nonAccessor(Element element) { | 549 Element nonAccessor(Element element) { |
511 if (element is PropertyAccessorElement && element.isSynthetic) { | 550 if (element is PropertyAccessorElement && element.isSynthetic) { |
512 return element.variable; | 551 return element.variable; |
513 } | 552 } |
514 return element; | 553 return element; |
515 } | 554 } |
516 | 555 |
517 Element element = nonAccessor(node.staticElement); | 556 Element element = nonAccessor(node.staticElement); |
518 if (element is VariableElement) { | 557 if (element is VariableElement && (filter == null || filter(element))) { |
519 if (filter == null || filter(element)) { | 558 results.add(element); |
520 results.add(element); | |
521 } | |
522 } | 559 } |
523 } | 560 } |
524 } | 561 } |
525 } | 562 } |
526 | 563 |
527 /** | 564 /** |
528 * A class of exception that is not used anywhere else. | 565 * A class of exception that is not used anywhere else. |
529 */ | 566 */ |
530 class _CycleException implements Exception {} | 567 class _CycleException implements Exception {} |
531 | 568 |
532 /** | 569 /** |
| 570 * The result of field type inference. |
| 571 */ |
| 572 class _FieldOverrideInferenceResult { |
| 573 final bool isCovariant; |
| 574 final DartType type; |
| 575 final bool isError; |
| 576 |
| 577 _FieldOverrideInferenceResult(this.isCovariant, this.type, this.isError); |
| 578 } |
| 579 |
| 580 /** |
533 * The visitor for [isValidForTypeInference]. | 581 * The visitor for [isValidForTypeInference]. |
534 */ | 582 */ |
535 class _IsValidForTypeInferenceVisitor extends RecursiveAstVisitor { | 583 class _IsValidForTypeInferenceVisitor extends RecursiveAstVisitor { |
536 bool isValid = true; | 584 bool isValid = true; |
537 | 585 |
538 @override | 586 @override |
539 void visitAssignmentExpression(AssignmentExpression node) { | 587 void visitAssignmentExpression(AssignmentExpression node) { |
540 isValid = false; | 588 isValid = false; |
541 } | 589 } |
542 | 590 |
543 @override | 591 @override |
544 void visitCascadeExpression(CascadeExpression node) { | 592 void visitCascadeExpression(CascadeExpression node) { |
545 node.target.accept(this); | 593 node.target.accept(this); |
546 } | 594 } |
547 | 595 |
548 @override | 596 @override |
549 void visitSimpleIdentifier(SimpleIdentifier node) { | 597 void visitSimpleIdentifier(SimpleIdentifier node) { |
550 Element element = node.staticElement; | 598 Element element = node.staticElement; |
551 if (element == null) { | 599 if (element == null) { |
552 AstNode parent = node.parent; | 600 AstNode parent = node.parent; |
553 if (parent is PropertyAccess && parent.propertyName == node || | 601 if (parent is PropertyAccess && parent.propertyName == node || |
554 parent is PrefixedIdentifier && parent.identifier == node) { | 602 parent is PrefixedIdentifier && parent.identifier == node) { |
555 isValid = false; | 603 isValid = false; |
556 } | 604 } |
557 } else if (element is PropertyAccessorElement && !element.isStatic) { | 605 } else if (element is PropertyAccessorElement && !element.isStatic) { |
558 isValid = false; | 606 isValid = false; |
559 } | 607 } |
560 } | 608 } |
561 } | 609 } |
OLD | NEW |