| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 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/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 5740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5751 } | 5751 } |
| 5752 | 5752 |
| 5753 /** | 5753 /** |
| 5754 * Prepares this [ResolverVisitor] to using it for incremental resolution. | 5754 * Prepares this [ResolverVisitor] to using it for incremental resolution. |
| 5755 */ | 5755 */ |
| 5756 void initForIncrementalResolution() { | 5756 void initForIncrementalResolution() { |
| 5757 _overrideManager.enterScope(); | 5757 _overrideManager.enterScope(); |
| 5758 } | 5758 } |
| 5759 | 5759 |
| 5760 /** | 5760 /** |
| 5761 * Returns true if this method is `Future.then`. |
| 5762 * |
| 5763 * If so we will apply special typing rules in strong mode, to handle the |
| 5764 * implicit union of `S | Future<S>` |
| 5765 */ |
| 5766 bool isFutureThen(Element element) { |
| 5767 return element is MethodElement && |
| 5768 element.name == 'then' && |
| 5769 element.enclosingElement.type.isDartAsyncFuture; |
| 5770 } |
| 5771 |
| 5772 /** |
| 5761 * Given a downward inference type [fnType], and the declared | 5773 * Given a downward inference type [fnType], and the declared |
| 5762 * [typeParameterList] for a function expression, determines if we can enable | 5774 * [typeParameterList] for a function expression, determines if we can enable |
| 5763 * downward inference and if so, returns the function type to use for | 5775 * downward inference and if so, returns the function type to use for |
| 5764 * inference. | 5776 * inference. |
| 5765 * | 5777 * |
| 5766 * This will return null if inference is not possible. This happens when | 5778 * This will return null if inference is not possible. This happens when |
| 5767 * there is no way we can find a subtype of the function type, given the | 5779 * there is no way we can find a subtype of the function type, given the |
| 5768 * provided type parameter list. | 5780 * provided type parameter list. |
| 5769 */ | 5781 */ |
| 5770 FunctionType matchFunctionTypeParameters( | 5782 FunctionType matchFunctionTypeParameters( |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6576 _overrideManager.enterScope(); | 6588 _overrideManager.enterScope(); |
| 6577 try { | 6589 try { |
| 6578 DartType functionType = InferenceContext.getType(node); | 6590 DartType functionType = InferenceContext.getType(node); |
| 6579 if (functionType is FunctionType) { | 6591 if (functionType is FunctionType) { |
| 6580 functionType = | 6592 functionType = |
| 6581 matchFunctionTypeParameters(node.typeParameters, functionType); | 6593 matchFunctionTypeParameters(node.typeParameters, functionType); |
| 6582 if (functionType is FunctionType) { | 6594 if (functionType is FunctionType) { |
| 6583 _inferFormalParameterList(node.parameters, functionType); | 6595 _inferFormalParameterList(node.parameters, functionType); |
| 6584 | 6596 |
| 6585 DartType returnType; | 6597 DartType returnType; |
| 6586 if (_isFutureThenLambda(node)) { | 6598 if (isFutureThen(node.staticParameterElement?.enclosingElement)) { |
| 6587 var futureThenType = | 6599 var futureThenType = |
| 6588 InferenceContext.getContext(node.parent) as FunctionType; | 6600 InferenceContext.getContext(node.parent) as FunctionType; |
| 6589 | 6601 |
| 6590 // Pretend the return type of Future<T>.then<S> first parameter is | 6602 // Pretend the return type of Future<T>.then<S> first parameter is |
| 6591 // | 6603 // |
| 6592 // T -> (S | Future<S>) | 6604 // T -> (S | Future<S>) |
| 6593 // | 6605 // |
| 6594 // We can't represent this in Dart so we populate it here during | 6606 // We can't represent this in Dart so we populate it here during |
| 6595 // inference. | 6607 // inference. |
| 6596 returnType = FutureUnionType.from( | 6608 returnType = FutureUnionType.from( |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7387 // | 7399 // |
| 7388 // Unsound to assume that [x = "hello";] never executed after the | 7400 // Unsound to assume that [x = "hello";] never executed after the |
| 7389 // if-statement. Of course, a dead-code analysis could point out that | 7401 // if-statement. Of course, a dead-code analysis could point out that |
| 7390 // [return] here is dead. | 7402 // [return] here is dead. |
| 7391 return _isAbruptTerminationStatement(statements[size - 1]); | 7403 return _isAbruptTerminationStatement(statements[size - 1]); |
| 7392 } | 7404 } |
| 7393 return false; | 7405 return false; |
| 7394 } | 7406 } |
| 7395 | 7407 |
| 7396 /** | 7408 /** |
| 7397 * Returns true if this expression is being passed to `Future.then`. | |
| 7398 * | |
| 7399 * If so we will apply special typing rules in strong mode, to handle the | |
| 7400 * implicit union of `S | Future<S>` | |
| 7401 */ | |
| 7402 bool _isFutureThenLambda(FunctionExpression node) { | |
| 7403 Element element = node.staticParameterElement?.enclosingElement; | |
| 7404 return element is MethodElement && | |
| 7405 element.name == 'then' && | |
| 7406 element.enclosingElement.type.isDartAsyncFuture; | |
| 7407 } | |
| 7408 | |
| 7409 /** | |
| 7410 * Return `true` if the given variable is accessed within a closure in the giv
en | 7409 * Return `true` if the given variable is accessed within a closure in the giv
en |
| 7411 * [AstNode] and also mutated somewhere in variable scope. This information is
only | 7410 * [AstNode] and also mutated somewhere in variable scope. This information is
only |
| 7412 * available for local variables (including parameters). | 7411 * available for local variables (including parameters). |
| 7413 * | 7412 * |
| 7414 * @param variable the variable to check | 7413 * @param variable the variable to check |
| 7415 * @param target the [AstNode] to check within | 7414 * @param target the [AstNode] to check within |
| 7416 * @return `true` if this variable is potentially mutated somewhere in the giv
en ASTNode | 7415 * @return `true` if this variable is potentially mutated somewhere in the giv
en ASTNode |
| 7417 */ | 7416 */ |
| 7418 bool _isVariableAccessedInClosure(Element variable, AstNode target) { | 7417 bool _isVariableAccessedInClosure(Element variable, AstNode target) { |
| 7419 _ResolverVisitor_isVariableAccessedInClosure visitor = | 7418 _ResolverVisitor_isVariableAccessedInClosure visitor = |
| (...skipping 3685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11105 return null; | 11104 return null; |
| 11106 } | 11105 } |
| 11107 if (identical(node.staticElement, variable)) { | 11106 if (identical(node.staticElement, variable)) { |
| 11108 if (node.inSetterContext()) { | 11107 if (node.inSetterContext()) { |
| 11109 result = true; | 11108 result = true; |
| 11110 } | 11109 } |
| 11111 } | 11110 } |
| 11112 return null; | 11111 return null; |
| 11113 } | 11112 } |
| 11114 } | 11113 } |
| OLD | NEW |