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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 299 } |
300 } | 300 } |
301 // | 301 // |
302 // Infer the parameter types. | 302 // Infer the parameter types. |
303 // | 303 // |
304 List<ParameterElement> parameters = element.parameters; | 304 List<ParameterElement> parameters = element.parameters; |
305 int length = parameters.length; | 305 int length = parameters.length; |
306 for (int i = 0; i < length; ++i) { | 306 for (int i = 0; i < length; ++i) { |
307 ParameterElement parameter = parameters[i]; | 307 ParameterElement parameter = parameters[i]; |
308 if (parameter is ParameterElementImpl) { | 308 if (parameter is ParameterElementImpl) { |
309 // If a parameter is covariant, any parameters that override it are too. | 309 _inferParameterCovariance(parameter, i, overriddenTypes); |
310 parameter.inheritsCovariant = overriddenTypes.any((f) { | |
311 var param = _getCorrespondingParameter(parameter, i, f.parameters); | |
312 return param != null && param.isCovariant; | |
313 }); | |
314 | 310 |
315 if (parameter.hasImplicitType) { | 311 if (parameter.hasImplicitType) { |
316 parameter.type = _computeParameterType(parameter, i, overriddenTypes); | 312 parameter.type = _computeParameterType(parameter, i, overriddenTypes); |
317 if (element is PropertyAccessorElement) { | 313 if (element is PropertyAccessorElement) { |
318 _updateSyntheticVariableType(element); | 314 _updateSyntheticVariableType(element); |
319 } | 315 } |
320 } | 316 } |
321 } | 317 } |
322 } | 318 } |
323 } | 319 } |
324 | 320 |
325 /** | 321 /** |
326 * If the given [fieldElement] represents a non-synthetic instance field for | 322 * If the given [fieldElement] represents a non-synthetic instance field for |
327 * which no type was provided, infer the type of the field. | 323 * which no type was provided, infer the type of the field. |
328 */ | 324 */ |
329 void _inferField(FieldElement fieldElement) { | 325 void _inferField(FieldElement fieldElement) { |
330 if (!fieldElement.isSynthetic && | 326 if (fieldElement.isSynthetic || fieldElement.isStatic) { |
331 !fieldElement.isStatic && | 327 return; |
332 fieldElement.hasImplicitType) { | 328 } |
| 329 List<ExecutableElement> overriddenSetters = |
| 330 inheritanceManager.lookupOverrides( |
| 331 fieldElement.enclosingElement, fieldElement.name + '='); |
| 332 var setter = fieldElement.setter; |
| 333 if (setter != null && overriddenSetters.isNotEmpty) { |
| 334 _inferParameterCovariance( |
| 335 setter.parameters[0], 0, overriddenSetters.map((s) => s.type)); |
| 336 } |
| 337 |
| 338 if (fieldElement.hasImplicitType) { |
333 // | 339 // |
334 // First look for overridden getters with the same name as the field. | 340 // First look for overridden getters with the same name as the field. |
335 // | 341 // |
336 List<ExecutableElement> overriddenGetters = inheritanceManager | 342 List<ExecutableElement> overriddenGetters = inheritanceManager |
337 .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); | 343 .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); |
338 DartType newType = null; | 344 DartType newType = null; |
339 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { | 345 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { |
340 newType = | 346 newType = |
341 _computeReturnType(overriddenGetters.map((e) => e.returnType)); | 347 _computeReturnType(overriddenGetters.map((e) => e.returnType)); |
342 List<ExecutableElement> overriddenSetters = | 348 |
343 inheritanceManager.lookupOverrides( | |
344 fieldElement.enclosingElement, fieldElement.name + '='); | |
345 if (!_isCompatible(newType, overriddenSetters)) { | 349 if (!_isCompatible(newType, overriddenSetters)) { |
346 newType = null; | 350 newType = null; |
347 } | 351 } |
348 } | 352 } |
349 // | 353 // |
350 // If there is no overridden getter or if the overridden getter's type is | 354 // If there is no overridden getter or if the overridden getter's type is |
351 // dynamic, then we can infer the type from the initialization expression | 355 // dynamic, then we can infer the type from the initialization expression |
352 // without breaking subtype rules. We could potentially infer a consistent | 356 // without breaking subtype rules. We could potentially infer a consistent |
353 // return type even if the overridden getter's type was not dynamic, but | 357 // return type even if the overridden getter's type was not dynamic, but |
354 // choose not to for simplicity. The field is required to be final to | 358 // choose not to for simplicity. The field is required to be final to |
(...skipping 14 matching lines...) Expand all Loading... |
369 } | 373 } |
370 | 374 |
371 void _inferFieldFormalParameter(FieldFormalParameterElement element) { | 375 void _inferFieldFormalParameter(FieldFormalParameterElement element) { |
372 FieldElement field = element.field; | 376 FieldElement field = element.field; |
373 if (field != null && element.hasImplicitType) { | 377 if (field != null && element.hasImplicitType) { |
374 (element as FieldFormalParameterElementImpl).type = field.type; | 378 (element as FieldFormalParameterElementImpl).type = field.type; |
375 } | 379 } |
376 } | 380 } |
377 | 381 |
378 /** | 382 /** |
| 383 * If a parameter is covariant, any parameters that override it are too. |
| 384 */ |
| 385 void _inferParameterCovariance(ParameterElementImpl parameter, int index, |
| 386 Iterable<FunctionType> overriddenTypes) { |
| 387 parameter.inheritsCovariant = overriddenTypes.any((f) { |
| 388 var param = _getCorrespondingParameter(parameter, index, f.parameters); |
| 389 return param != null && param.isCovariant; |
| 390 }); |
| 391 } |
| 392 |
| 393 /** |
379 * Infer type information for all of the instance members in the given | 394 * Infer type information for all of the instance members in the given |
380 * interface [type]. | 395 * interface [type]. |
381 */ | 396 */ |
382 void _inferType(InterfaceType type) { | 397 void _inferType(InterfaceType type) { |
383 if (type != null) { | 398 if (type != null) { |
384 ClassElement element = type.element; | 399 ClassElement element = type.element; |
385 if (element != null) { | 400 if (element != null) { |
386 _inferClass(element); | 401 _inferClass(element); |
387 } | 402 } |
388 } | 403 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 results.add(element); | 495 results.add(element); |
481 } | 496 } |
482 } | 497 } |
483 } | 498 } |
484 } | 499 } |
485 | 500 |
486 /** | 501 /** |
487 * A class of exception that is not used anywhere else. | 502 * A class of exception that is not used anywhere else. |
488 */ | 503 */ |
489 class _CycleException implements Exception {} | 504 class _CycleException implements Exception {} |
OLD | NEW |