Chromium Code Reviews| 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 4671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4682 * of all return statements in a lambda. | 4682 * of all return statements in a lambda. |
| 4683 * | 4683 * |
| 4684 * This will always be kept in sync with [_returnStack]. | 4684 * This will always be kept in sync with [_returnStack]. |
| 4685 */ | 4685 */ |
| 4686 final List<DartType> _inferredReturn = <DartType>[]; | 4686 final List<DartType> _inferredReturn = <DartType>[]; |
| 4687 | 4687 |
| 4688 /** | 4688 /** |
| 4689 * A stack of return types for all of the enclosing | 4689 * A stack of return types for all of the enclosing |
| 4690 * functions and methods. | 4690 * functions and methods. |
| 4691 */ | 4691 */ |
| 4692 // TODO(leafp) Handle the implicit union type for Futures | |
| 4693 // https://github.com/dart-lang/sdk/issues/25322 | |
| 4694 final List<DartType> _returnStack = <DartType>[]; | 4692 final List<DartType> _returnStack = <DartType>[]; |
| 4695 | 4693 |
| 4696 InferenceContext._(this._errorReporter, TypeProvider typeProvider, | 4694 InferenceContext._(this._errorReporter, TypeProvider typeProvider, |
| 4697 this._typeSystem, this._inferenceHints) | 4695 this._typeSystem, this._inferenceHints) |
| 4698 : _typeProvider = typeProvider; | 4696 : _typeProvider = typeProvider; |
| 4699 | 4697 |
| 4700 /** | 4698 /** |
| 4701 * Get the return type of the current enclosing function, if any. | 4699 * Get the return type of the current enclosing function, if any. |
| 4702 * | 4700 * |
| 4703 * The type returned for a function is the type that is expected | 4701 * The type returned for a function is the type that is expected |
| 4704 * to be used in a return or yield context. For ordinary functions | 4702 * to be used in a return or yield context. For ordinary functions |
| 4705 * this is the same as the return type of the function. For async | 4703 * this is the same as the return type of the function. For async |
| 4706 * functions returning Future<T> and for generator functions | 4704 * functions returning Future<T> and for generator functions |
| 4707 * returning Stream<T> or Iterable<T>, this is T. | 4705 * returning Stream<T> or Iterable<T>, this is T. |
| 4708 */ | 4706 */ |
| 4709 DartType get returnContext => | 4707 DartType get returnContext => |
| 4710 _returnStack.isNotEmpty ? _returnStack.last : null; | 4708 _returnStack.isNotEmpty ? _returnStack.last : null; |
| 4711 | 4709 |
| 4712 /** | 4710 /** |
| 4713 * Records the type of the expression of a return statement. | 4711 * Records the type of the expression of a return statement. |
| 4714 * | 4712 * |
| 4715 * This will be used for inferring a block bodied lambda, if no context | 4713 * This will be used for inferring a block bodied lambda, if no context |
| 4716 * type was available. | 4714 * type was available. |
| 4717 */ | 4715 */ |
| 4718 void addReturnOrYieldType(DartType type) { | 4716 void addReturnOrYieldType(DartType type) { |
| 4719 if (_returnStack.isEmpty) { | 4717 if (_returnStack.isEmpty) { |
| 4720 return; | 4718 return; |
| 4721 } | 4719 } |
| 4722 DartType context = _returnStack.last; | 4720 DartType context = _returnStack.last; |
| 4723 if (context == null || context.isDynamic) { | 4721 if (context == null || context is DartType && context.isDynamic) { |
|
vsm
2016/08/09 20:29:33
Why "context is DartType"? That's the static type
Jennifer Messerly
2016/08/09 20:56:57
Good catch. Holdover from the earlier design when
| |
| 4724 DartType inferred = _inferredReturn.last; | 4722 DartType inferred = _inferredReturn.last; |
| 4725 inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred); | 4723 inferred = _typeSystem.getLeastUpperBound(_typeProvider, inferred, type); |
|
vsm
2016/08/09 20:29:33
Does the order actually matter?
Jennifer Messerly
2016/08/09 20:56:57
no. it got swapped because I had removed and recon
| |
| 4726 _inferredReturn[_inferredReturn.length - 1] = inferred; | 4724 _inferredReturn[_inferredReturn.length - 1] = inferred; |
| 4727 } | 4725 } |
| 4728 } | 4726 } |
| 4729 | 4727 |
| 4730 /** | 4728 /** |
| 4731 * Match type [t1] against type [t2] as follows. | 4729 * Match type [t1] against type [t2] as follows. |
| 4732 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype | 4730 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype |
| 4733 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` | 4731 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` |
| 4734 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` | 4732 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` |
| 4735 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, | 4733 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 4755 if (!inferred.isBottom) { | 4753 if (!inferred.isBottom) { |
| 4756 setType(node, inferred); | 4754 setType(node, inferred); |
| 4757 } | 4755 } |
| 4758 } | 4756 } |
| 4759 } | 4757 } |
| 4760 | 4758 |
| 4761 /** | 4759 /** |
| 4762 * Push a block function body's return type onto the return stack. | 4760 * Push a block function body's return type onto the return stack. |
| 4763 */ | 4761 */ |
| 4764 void pushReturnContext(BlockFunctionBody node) { | 4762 void pushReturnContext(BlockFunctionBody node) { |
| 4765 DartType returnType = getType(node); | 4763 _returnStack.add(getContext(node)); |
| 4766 _returnStack.add(returnType); | |
| 4767 _inferredReturn.add(BottomTypeImpl.instance); | 4764 _inferredReturn.add(BottomTypeImpl.instance); |
| 4768 } | 4765 } |
| 4769 | 4766 |
| 4770 /** | 4767 /** |
| 4771 * Place an info node into the error stream indicating that a | 4768 * Place an info node into the error stream indicating that a |
| 4772 * [type] has been inferred as the type of [node]. | 4769 * [type] has been inferred as the type of [node]. |
| 4773 */ | 4770 */ |
| 4774 void recordInference(Expression node, DartType type) { | 4771 void recordInference(Expression node, DartType type) { |
| 4775 if (!_inferenceHints) { | 4772 if (!_inferenceHints) { |
| 4776 return; | 4773 return; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4898 } | 4895 } |
| 4899 | 4896 |
| 4900 /** | 4897 /** |
| 4901 * Clear the type information assocated with [node]. | 4898 * Clear the type information assocated with [node]. |
| 4902 */ | 4899 */ |
| 4903 static void clearType(AstNode node) { | 4900 static void clearType(AstNode node) { |
| 4904 node?.setProperty(_typeProperty, null); | 4901 node?.setProperty(_typeProperty, null); |
| 4905 } | 4902 } |
| 4906 | 4903 |
| 4907 /** | 4904 /** |
| 4905 * Look for a single contextual type attached to [node], and returns the type | |
| 4906 * if found, otherwise null. | |
| 4907 * | |
| 4908 * If [node] has a contextual union type like `T | Future<T>` this will | |
| 4909 * simplify it to only return `T`. If the caller can handle a union type, | |
| 4910 * [getContext] should be used instead. | |
| 4911 */ | |
| 4912 static DartType getType(AstNode node) { | |
| 4913 DartType t = getContext(node); | |
| 4914 if (t is FutureUnionType) { | |
| 4915 return t.type; | |
| 4916 } | |
| 4917 return t; | |
| 4918 } | |
| 4919 | |
| 4920 /** | |
| 4908 * Look for contextual type information attached to [node]. Returns | 4921 * Look for contextual type information attached to [node]. Returns |
| 4909 * the type if found, otherwise null. | 4922 * the type if found, otherwise null. |
| 4923 * | |
| 4924 * If [node] has a contextual union type like `T | Future<T>` this will be | |
| 4925 * returned. You can use [getType] if you prefer to only get the `T`. | |
| 4910 */ | 4926 */ |
| 4911 static DartType getType(AstNode node) => node?.getProperty(_typeProperty); | 4927 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); |
| 4928 | |
| 4929 /** | |
| 4930 * Like [getContext] but expands a union type into a list of types. | |
| 4931 */ | |
| 4932 static Iterable<DartType> getTypes(AstNode node) { | |
| 4933 DartType t = getContext(node); | |
| 4934 if (t == null) { | |
| 4935 return DartType.EMPTY_LIST; | |
| 4936 } | |
| 4937 if (t is FutureUnionType) { | |
| 4938 return t.types; | |
| 4939 } | |
| 4940 return <DartType>[t]; | |
| 4941 } | |
| 4912 | 4942 |
| 4913 /** | 4943 /** |
| 4914 * Attach contextual type information [type] to [node] for use during | 4944 * Attach contextual type information [type] to [node] for use during |
| 4915 * inference. | 4945 * inference. |
| 4916 */ | 4946 */ |
| 4917 static void setType(AstNode node, DartType type) { | 4947 static void setType(AstNode node, DartType type) { |
| 4918 // TODO(jmesserly): this sets the type even when it's dynamic. | |
| 4919 // Can we skip that? | |
| 4920 node?.setProperty(_typeProperty, type); | 4948 node?.setProperty(_typeProperty, type); |
| 4921 } | 4949 } |
| 4922 | 4950 |
| 4923 /** | 4951 /** |
| 4924 * Attach contextual type information [type] to [node] for use during | 4952 * Attach contextual type information [type] to [node] for use during |
| 4925 * inference. | 4953 * inference. |
| 4926 */ | 4954 */ |
| 4927 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) { | 4955 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) { |
| 4928 setType(innerNode, getType(outerNode)); | 4956 setType(innerNode, getContext(outerNode)); |
| 4929 } | 4957 } |
| 4930 } | 4958 } |
| 4931 | 4959 |
| 4932 /** | 4960 /** |
| 4933 * This enum holds one of four states of a field initialization state through a constructor | 4961 * This enum holds one of four states of a field initialization state through a constructor |
| 4934 * signature, not initialized, initialized in the field declaration, initialized in the field | 4962 * signature, not initialized, initialized in the field declaration, initialized in the field |
| 4935 * formal, and finally, initialized in the initializers list. | 4963 * formal, and finally, initialized in the initializers list. |
| 4936 */ | 4964 */ |
| 4937 class INIT_STATE extends Enum<INIT_STATE> { | 4965 class INIT_STATE extends Enum<INIT_STATE> { |
| 4938 static const INIT_STATE NOT_INIT = const INIT_STATE('NOT_INIT', 0); | 4966 static const INIT_STATE NOT_INIT = const INIT_STATE('NOT_INIT', 0); |
| (...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6002 node.rightHandSide, node.leftHandSide.staticType); | 6030 node.rightHandSide, node.leftHandSide.staticType); |
| 6003 } | 6031 } |
| 6004 node.rightHandSide?.accept(this); | 6032 node.rightHandSide?.accept(this); |
| 6005 node.accept(elementResolver); | 6033 node.accept(elementResolver); |
| 6006 node.accept(typeAnalyzer); | 6034 node.accept(typeAnalyzer); |
| 6007 return null; | 6035 return null; |
| 6008 } | 6036 } |
| 6009 | 6037 |
| 6010 @override | 6038 @override |
| 6011 Object visitAwaitExpression(AwaitExpression node) { | 6039 Object visitAwaitExpression(AwaitExpression node) { |
| 6012 // TODO(leafp): Handle the implicit union type here | 6040 DartType contextType = InferenceContext.getContext(node); |
| 6013 // https://github.com/dart-lang/sdk/issues/25322 | |
| 6014 DartType contextType = InferenceContext.getType(node); | |
| 6015 if (contextType != null) { | 6041 if (contextType != null) { |
| 6016 InterfaceType futureT = typeProvider.futureType | 6042 var futureUnion = |
| 6017 .instantiate([contextType.flattenFutures(typeSystem)]); | 6043 FutureUnionType.from(contextType, typeProvider, typeSystem); |
| 6018 InferenceContext.setType(node.expression, futureT); | 6044 InferenceContext.setType(node.expression, futureUnion); |
| 6019 } | 6045 } |
| 6020 return super.visitAwaitExpression(node); | 6046 return super.visitAwaitExpression(node); |
| 6021 } | 6047 } |
| 6022 | 6048 |
| 6023 @override | 6049 @override |
| 6024 Object visitBinaryExpression(BinaryExpression node) { | 6050 Object visitBinaryExpression(BinaryExpression node) { |
| 6025 TokenType operatorType = node.operator.type; | 6051 TokenType operatorType = node.operator.type; |
| 6026 Expression leftOperand = node.leftOperand; | 6052 Expression leftOperand = node.leftOperand; |
| 6027 Expression rightOperand = node.rightOperand; | 6053 Expression rightOperand = node.rightOperand; |
| 6028 if (operatorType == TokenType.AMPERSAND_AMPERSAND) { | 6054 if (operatorType == TokenType.AMPERSAND_AMPERSAND) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6062 } else { | 6088 } else { |
| 6063 // TODO(leafp): Do downwards inference using the declared type | 6089 // TODO(leafp): Do downwards inference using the declared type |
| 6064 // of the binary operator for other cases. | 6090 // of the binary operator for other cases. |
| 6065 if (operatorType == TokenType.QUESTION_QUESTION) { | 6091 if (operatorType == TokenType.QUESTION_QUESTION) { |
| 6066 InferenceContext.setTypeFromNode(leftOperand, node); | 6092 InferenceContext.setTypeFromNode(leftOperand, node); |
| 6067 } | 6093 } |
| 6068 leftOperand?.accept(this); | 6094 leftOperand?.accept(this); |
| 6069 if (operatorType == TokenType.QUESTION_QUESTION) { | 6095 if (operatorType == TokenType.QUESTION_QUESTION) { |
| 6070 // Set the right side, either from the context, or using the information | 6096 // Set the right side, either from the context, or using the information |
| 6071 // from the left side if it is more precise. | 6097 // from the left side if it is more precise. |
| 6072 DartType contextType = InferenceContext.getType(node); | 6098 DartType contextType = InferenceContext.getContext(node); |
| 6073 DartType leftType = leftOperand?.staticType; | 6099 DartType leftType = leftOperand?.staticType; |
| 6074 if (contextType == null || contextType.isDynamic) { | 6100 if (contextType == null || contextType.isDynamic) { |
| 6075 contextType = leftType; | 6101 contextType = leftType; |
| 6076 } | 6102 } |
| 6077 InferenceContext.setType(rightOperand, contextType); | 6103 InferenceContext.setType(rightOperand, contextType); |
| 6078 } | 6104 } |
| 6079 rightOperand?.accept(this); | 6105 rightOperand?.accept(this); |
| 6080 } | 6106 } |
| 6081 node.accept(elementResolver); | 6107 node.accept(elementResolver); |
| 6082 node.accept(typeAnalyzer); | 6108 node.accept(typeAnalyzer); |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6540 _currentFunctionBody = node.body; | 6566 _currentFunctionBody = node.body; |
| 6541 _enclosingFunction = node.element; | 6567 _enclosingFunction = node.element; |
| 6542 _overrideManager.enterScope(); | 6568 _overrideManager.enterScope(); |
| 6543 try { | 6569 try { |
| 6544 DartType functionType = InferenceContext.getType(node); | 6570 DartType functionType = InferenceContext.getType(node); |
| 6545 if (functionType is FunctionType) { | 6571 if (functionType is FunctionType) { |
| 6546 functionType = | 6572 functionType = |
| 6547 matchFunctionTypeParameters(node.typeParameters, functionType); | 6573 matchFunctionTypeParameters(node.typeParameters, functionType); |
| 6548 if (functionType is FunctionType) { | 6574 if (functionType is FunctionType) { |
| 6549 _inferFormalParameterList(node.parameters, functionType); | 6575 _inferFormalParameterList(node.parameters, functionType); |
| 6550 DartType returnType = | 6576 |
| 6551 _computeReturnOrYieldType(functionType.returnType); | 6577 DartType returnType; |
| 6578 if (_isFutureThenLambda(node)) { | |
| 6579 var futureThenType = | |
| 6580 InferenceContext.getContext(node.parent) as FunctionType; | |
| 6581 | |
| 6582 // Pretend the return type of Future<T>.then<S> first parameter is | |
| 6583 // | |
| 6584 // T -> (S | Future<S>) | |
| 6585 // | |
| 6586 // We can't represent this in Dart so we populate it here during | |
| 6587 // inference. | |
| 6588 returnType = FutureUnionType.from( | |
| 6589 futureThenType.returnType, typeProvider, typeSystem); | |
| 6590 } else { | |
| 6591 returnType = _computeReturnOrYieldType(functionType.returnType); | |
| 6592 } | |
| 6593 | |
| 6552 InferenceContext.setType(node.body, returnType); | 6594 InferenceContext.setType(node.body, returnType); |
| 6553 } | 6595 } |
| 6554 } | 6596 } |
| 6555 super.visitFunctionExpression(node); | 6597 super.visitFunctionExpression(node); |
| 6556 } finally { | 6598 } finally { |
| 6557 _overrideManager.exitScope(); | 6599 _overrideManager.exitScope(); |
| 6558 } | 6600 } |
| 6559 } finally { | 6601 } finally { |
| 6560 _currentFunctionBody = outerFunctionBody; | 6602 _currentFunctionBody = outerFunctionBody; |
| 6561 _enclosingFunction = outerFunction; | 6603 _enclosingFunction = outerFunction; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6657 perBranchOverrides.add(elseOverrides); | 6699 perBranchOverrides.add(elseOverrides); |
| 6658 _overrideManager.mergeOverrides(perBranchOverrides); | 6700 _overrideManager.mergeOverrides(perBranchOverrides); |
| 6659 } | 6701 } |
| 6660 return null; | 6702 return null; |
| 6661 } | 6703 } |
| 6662 | 6704 |
| 6663 @override | 6705 @override |
| 6664 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 6706 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 6665 TypeName classTypeName = node.constructorName.type; | 6707 TypeName classTypeName = node.constructorName.type; |
| 6666 if (classTypeName.typeArguments == null) { | 6708 if (classTypeName.typeArguments == null) { |
| 6667 DartType contextType = InferenceContext.getType(node); | 6709 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first |
| 6668 if (contextType is InterfaceType && | 6710 // valid instantiation `new C<Ti>`, if it exists. |
| 6669 contextType.typeArguments != null && | 6711 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` |
| 6670 contextType.typeArguments.length > 0) { | 6712 // will become a valid possibility. Right now the only allowed union is |
| 6671 // TODO(jmesserly): for generic methods we use the | 6713 // `T | Future<T>` so we can take a simple approach. |
| 6672 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to | 6714 for (var contextType in InferenceContext.getTypes(node)) { |
| 6673 // be a tad more powerful than matchTypes. | 6715 if (contextType is InterfaceType && |
| 6674 // | 6716 contextType.typeArguments != null && |
| 6675 // For example it can infer this case: | 6717 contextType.typeArguments.isNotEmpty) { |
| 6676 // | 6718 // TODO(jmesserly): for generic methods we use the |
| 6677 // class E<S, T> extends A<C<S>, T> { ... } | 6719 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to |
| 6678 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); | 6720 // be a tad more powerful than matchTypes. |
| 6679 // | 6721 // |
| 6680 // See _inferArgumentTypesFromContext in this file for use of it. | 6722 // For example it can infer this case: |
| 6681 List<DartType> targs = | 6723 // |
| 6682 inferenceContext.matchTypes(classTypeName.type, contextType); | 6724 // class E<S, T> extends A<C<S>, T> { ... } |
| 6683 if (targs != null && targs.any((t) => !t.isDynamic)) { | 6725 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); |
| 6684 ClassElement classElement = classTypeName.type.element; | 6726 // |
| 6685 InterfaceType rawType = classElement.type; | 6727 // See _inferArgumentTypesFromContext in this file for use of it. |
| 6686 InterfaceType fullType = | 6728 List<DartType> targs = |
| 6687 rawType.substitute2(targs, rawType.typeArguments); | 6729 inferenceContext.matchTypes(classTypeName.type, contextType); |
| 6688 // The element resolver uses the type on the constructor name, so | 6730 if (targs != null && targs.any((t) => !t.isDynamic)) { |
| 6689 // infer it first | 6731 ClassElement classElement = classTypeName.type.element; |
| 6690 typeAnalyzer.inferConstructorName(node.constructorName, fullType); | 6732 InterfaceType rawType = classElement.type; |
| 6733 InterfaceType fullType = | |
| 6734 rawType.substitute2(targs, rawType.typeArguments); | |
| 6735 // The element resolver uses the type on the constructor name, so | |
| 6736 // infer it first | |
| 6737 typeAnalyzer.inferConstructorName(node.constructorName, fullType); | |
| 6738 break; | |
| 6739 } | |
| 6691 } | 6740 } |
| 6692 } | 6741 } |
| 6693 } | 6742 } |
| 6694 node.constructorName?.accept(this); | 6743 node.constructorName?.accept(this); |
| 6695 FunctionType constructorType = node.constructorName.staticElement?.type; | 6744 FunctionType constructorType = node.constructorName.staticElement?.type; |
| 6696 if (constructorType != null) { | 6745 if (constructorType != null) { |
| 6697 InferenceContext.setType(node.argumentList, constructorType); | 6746 InferenceContext.setType(node.argumentList, constructorType); |
| 6698 } | 6747 } |
| 6699 node.argumentList?.accept(this); | 6748 node.argumentList?.accept(this); |
| 6700 node.accept(elementResolver); | 6749 node.accept(elementResolver); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6794 node.typeArguments?.accept(this); | 6843 node.typeArguments?.accept(this); |
| 6795 node.accept(elementResolver); | 6844 node.accept(elementResolver); |
| 6796 _inferArgumentTypesFromContext(node); | 6845 _inferArgumentTypesFromContext(node); |
| 6797 node.argumentList?.accept(this); | 6846 node.argumentList?.accept(this); |
| 6798 node.accept(typeAnalyzer); | 6847 node.accept(typeAnalyzer); |
| 6799 return null; | 6848 return null; |
| 6800 } | 6849 } |
| 6801 | 6850 |
| 6802 @override | 6851 @override |
| 6803 Object visitNamedExpression(NamedExpression node) { | 6852 Object visitNamedExpression(NamedExpression node) { |
| 6804 InferenceContext.setType(node.expression, InferenceContext.getType(node)); | 6853 InferenceContext.setTypeFromNode(node.expression, node); |
| 6805 return super.visitNamedExpression(node); | 6854 return super.visitNamedExpression(node); |
| 6806 } | 6855 } |
| 6807 | 6856 |
| 6808 @override | 6857 @override |
| 6809 Object visitNode(AstNode node) { | 6858 Object visitNode(AstNode node) { |
| 6810 node.visitChildren(this); | 6859 node.visitChildren(this); |
| 6811 node.accept(elementResolver); | 6860 node.accept(elementResolver); |
| 6812 node.accept(typeAnalyzer); | 6861 node.accept(typeAnalyzer); |
| 6813 return null; | 6862 return null; |
| 6814 } | 6863 } |
| 6815 | 6864 |
| 6816 @override | 6865 @override |
| 6817 Object visitParenthesizedExpression(ParenthesizedExpression node) { | 6866 Object visitParenthesizedExpression(ParenthesizedExpression node) { |
| 6818 InferenceContext.setType(node.expression, InferenceContext.getType(node)); | 6867 InferenceContext.setTypeFromNode(node.expression, node); |
| 6819 return super.visitParenthesizedExpression(node); | 6868 return super.visitParenthesizedExpression(node); |
| 6820 } | 6869 } |
| 6821 | 6870 |
| 6822 @override | 6871 @override |
| 6823 Object visitPrefixedIdentifier(PrefixedIdentifier node) { | 6872 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 6824 // | 6873 // |
| 6825 // We visit the prefix, but do not visit the identifier because it needs to | 6874 // We visit the prefix, but do not visit the identifier because it needs to |
| 6826 // be visited in the context of the prefix. | 6875 // be visited in the context of the prefix. |
| 6827 // | 6876 // |
| 6828 node.prefix?.accept(this); | 6877 node.prefix?.accept(this); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6926 _overrideManager.applyOverrides(overrides); | 6975 _overrideManager.applyOverrides(overrides); |
| 6927 } | 6976 } |
| 6928 return null; | 6977 return null; |
| 6929 } | 6978 } |
| 6930 | 6979 |
| 6931 @override | 6980 @override |
| 6932 Object visitTypeName(TypeName node) => null; | 6981 Object visitTypeName(TypeName node) => null; |
| 6933 | 6982 |
| 6934 @override | 6983 @override |
| 6935 Object visitVariableDeclaration(VariableDeclaration node) { | 6984 Object visitVariableDeclaration(VariableDeclaration node) { |
| 6936 InferenceContext.setType(node.initializer, InferenceContext.getType(node)); | 6985 InferenceContext.setTypeFromNode(node.initializer, node); |
| 6937 super.visitVariableDeclaration(node); | 6986 super.visitVariableDeclaration(node); |
| 6938 VariableElement element = node.element; | 6987 VariableElement element = node.element; |
| 6939 if (element.initializer != null && node.initializer != null) { | 6988 if (element.initializer != null && node.initializer != null) { |
| 6940 (element.initializer as FunctionElementImpl).returnType = | 6989 (element.initializer as FunctionElementImpl).returnType = |
| 6941 node.initializer.staticType; | 6990 node.initializer.staticType; |
| 6942 } | 6991 } |
| 6943 // Note: in addition to cloning the initializers for const variables, we | 6992 // Note: in addition to cloning the initializers for const variables, we |
| 6944 // have to clone the initializers for non-static final fields (because if | 6993 // have to clone the initializers for non-static final fields (because if |
| 6945 // they occur in a class with a const constructor, they will be needed to | 6994 // they occur in a class with a const constructor, they will be needed to |
| 6946 // evaluate the const constructor). | 6995 // evaluate the const constructor). |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7070 * cannot be computed from the declared return type, return null. | 7119 * cannot be computed from the declared return type, return null. |
| 7071 */ | 7120 */ |
| 7072 DartType _computeReturnOrYieldType(DartType declaredType) { | 7121 DartType _computeReturnOrYieldType(DartType declaredType) { |
| 7073 bool isGenerator = _enclosingFunction.isGenerator; | 7122 bool isGenerator = _enclosingFunction.isGenerator; |
| 7074 bool isAsynchronous = _enclosingFunction.isAsynchronous; | 7123 bool isAsynchronous = _enclosingFunction.isAsynchronous; |
| 7075 | 7124 |
| 7076 // Ordinary functions just return their declared types. | 7125 // Ordinary functions just return their declared types. |
| 7077 if (!isGenerator && !isAsynchronous) { | 7126 if (!isGenerator && !isAsynchronous) { |
| 7078 return declaredType; | 7127 return declaredType; |
| 7079 } | 7128 } |
| 7080 if (isGenerator) { | 7129 if (declaredType is InterfaceType) { |
| 7081 if (declaredType is! InterfaceType) { | 7130 if (isGenerator) { |
| 7082 return null; | 7131 // If it's sync* we expect Iterable<T> |
| 7132 // IF it's async* we expect Stream<T> | |
|
vsm
2016/08/09 20:29:33
IF -> If
Jennifer Messerly
2016/08/09 20:56:57
Done.
| |
| 7133 InterfaceType rawType = isAsynchronous | |
| 7134 ? typeProvider.streamDynamicType | |
| 7135 : typeProvider.iterableDynamicType; | |
| 7136 // Match the types to instantiate the type arguments if possible | |
| 7137 List<DartType> typeArgs = | |
| 7138 inferenceContext.matchTypes(rawType, declaredType); | |
| 7139 return (typeArgs?.length == 1) ? typeArgs[0] : null; | |
| 7083 } | 7140 } |
| 7084 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> | 7141 // async functions expect `Future<T> | T` |
| 7085 InterfaceType rawType = isAsynchronous | 7142 return new FutureUnionType(declaredType, typeProvider, typeSystem); |
| 7086 ? typeProvider.streamDynamicType | |
| 7087 : typeProvider.iterableDynamicType; | |
| 7088 // Match the types to instantiate the type arguments if possible | |
| 7089 List<DartType> typeArgs = | |
| 7090 inferenceContext.matchTypes(rawType, declaredType); | |
| 7091 return (typeArgs?.length == 1) ? typeArgs[0] : null; | |
| 7092 } | 7143 } |
| 7093 // Must be asynchronous to reach here, so strip off any layers of Future | 7144 return declaredType; |
| 7094 return declaredType.flattenFutures(typeSystem); | |
| 7095 } | 7145 } |
| 7096 | 7146 |
| 7097 /** | 7147 /** |
| 7098 * The given expression is the expression used to compute the iterator for a | 7148 * The given expression is the expression used to compute the iterator for a |
| 7099 * for-each statement. Attempt to compute the type of objects that will be | 7149 * for-each statement. Attempt to compute the type of objects that will be |
| 7100 * assigned to the loop variable and return that type. Return `null` if the | 7150 * assigned to the loop variable and return that type. Return `null` if the |
| 7101 * type could not be determined. The [iteratorExpression] is the expression | 7151 * type could not be determined. The [iteratorExpression] is the expression |
| 7102 * that will return the Iterable being iterated over. | 7152 * that will return the Iterable being iterated over. |
| 7103 */ | 7153 */ |
| 7104 DartType _getIteratorElementType(Expression iteratorExpression) { | 7154 DartType _getIteratorElementType(Expression iteratorExpression) { |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7315 // | 7365 // |
| 7316 // Unsound to assume that [x = "hello";] never executed after the | 7366 // Unsound to assume that [x = "hello";] never executed after the |
| 7317 // if-statement. Of course, a dead-code analysis could point out that | 7367 // if-statement. Of course, a dead-code analysis could point out that |
| 7318 // [return] here is dead. | 7368 // [return] here is dead. |
| 7319 return _isAbruptTerminationStatement(statements[size - 1]); | 7369 return _isAbruptTerminationStatement(statements[size - 1]); |
| 7320 } | 7370 } |
| 7321 return false; | 7371 return false; |
| 7322 } | 7372 } |
| 7323 | 7373 |
| 7324 /** | 7374 /** |
| 7375 * Returns true if this expression is being passed to `Future.then`. | |
| 7376 * | |
| 7377 * If so we will apply special typing rules in strong mode, to handle the | |
| 7378 * implicit union of `S | Future<S>` | |
| 7379 */ | |
| 7380 bool _isFutureThenLambda(FunctionExpression node) { | |
| 7381 Element element = node.staticParameterElement?.enclosingElement; | |
| 7382 return element is MethodElement && | |
| 7383 element.name == 'then' && | |
| 7384 element.enclosingElement.type.isDartAsyncFuture; | |
| 7385 } | |
| 7386 | |
| 7387 /** | |
| 7325 * Return `true` if the given variable is accessed within a closure in the giv en | 7388 * Return `true` if the given variable is accessed within a closure in the giv en |
| 7326 * [AstNode] and also mutated somewhere in variable scope. This information is only | 7389 * [AstNode] and also mutated somewhere in variable scope. This information is only |
| 7327 * available for local variables (including parameters). | 7390 * available for local variables (including parameters). |
| 7328 * | 7391 * |
| 7329 * @param variable the variable to check | 7392 * @param variable the variable to check |
| 7330 * @param target the [AstNode] to check within | 7393 * @param target the [AstNode] to check within |
| 7331 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode | 7394 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode |
| 7332 */ | 7395 */ |
| 7333 bool _isVariableAccessedInClosure(Element variable, AstNode target) { | 7396 bool _isVariableAccessedInClosure(Element variable, AstNode target) { |
| 7334 _ResolverVisitor_isVariableAccessedInClosure visitor = | 7397 _ResolverVisitor_isVariableAccessedInClosure visitor = |
| (...skipping 3670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11005 return null; | 11068 return null; |
| 11006 } | 11069 } |
| 11007 if (identical(node.staticElement, variable)) { | 11070 if (identical(node.staticElement, variable)) { |
| 11008 if (node.inSetterContext()) { | 11071 if (node.inSetterContext()) { |
| 11009 result = true; | 11072 result = true; |
| 11010 } | 11073 } |
| 11011 } | 11074 } |
| 11012 return null; | 11075 return null; |
| 11013 } | 11076 } |
| 11014 } | 11077 } |
| OLD | NEW |