| 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 * Sets the type of the field. This is stored in the field itself, and the | 22 * Sets the type of the field. This is stored in the field itself, and the |
| 23 * synthetic getter/setter types. | 23 * synthetic getter/setter types. |
| 24 */ | 24 */ |
| 25 void setFieldType(VariableElement field, DartType newType) { | 25 void setFieldType(VariableElement field, DartType newType) { |
| 26 (field as VariableElementImpl).type = newType; | 26 (field as VariableElementImpl).type = newType; |
| 27 if (field.initializer != null) { | 27 if (field.initializer != null) { |
| 28 (field.initializer as ExecutableElementImpl).returnType = newType; | 28 (field.initializer as ExecutableElementImpl).returnType = newType; |
| 29 } | 29 } |
| 30 } | 30 } |
| 31 | 31 |
| 32 bool hasInstanceGetterReference(Expression expression) { |
| 33 var visitor = new _InstanceGetterReferenceVisitor(); |
| 34 expression.accept(visitor); |
| 35 return visitor.hasInstanceFieldOrGetterReference; |
| 36 } |
| 37 |
| 32 /** | 38 /** |
| 33 * Return the element for the single parameter of the given [setter], or `null` | 39 * Return the element for the single parameter of the given [setter], or `null` |
| 34 * if the executable element is not a setter or does not have a single | 40 * if the executable element is not a setter or does not have a single |
| 35 * parameter. | 41 * parameter. |
| 36 */ | 42 */ |
| 37 ParameterElement _getParameter(ExecutableElement setter) { | 43 ParameterElement _getParameter(ExecutableElement setter) { |
| 38 if (setter is PropertyAccessorElement && setter.isSetter) { | 44 if (setter is PropertyAccessorElement && setter.isSetter) { |
| 39 List<ParameterElement> parameters = setter.parameters; | 45 List<ParameterElement> parameters = setter.parameters; |
| 40 if (parameters.length == 1) { | 46 if (parameters.length == 1) { |
| 41 return parameters[0]; | 47 return parameters[0]; |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 // | 362 // |
| 357 // If there is no overridden getter or if the overridden getter's type is | 363 // 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 | 364 // dynamic, then we can infer the type from the initialization expression |
| 359 // without breaking subtype rules. We could potentially infer a consistent | 365 // without breaking subtype rules. We could potentially infer a consistent |
| 360 // return type even if the overridden getter's type was not dynamic, but | 366 // 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 | 367 // 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 | 368 // prevent choosing a type that is inconsistent with assignments we cannot |
| 363 // analyze. | 369 // analyze. |
| 364 // | 370 // |
| 365 if (newType == null || newType.isDynamic) { | 371 if (newType == null || newType.isDynamic) { |
| 366 if (fieldElement.initializer != null && | 372 FunctionElement initializer = fieldElement.initializer; |
| 373 if (initializer != null && |
| 367 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | 374 (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
| 368 newType = fieldElement.initializer.returnType; | 375 newType = initializer.returnType; |
| 369 } | 376 } |
| 370 } | 377 } |
| 371 if (newType == null || newType.isBottom || newType.isDartCoreNull) { | 378 if (newType == null || newType.isBottom || newType.isDartCoreNull) { |
| 372 newType = typeProvider.dynamicType; | 379 newType = typeProvider.dynamicType; |
| 373 } | 380 } |
| 374 setFieldType(fieldElement, newType); | 381 setFieldType(fieldElement, newType); |
| 375 } | 382 } |
| 376 } | 383 } |
| 377 | 384 |
| 378 void _inferFieldFormalParameter(FieldFormalParameterElementImpl element) { | 385 void _inferFieldFormalParameter(FieldFormalParameterElementImpl element) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 * The filter used to limit which variables are gathered, or `null` if no | 477 * The filter used to limit which variables are gathered, or `null` if no |
| 471 * filtering is to be performed. | 478 * filtering is to be performed. |
| 472 */ | 479 */ |
| 473 final VariableFilter filter; | 480 final VariableFilter filter; |
| 474 | 481 |
| 475 /** | 482 /** |
| 476 * The variables that were found. | 483 * The variables that were found. |
| 477 */ | 484 */ |
| 478 final Set<VariableElement> results = new HashSet<VariableElement>(); | 485 final Set<VariableElement> results = new HashSet<VariableElement>(); |
| 479 | 486 |
| 487 bool hasInstanceFieldOrGetterReference = false; |
| 488 |
| 480 /** | 489 /** |
| 481 * Initialize a newly created gatherer to gather all of the variables that | 490 * Initialize a newly created gatherer to gather all of the variables that |
| 482 * pass the given [filter] (or all variables if no filter is provided). | 491 * pass the given [filter] (or all variables if no filter is provided). |
| 483 */ | 492 */ |
| 484 VariableGatherer([this.filter = null]); | 493 VariableGatherer([this.filter = null]); |
| 485 | 494 |
| 486 @override | 495 @override |
| 487 void visitSimpleIdentifier(SimpleIdentifier node) { | 496 void visitSimpleIdentifier(SimpleIdentifier node) { |
| 488 if (!node.inDeclarationContext()) { | 497 if (!node.inDeclarationContext()) { |
| 489 Element nonAccessor(Element element) { | 498 Element nonAccessor(Element element) { |
| 490 if (element is PropertyAccessorElement && element.isSynthetic) { | 499 if (element is PropertyAccessorElement && element.isSynthetic) { |
| 491 return element.variable; | 500 return element.variable; |
| 492 } | 501 } |
| 493 return element; | 502 return element; |
| 494 } | 503 } |
| 495 | 504 |
| 496 Element element = nonAccessor(node.staticElement); | 505 Element element = nonAccessor(node.staticElement); |
| 497 if (element is VariableElement && (filter == null || filter(element))) { | 506 |
| 498 results.add(element); | 507 // if (element == null) { |
| 508 // AstNode parent = node.parent; |
| 509 // if (parent is PropertyAccess && parent.propertyName == node || |
| 510 // parent is PrefixedIdentifier && parent.identifier == node) { |
| 511 // hasInstanceFieldOrGetterReference = true; |
| 512 // } |
| 513 // } else |
| 514 if (element is FieldElement && !element.isStatic || |
| 515 element is PropertyAccessorElement && !element.isStatic) { |
| 516 hasInstanceFieldOrGetterReference = true; |
| 517 } |
| 518 |
| 519 if (element is VariableElement) { |
| 520 if (filter == null || filter(element)) { |
| 521 results.add(element); |
| 522 } |
| 499 } | 523 } |
| 500 } | 524 } |
| 501 } | 525 } |
| 502 } | 526 } |
| 527 |
| 528 class _InstanceGetterReferenceVisitor extends RecursiveAstVisitor { |
| 529 bool hasInstanceFieldOrGetterReference = false; |
| 530 |
| 531 @override |
| 532 void visitSimpleIdentifier(SimpleIdentifier node) { |
| 533 Element element = node.staticElement; |
| 534 if (element == null) { |
| 535 AstNode parent = node.parent; |
| 536 if (parent is PropertyAccess && parent.propertyName == node || |
| 537 parent is PrefixedIdentifier && parent.identifier == node) { |
| 538 hasInstanceFieldOrGetterReference = true; |
| 539 } |
| 540 } else if (element is PropertyAccessorElement && !element.isStatic) { |
| 541 hasInstanceFieldOrGetterReference = true; |
| 542 } |
| 543 } |
| 544 } |
| 503 | 545 |
| 504 /** | 546 /** |
| 505 * A class of exception that is not used anywhere else. | 547 * A class of exception that is not used anywhere else. |
| 506 */ | 548 */ |
| 507 class _CycleException implements Exception {} | 549 class _CycleException implements Exception {} |
| OLD | NEW |