| 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'; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/dart/element/type.dart'; | 12 import 'package:analyzer/dart/element/type.dart'; |
| 13 import 'package:analyzer/src/dart/element/element.dart'; | 13 import 'package:analyzer/src/dart/element/element.dart'; |
| 14 import 'package:analyzer/src/dart/element/type.dart'; | 14 import 'package:analyzer/src/dart/element/type.dart'; |
| 15 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 15 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 16 import 'package:analyzer/src/generated/resolver.dart' | 16 import 'package:analyzer/src/generated/resolver.dart' |
| 17 show TypeProvider, InheritanceManager; | 17 show TypeProvider, InheritanceManager; |
| 18 import 'package:analyzer/src/generated/type_system.dart'; | 18 import 'package:analyzer/src/generated/type_system.dart'; |
| 19 import 'package:analyzer/src/generated/utilities_dart.dart'; | 19 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 20 | 20 |
| 21 /** | 21 /** |
| 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. |
| 24 */ |
| 25 bool isValidForTypeInference(Expression expression) { |
| 26 var visitor = new _IsValidForTypeInferenceVisitor(); |
| 27 expression.accept(visitor); |
| 28 return visitor.isValid; |
| 29 } |
| 30 |
| 31 /** |
| 22 * Sets the type of the field. This is stored in the field itself, and the | 32 * Sets the type of the field. This is stored in the field itself, and the |
| 23 * synthetic getter/setter types. | 33 * synthetic getter/setter types. |
| 24 */ | 34 */ |
| 25 void setFieldType(VariableElement field, DartType newType) { | 35 void setFieldType(VariableElement field, DartType newType) { |
| 26 (field as VariableElementImpl).type = newType; | 36 (field as VariableElementImpl).type = newType; |
| 27 if (field.initializer != null) { | 37 if (field.initializer != null) { |
| 28 (field.initializer as ExecutableElementImpl).returnType = newType; | 38 (field.initializer as ExecutableElementImpl).returnType = newType; |
| 29 } | 39 } |
| 30 } | 40 } |
| 31 | 41 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 * The type system used to compute the least upper bound of types. | 73 * The type system used to compute the least upper bound of types. |
| 64 */ | 74 */ |
| 65 TypeSystem typeSystem; | 75 TypeSystem typeSystem; |
| 66 | 76 |
| 67 /** | 77 /** |
| 68 * The inheritance manager used to find overridden method. | 78 * The inheritance manager used to find overridden method. |
| 69 */ | 79 */ |
| 70 final InheritanceManager inheritanceManager; | 80 final InheritanceManager inheritanceManager; |
| 71 | 81 |
| 72 /** | 82 /** |
| 83 * The set of fields for which type inference from initializer should be |
| 84 * disabled, because their initializers are not immediately-evident |
| 85 * expressions. |
| 86 */ |
| 87 final Set<FieldElement> fieldsWithDisabledInitializerInference; |
| 88 |
| 89 /** |
| 73 * The classes that have been visited while attempting to infer the types of | 90 * The classes that have been visited while attempting to infer the types of |
| 74 * instance members of some base class. | 91 * instance members of some base class. |
| 75 */ | 92 */ |
| 76 HashSet<ClassElementImpl> elementsBeingInferred = | 93 HashSet<ClassElementImpl> elementsBeingInferred = |
| 77 new HashSet<ClassElementImpl>(); | 94 new HashSet<ClassElementImpl>(); |
| 78 | 95 |
| 79 /** | 96 /** |
| 80 * Initialize a newly create inferrer. | 97 * Initialize a newly create inferrer. |
| 81 */ | 98 */ |
| 82 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager, | 99 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager, |
| 100 this.fieldsWithDisabledInitializerInference, |
| 83 {TypeSystem typeSystem}) | 101 {TypeSystem typeSystem}) |
| 84 : typeSystem = (typeSystem != null) | 102 : typeSystem = (typeSystem != null) |
| 85 ? typeSystem | 103 ? typeSystem |
| 86 : new TypeSystemImpl(typeProvider), | 104 : new TypeSystemImpl(typeProvider), |
| 87 this.typeProvider = typeProvider; | 105 this.typeProvider = typeProvider; |
| 88 | 106 |
| 89 /** | 107 /** |
| 90 * Infer type information for all of the instance members in the given | 108 * Infer type information for all of the instance members in the given |
| 91 * compilation [unit]. | 109 * compilation [unit]. |
| 92 */ | 110 */ |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 // | 374 // |
| 357 // If there is no overridden getter or if the overridden getter's type is | 375 // If there is no overridden getter or if the overridden getter's type is |
| 358 // dynamic, then we can infer the type from the initialization expression | 376 // dynamic, then we can infer the type from the initialization expression |
| 359 // without breaking subtype rules. We could potentially infer a consistent | 377 // without breaking subtype rules. We could potentially infer a consistent |
| 360 // return type even if the overridden getter's type was not dynamic, but | 378 // return type even if the overridden getter's type was not dynamic, but |
| 361 // choose not to for simplicity. The field is required to be final to | 379 // choose not to for simplicity. The field is required to be final to |
| 362 // prevent choosing a type that is inconsistent with assignments we cannot | 380 // prevent choosing a type that is inconsistent with assignments we cannot |
| 363 // analyze. | 381 // analyze. |
| 364 // | 382 // |
| 365 if (newType == null || newType.isDynamic) { | 383 if (newType == null || newType.isDynamic) { |
| 366 if (fieldElement.initializer != null && | 384 FunctionElement initializer = fieldElement.initializer; |
| 385 if (initializer != null && |
| 367 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | 386 (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
| 368 newType = fieldElement.initializer.returnType; | 387 if (!fieldsWithDisabledInitializerInference.contains(fieldElement)) { |
| 388 newType = initializer.returnType; |
| 389 } |
| 369 } | 390 } |
| 370 } | 391 } |
| 371 if (newType == null || newType.isBottom || newType.isDartCoreNull) { | 392 if (newType == null || newType.isBottom || newType.isDartCoreNull) { |
| 372 newType = typeProvider.dynamicType; | 393 newType = typeProvider.dynamicType; |
| 373 } | 394 } |
| 374 setFieldType(fieldElement, newType); | 395 setFieldType(fieldElement, newType); |
| 375 } | 396 } |
| 376 } | 397 } |
| 377 | 398 |
| 378 void _inferFieldFormalParameter(FieldFormalParameterElementImpl element) { | 399 void _inferFieldFormalParameter(FieldFormalParameterElementImpl element) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 void visitSimpleIdentifier(SimpleIdentifier node) { | 508 void visitSimpleIdentifier(SimpleIdentifier node) { |
| 488 if (!node.inDeclarationContext()) { | 509 if (!node.inDeclarationContext()) { |
| 489 Element nonAccessor(Element element) { | 510 Element nonAccessor(Element element) { |
| 490 if (element is PropertyAccessorElement && element.isSynthetic) { | 511 if (element is PropertyAccessorElement && element.isSynthetic) { |
| 491 return element.variable; | 512 return element.variable; |
| 492 } | 513 } |
| 493 return element; | 514 return element; |
| 494 } | 515 } |
| 495 | 516 |
| 496 Element element = nonAccessor(node.staticElement); | 517 Element element = nonAccessor(node.staticElement); |
| 497 if (element is VariableElement && (filter == null || filter(element))) { | 518 if (element is VariableElement) { |
| 498 results.add(element); | 519 if (filter == null || filter(element)) { |
| 520 results.add(element); |
| 521 } |
| 499 } | 522 } |
| 500 } | 523 } |
| 501 } | 524 } |
| 502 } | 525 } |
| 503 | 526 |
| 504 /** | 527 /** |
| 505 * A class of exception that is not used anywhere else. | 528 * A class of exception that is not used anywhere else. |
| 506 */ | 529 */ |
| 507 class _CycleException implements Exception {} | 530 class _CycleException implements Exception {} |
| 531 |
| 532 /** |
| 533 * The visitor for [isValidForTypeInference]. |
| 534 */ |
| 535 class _IsValidForTypeInferenceVisitor extends RecursiveAstVisitor { |
| 536 bool isValid = true; |
| 537 |
| 538 @override |
| 539 void visitAssignmentExpression(AssignmentExpression node) { |
| 540 isValid = false; |
| 541 } |
| 542 |
| 543 @override |
| 544 void visitCascadeExpression(CascadeExpression node) { |
| 545 node.target.accept(this); |
| 546 } |
| 547 |
| 548 @override |
| 549 void visitSimpleIdentifier(SimpleIdentifier node) { |
| 550 Element element = node.staticElement; |
| 551 if (element == null) { |
| 552 AstNode parent = node.parent; |
| 553 if (parent is PropertyAccess && parent.propertyName == node || |
| 554 parent is PrefixedIdentifier && parent.identifier == node) { |
| 555 isValid = false; |
| 556 } |
| 557 } else if (element is PropertyAccessorElement && !element.isStatic) { |
| 558 isValid = false; |
| 559 } |
| 560 } |
| 561 } |
| OLD | NEW |