| 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 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 /** | 35 /** |
| 36 * Sets the type of the field. The types in implicit accessors are updated | 36 * Sets the type of the field. The types in implicit accessors are updated |
| 37 * implicitly, and the types of explicit accessors should be updated separately. | 37 * implicitly, and the types of explicit accessors should be updated separately. |
| 38 */ | 38 */ |
| 39 void setFieldType(VariableElement field, DartType newType) { | 39 void setFieldType(VariableElement field, DartType newType) { |
| 40 (field as VariableElementImpl).type = newType; | 40 (field as VariableElementImpl).type = newType; |
| 41 } | 41 } |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * A function that return the [InheritanceManager] for the class [element]. |
| 45 */ |
| 46 typedef InheritanceManager InheritanceManagerProvider(ClassElement element); |
| 47 |
| 48 /** |
| 44 * A function that returns `true` if the given [element] passes the filter. | 49 * A function that returns `true` if the given [element] passes the filter. |
| 45 */ | 50 */ |
| 46 typedef bool VariableFilter(VariableElement element); | 51 typedef bool VariableFilter(VariableElement element); |
| 47 | 52 |
| 48 /** | 53 /** |
| 49 * An object used to infer the type of instance fields and the return types of | 54 * An object used to infer the type of instance fields and the return types of |
| 50 * instance methods within a single compilation unit. | 55 * instance methods within a single compilation unit. |
| 51 */ | 56 */ |
| 52 class InstanceMemberInferrer { | 57 class InstanceMemberInferrer { |
| 53 /** | 58 /** |
| 54 * The type provider used to look up types. | 59 * The type provider used to look up types. |
| 55 */ | 60 */ |
| 56 final TypeProvider typeProvider; | 61 final TypeProvider typeProvider; |
| 57 | 62 |
| 58 /** | 63 /** |
| 59 * The type system used to compute the least upper bound of types. | 64 * The type system used to compute the least upper bound of types. |
| 60 */ | 65 */ |
| 61 TypeSystem typeSystem; | 66 TypeSystem typeSystem; |
| 62 | 67 |
| 63 /** | 68 /** |
| 64 * The inheritance manager used to find overridden method. | 69 * The provider for inheritance managers used to find overridden method. |
| 65 */ | 70 */ |
| 66 final InheritanceManager inheritanceManager; | 71 final InheritanceManagerProvider inheritanceManagerProvider; |
| 67 | 72 |
| 68 /** | 73 /** |
| 69 * The set of fields for which type inference from initializer should be | 74 * The set of fields for which type inference from initializer should be |
| 70 * disabled, because their initializers are not immediately-evident | 75 * disabled, because their initializers are not immediately-evident |
| 71 * expressions. | 76 * expressions. |
| 72 */ | 77 */ |
| 73 final Set<FieldElement> fieldsWithDisabledInitializerInference; | 78 final Set<FieldElement> fieldsWithDisabledInitializerInference; |
| 74 | 79 |
| 75 /** | 80 /** |
| 76 * The classes that have been visited while attempting to infer the types of | 81 * The classes that have been visited while attempting to infer the types of |
| 77 * instance members of some base class. | 82 * instance members of some base class. |
| 78 */ | 83 */ |
| 79 HashSet<ClassElementImpl> elementsBeingInferred = | 84 HashSet<ClassElementImpl> elementsBeingInferred = |
| 80 new HashSet<ClassElementImpl>(); | 85 new HashSet<ClassElementImpl>(); |
| 81 | 86 |
| 82 /** | 87 /** |
| 83 * Initialize a newly create inferrer. | 88 * Initialize a newly create inferrer. |
| 84 */ | 89 */ |
| 85 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager, | 90 InstanceMemberInferrer( |
| 91 TypeProvider typeProvider, |
| 92 this.inheritanceManagerProvider, |
| 86 this.fieldsWithDisabledInitializerInference, | 93 this.fieldsWithDisabledInitializerInference, |
| 87 {TypeSystem typeSystem}) | 94 {TypeSystem typeSystem}) |
| 88 : typeSystem = (typeSystem != null) | 95 : typeSystem = (typeSystem != null) |
| 89 ? typeSystem | 96 ? typeSystem |
| 90 : new TypeSystemImpl(typeProvider), | 97 : new TypeSystemImpl(typeProvider), |
| 91 this.typeProvider = typeProvider; | 98 this.typeProvider = typeProvider; |
| 92 | 99 |
| 93 /** | 100 /** |
| 94 * Infer type information for all of the instance members in the given | 101 * Infer type information for all of the instance members in the given |
| 95 * compilation [unit]. | 102 * compilation [unit]. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 111 bool _allSameElementKind( | 118 bool _allSameElementKind( |
| 112 ExecutableElement element, List<ExecutableElement> elements) { | 119 ExecutableElement element, List<ExecutableElement> elements) { |
| 113 return elements.every((e) => e.kind == element.kind); | 120 return elements.every((e) => e.kind == element.kind); |
| 114 } | 121 } |
| 115 | 122 |
| 116 /** | 123 /** |
| 117 * Compute the inferred type for the given property [accessor]. The returned | 124 * Compute the inferred type for the given property [accessor]. The returned |
| 118 * value is never `null`, but might be an error, and/or have the `null` type. | 125 * value is never `null`, but might be an error, and/or have the `null` type. |
| 119 */ | 126 */ |
| 120 _FieldOverrideInferenceResult _computeFieldOverrideType( | 127 _FieldOverrideInferenceResult _computeFieldOverrideType( |
| 121 PropertyAccessorElement accessor) { | 128 InheritanceManager inheritanceManager, PropertyAccessorElement accessor) { |
| 122 String name = accessor.displayName; | 129 String name = accessor.displayName; |
| 123 | 130 |
| 124 var overriddenElements = <ExecutableElement>[]; | 131 var overriddenElements = <ExecutableElement>[]; |
| 125 overriddenElements.addAll( | 132 overriddenElements.addAll( |
| 126 inheritanceManager.lookupOverrides(accessor.enclosingElement, name)); | 133 inheritanceManager.lookupOverrides(accessor.enclosingElement, name)); |
| 127 if (overriddenElements.isEmpty || !accessor.variable.isFinal) { | 134 if (overriddenElements.isEmpty || !accessor.variable.isFinal) { |
| 128 List<ExecutableElement> overriddenSetters = inheritanceManager | 135 List<ExecutableElement> overriddenSetters = inheritanceManager |
| 129 .lookupOverrides(accessor.enclosingElement, '$name='); | 136 .lookupOverrides(accessor.enclosingElement, '$name='); |
| 130 overriddenElements.addAll(overriddenSetters); | 137 overriddenElements.addAll(overriddenSetters); |
| 131 } | 138 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 return matchingParameter; | 255 return matchingParameter; |
| 249 } | 256 } |
| 250 } | 257 } |
| 251 return null; | 258 return null; |
| 252 } | 259 } |
| 253 | 260 |
| 254 /** | 261 /** |
| 255 * If the given [element] represents a non-synthetic instance property | 262 * If the given [element] represents a non-synthetic instance property |
| 256 * accessor for which no type was provided, infer its types. | 263 * accessor for which no type was provided, infer its types. |
| 257 */ | 264 */ |
| 258 void _inferAccessor(PropertyAccessorElement element) { | 265 void _inferAccessor( |
| 266 InheritanceManager inheritanceManager, PropertyAccessorElement element) { |
| 259 if (element.isSynthetic || element.isStatic) { | 267 if (element.isSynthetic || element.isStatic) { |
| 260 return; | 268 return; |
| 261 } | 269 } |
| 262 | 270 |
| 263 if (element.kind == ElementKind.GETTER && !element.hasImplicitReturnType) { | 271 if (element.kind == ElementKind.GETTER && !element.hasImplicitReturnType) { |
| 264 return; | 272 return; |
| 265 } | 273 } |
| 266 | 274 |
| 267 _FieldOverrideInferenceResult typeResult = | 275 _FieldOverrideInferenceResult typeResult = |
| 268 _computeFieldOverrideType(element); | 276 _computeFieldOverrideType(inheritanceManager, element); |
| 269 if (typeResult.isError == null || typeResult.type == null) { | 277 if (typeResult.isError == null || typeResult.type == null) { |
| 270 return; | 278 return; |
| 271 } | 279 } |
| 272 | 280 |
| 273 if (element.kind == ElementKind.GETTER) { | 281 if (element.kind == ElementKind.GETTER) { |
| 274 (element as ExecutableElementImpl).returnType = typeResult.type; | 282 (element as ExecutableElementImpl).returnType = typeResult.type; |
| 275 } else if (element.kind == ElementKind.SETTER) { | 283 } else if (element.kind == ElementKind.SETTER) { |
| 276 List<ParameterElement> parameters = element.parameters; | 284 List<ParameterElement> parameters = element.parameters; |
| 277 if (parameters.isNotEmpty) { | 285 if (parameters.isNotEmpty) { |
| 278 var parameter = parameters[0] as ParameterElementImpl; | 286 var parameter = parameters[0] as ParameterElementImpl; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 296 } | 304 } |
| 297 if (!elementsBeingInferred.add(classElement)) { | 305 if (!elementsBeingInferred.add(classElement)) { |
| 298 // We have found a circularity in the class hierarchy. For now we just | 306 // We have found a circularity in the class hierarchy. For now we just |
| 299 // stop trying to infer any type information for any classes that | 307 // stop trying to infer any type information for any classes that |
| 300 // inherit from any class in the cycle. We could potentially limit the | 308 // inherit from any class in the cycle. We could potentially limit the |
| 301 // algorithm to only not inferring types in the classes in the cycle, | 309 // algorithm to only not inferring types in the classes in the cycle, |
| 302 // but it isn't clear that the results would be significantly better. | 310 // but it isn't clear that the results would be significantly better. |
| 303 throw new _CycleException(); | 311 throw new _CycleException(); |
| 304 } | 312 } |
| 305 try { | 313 try { |
| 314 InheritanceManager inheritanceManager = |
| 315 inheritanceManagerProvider(classElement); |
| 306 // | 316 // |
| 307 // Ensure that all of instance members in the supertypes have had types | 317 // Ensure that all of instance members in the supertypes have had types |
| 308 // inferred for them. | 318 // inferred for them. |
| 309 // | 319 // |
| 310 _inferType(classElement.supertype); | 320 _inferType(classElement.supertype); |
| 311 classElement.mixins.forEach(_inferType); | 321 classElement.mixins.forEach(_inferType); |
| 312 classElement.interfaces.forEach(_inferType); | 322 classElement.interfaces.forEach(_inferType); |
| 313 // | 323 // |
| 314 // Then infer the types for the members. | 324 // Then infer the types for the members. |
| 315 // | 325 // |
| 316 classElement.fields.forEach(_inferField); | 326 classElement.fields.forEach((field) { |
| 317 classElement.accessors.forEach(_inferAccessor); | 327 _inferField(inheritanceManager, field); |
| 318 classElement.methods.forEach(_inferExecutable); | 328 }); |
| 329 classElement.accessors.forEach((accessor) { |
| 330 _inferAccessor(inheritanceManager, accessor); |
| 331 }); |
| 332 classElement.methods.forEach((method) { |
| 333 _inferExecutable(inheritanceManager, method); |
| 334 }); |
| 319 // | 335 // |
| 320 // Infer initializing formal parameter types. This must happen after | 336 // Infer initializing formal parameter types. This must happen after |
| 321 // field types are inferred. | 337 // field types are inferred. |
| 322 // | 338 // |
| 323 classElement.constructors.forEach(_inferConstructorFieldFormals); | 339 classElement.constructors.forEach(_inferConstructorFieldFormals); |
| 324 classElement.hasBeenInferred = true; | 340 classElement.hasBeenInferred = true; |
| 325 } finally { | 341 } finally { |
| 326 elementsBeingInferred.remove(classElement); | 342 elementsBeingInferred.remove(classElement); |
| 327 } | 343 } |
| 328 } | 344 } |
| 329 } | 345 } |
| 330 | 346 |
| 331 void _inferConstructorFieldFormals(ConstructorElement constructor) { | 347 void _inferConstructorFieldFormals(ConstructorElement constructor) { |
| 332 for (ParameterElement parameter in constructor.parameters) { | 348 for (ParameterElement parameter in constructor.parameters) { |
| 333 if (parameter.hasImplicitType && | 349 if (parameter.hasImplicitType && |
| 334 parameter is FieldFormalParameterElementImpl) { | 350 parameter is FieldFormalParameterElementImpl) { |
| 335 FieldElement field = parameter.field; | 351 FieldElement field = parameter.field; |
| 336 if (field != null) { | 352 if (field != null) { |
| 337 parameter.type = field.type; | 353 parameter.type = field.type; |
| 338 } | 354 } |
| 339 } | 355 } |
| 340 } | 356 } |
| 341 } | 357 } |
| 342 | 358 |
| 343 /** | 359 /** |
| 344 * If the given [element] represents a non-synthetic instance method, | 360 * If the given [element] represents a non-synthetic instance method, |
| 345 * getter or setter, infer the return type and any parameter type(s) where | 361 * getter or setter, infer the return type and any parameter type(s) where |
| 346 * they were not provided. | 362 * they were not provided. |
| 347 */ | 363 */ |
| 348 void _inferExecutable(ExecutableElement element) { | 364 void _inferExecutable( |
| 365 InheritanceManager inheritanceManager, ExecutableElement element) { |
| 349 if (element.isSynthetic || element.isStatic) { | 366 if (element.isSynthetic || element.isStatic) { |
| 350 return; | 367 return; |
| 351 } | 368 } |
| 352 List<ExecutableElement> overriddenElements = inheritanceManager | 369 List<ExecutableElement> overriddenElements = inheritanceManager |
| 353 .lookupOverrides(element.enclosingElement, element.displayName); | 370 .lookupOverrides(element.enclosingElement, element.displayName); |
| 354 if (overriddenElements.isEmpty || | 371 if (overriddenElements.isEmpty || |
| 355 !_allSameElementKind(element, overriddenElements)) { | 372 !_allSameElementKind(element, overriddenElements)) { |
| 356 return; | 373 return; |
| 357 } | 374 } |
| 358 | 375 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 389 } | 406 } |
| 390 } | 407 } |
| 391 } | 408 } |
| 392 } | 409 } |
| 393 } | 410 } |
| 394 | 411 |
| 395 /** | 412 /** |
| 396 * If the given [field] represents a non-synthetic instance field for | 413 * If the given [field] represents a non-synthetic instance field for |
| 397 * which no type was provided, infer the type of the field. | 414 * which no type was provided, infer the type of the field. |
| 398 */ | 415 */ |
| 399 void _inferField(FieldElement field) { | 416 void _inferField(InheritanceManager inheritanceManager, FieldElement field) { |
| 400 if (field.isSynthetic || field.isStatic) { | 417 if (field.isSynthetic || field.isStatic) { |
| 401 return; | 418 return; |
| 402 } | 419 } |
| 403 | 420 |
| 404 _FieldOverrideInferenceResult typeResult = | 421 _FieldOverrideInferenceResult typeResult = |
| 405 _computeFieldOverrideType(field.getter); | 422 _computeFieldOverrideType(inheritanceManager, field.getter); |
| 406 if (typeResult.isError) { | 423 if (typeResult.isError) { |
| 407 if (field is FieldElementForLink_ClassField) { | 424 if (field is FieldElementForLink_ClassField) { |
| 408 field.setInferenceError(new TopLevelInferenceErrorBuilder( | 425 field.setInferenceError(new TopLevelInferenceErrorBuilder( |
| 409 kind: TopLevelInferenceErrorKind.overrideConflictFieldType)); | 426 kind: TopLevelInferenceErrorKind.overrideConflictFieldType)); |
| 410 } | 427 } |
| 411 return; | 428 return; |
| 412 } | 429 } |
| 413 | 430 |
| 414 if (field.hasImplicitType) { | 431 if (field.hasImplicitType) { |
| 415 DartType newType = typeResult.type; | 432 DartType newType = typeResult.type; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 AstNode parent = node.parent; | 691 AstNode parent = node.parent; |
| 675 if (parent is PropertyAccess && parent.propertyName == node || | 692 if (parent is PropertyAccess && parent.propertyName == node || |
| 676 parent is PrefixedIdentifier && parent.identifier == node) { | 693 parent is PrefixedIdentifier && parent.identifier == node) { |
| 677 isValid = false; | 694 isValid = false; |
| 678 } | 695 } |
| 679 } else if (element is PropertyAccessorElement && !element.isStatic) { | 696 } else if (element is PropertyAccessorElement && !element.isStatic) { |
| 680 isValid = false; | 697 isValid = false; |
| 681 } | 698 } |
| 682 } | 699 } |
| 683 } | 700 } |
| OLD | NEW |