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 4584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4595 * Type provider, needed for type matching. | 4595 * Type provider, needed for type matching. |
| 4596 */ | 4596 */ |
| 4597 final TypeProvider _typeProvider; | 4597 final TypeProvider _typeProvider; |
| 4598 | 4598 |
| 4599 /** | 4599 /** |
| 4600 * The type system in use. | 4600 * The type system in use. |
| 4601 */ | 4601 */ |
| 4602 final TypeSystem _typeSystem; | 4602 final TypeSystem _typeSystem; |
| 4603 | 4603 |
| 4604 /** | 4604 /** |
| 4605 * When no context type is available, this will track the least upper bound | |
| 4606 * of all return statements in a lambda. | |
| 4607 * | |
| 4608 * This will always be kept in sync with [_returnStack]. | |
| 4609 */ | |
| 4610 final List<DartType> _inferredReturn = <DartType>[]; | |
| 4611 | |
| 4612 /** | |
| 4605 * A stack of return types for all of the enclosing | 4613 * A stack of return types for all of the enclosing |
| 4606 * functions and methods. | 4614 * functions and methods. |
| 4607 */ | 4615 */ |
| 4608 // TODO(leafp) Handle the implicit union type for Futures | 4616 // TODO(leafp) Handle the implicit union type for Futures |
| 4609 // https://github.com/dart-lang/sdk/issues/25322 | 4617 // https://github.com/dart-lang/sdk/issues/25322 |
| 4610 List<DartType> _returnStack = <DartType>[]; | 4618 final List<DartType> _returnStack = <DartType>[]; |
| 4611 | 4619 |
| 4612 InferenceContext._(this._errorListener, TypeProvider typeProvider, | 4620 InferenceContext._(this._errorListener, TypeProvider typeProvider, |
| 4613 this._typeSystem, this._inferenceHints) | 4621 this._typeSystem, this._inferenceHints) |
| 4614 : _typeProvider = typeProvider; | 4622 : _typeProvider = typeProvider; |
| 4615 | 4623 |
| 4616 /** | 4624 /** |
| 4617 * Get the return type of the current enclosing function, if any. | 4625 * Get the return type of the current enclosing function, if any. |
| 4618 * | 4626 * |
| 4619 * The type returned for a function is the type that is expected | 4627 * The type returned for a function is the type that is expected |
| 4620 * to be used in a return or yield context. For ordinary functions | 4628 * to be used in a return or yield context. For ordinary functions |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 4631 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` | 4639 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` |
| 4632 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` | 4640 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` |
| 4633 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, | 4641 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, |
| 4634 * such that `I<T0, .., Tn> <: t2` | 4642 * such that `I<T0, .., Tn> <: t2` |
| 4635 */ | 4643 */ |
| 4636 List<DartType> matchTypes(DartType t1, DartType t2) => | 4644 List<DartType> matchTypes(DartType t1, DartType t2) => |
| 4637 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null; | 4645 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null; |
| 4638 | 4646 |
| 4639 /** | 4647 /** |
| 4640 * Pop a return type off of the return stack. | 4648 * Pop a return type off of the return stack. |
| 4649 * | |
| 4650 * Also record any inferred return type using [setType], unless this node | |
| 4651 * already has a context type. This recorded type will be the least upper | |
| 4652 * bound of all types added with [addReturnType]. | |
| 4641 */ | 4653 */ |
| 4642 void popReturnContext() { | 4654 void popReturnContext(BlockFunctionBody node) { |
| 4643 assert(_returnStack.isNotEmpty); | 4655 assert(_returnStack.isNotEmpty && _inferredReturn.isNotEmpty); |
| 4644 if (_returnStack.isNotEmpty) { | 4656 if (_returnStack.isNotEmpty) { |
| 4645 _returnStack.removeLast(); | 4657 _returnStack.removeLast(); |
| 4646 } | 4658 } |
| 4659 if (_inferredReturn.isNotEmpty) { | |
| 4660 DartType inferred = _inferredReturn.removeLast(); | |
| 4661 if (!inferred.isBottom) { | |
| 4662 setType(node, inferred); | |
| 4663 } | |
| 4664 } | |
| 4647 } | 4665 } |
| 4648 | 4666 |
| 4649 /** | 4667 /** |
| 4650 * Push a [returnType] onto the return stack. | 4668 * Push a block function body's return type onto the return stack. |
| 4651 */ | 4669 */ |
| 4652 void pushReturnContext(DartType returnType) { | 4670 void pushReturnContext(BlockFunctionBody node) { |
| 4671 DartType returnType = getType(node); | |
| 4653 _returnStack.add(returnType); | 4672 _returnStack.add(returnType); |
| 4673 _inferredReturn.add(BottomTypeImpl.instance); | |
| 4654 } | 4674 } |
| 4655 | 4675 |
| 4656 /** | 4676 /** |
| 4677 * Records the type of the expression of a return statement. | |
| 4678 * | |
| 4679 * This will be used for inferring a block bodied lambda, if no context | |
| 4680 * type was available. | |
| 4681 */ | |
| 4682 void addReturnType(DartType type) { | |
| 4683 if (type == null || _returnStack.isEmpty) { | |
| 4684 return; | |
| 4685 } | |
| 4686 DartType context = _returnStack.last; | |
| 4687 if (context == null || context.isDynamic) { | |
| 4688 DartType inferred = _inferredReturn.last; | |
| 4689 inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred); | |
| 4690 _inferredReturn[_inferredReturn.length - 1] = inferred; | |
| 4691 } | |
| 4692 } | |
| 4693 | |
| 4694 /** | |
| 4657 * Place an info node into the error stream indicating that a | 4695 * Place an info node into the error stream indicating that a |
| 4658 * [type] has been inferred as the type of [node]. | 4696 * [type] has been inferred as the type of [node]. |
| 4659 */ | 4697 */ |
| 4660 void recordInference(Expression node, DartType type) { | 4698 void recordInference(Expression node, DartType type) { |
| 4661 StaticInfo info = InferredType.create(_typeSystem, node, type); | 4699 StaticInfo info = InferredType.create(_typeSystem, node, type); |
| 4662 if (!_inferenceHints || info == null) { | 4700 if (!_inferenceHints || info == null) { |
| 4663 return; | 4701 return; |
| 4664 } | 4702 } |
| 4665 AnalysisError error = info.toAnalysisError(); | 4703 AnalysisError error = info.toAnalysisError(); |
| 4666 _errorListener.onError(error); | 4704 _errorListener.onError(error); |
| (...skipping 2983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7650 } | 7688 } |
| 7651 node.accept(elementResolver); | 7689 node.accept(elementResolver); |
| 7652 node.accept(typeAnalyzer); | 7690 node.accept(typeAnalyzer); |
| 7653 return null; | 7691 return null; |
| 7654 } | 7692 } |
| 7655 | 7693 |
| 7656 @override | 7694 @override |
| 7657 Object visitBlockFunctionBody(BlockFunctionBody node) { | 7695 Object visitBlockFunctionBody(BlockFunctionBody node) { |
| 7658 _overrideManager.enterScope(); | 7696 _overrideManager.enterScope(); |
| 7659 try { | 7697 try { |
| 7660 inferenceContext.pushReturnContext(InferenceContext.getType(node)); | 7698 inferenceContext.pushReturnContext(node); |
| 7661 super.visitBlockFunctionBody(node); | 7699 super.visitBlockFunctionBody(node); |
| 7662 } finally { | 7700 } finally { |
| 7663 _overrideManager.exitScope(); | 7701 _overrideManager.exitScope(); |
| 7664 inferenceContext.popReturnContext(); | 7702 inferenceContext.popReturnContext(node); |
| 7665 } | 7703 } |
| 7666 return null; | 7704 return null; |
| 7667 } | 7705 } |
| 7668 | 7706 |
| 7669 @override | 7707 @override |
| 7670 Object visitBreakStatement(BreakStatement node) { | 7708 Object visitBreakStatement(BreakStatement node) { |
| 7671 // | 7709 // |
| 7672 // We do not visit the label because it needs to be visited in the context | 7710 // We do not visit the label because it needs to be visited in the context |
| 7673 // of the statement. | 7711 // of the statement. |
| 7674 // | 7712 // |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8444 // | 8482 // |
| 8445 InferenceContext.setType(node.argumentList, node.staticElement?.type); | 8483 InferenceContext.setType(node.argumentList, node.staticElement?.type); |
| 8446 safelyVisit(node.argumentList); | 8484 safelyVisit(node.argumentList); |
| 8447 node.accept(elementResolver); | 8485 node.accept(elementResolver); |
| 8448 node.accept(typeAnalyzer); | 8486 node.accept(typeAnalyzer); |
| 8449 return null; | 8487 return null; |
| 8450 } | 8488 } |
| 8451 | 8489 |
| 8452 @override | 8490 @override |
| 8453 Object visitReturnStatement(ReturnStatement node) { | 8491 Object visitReturnStatement(ReturnStatement node) { |
| 8454 InferenceContext.setType(node.expression, inferenceContext.returnContext); | 8492 Expression e = node.expression; |
| 8455 return super.visitReturnStatement(node); | 8493 InferenceContext.setType(e, inferenceContext.returnContext); |
| 8494 super.visitReturnStatement(node); | |
| 8495 if (e != null) { | |
| 8496 inferenceContext.addReturnType(e.staticType); | |
|
Leaf
2016/02/23 02:17:47
As it stands, I think that this will do the right
Jennifer Messerly
2016/02/23 17:41:46
Nice catch. Yeah, it seems like we should interpre
Jennifer Messerly
2016/02/24 00:20:40
Done.
| |
| 8497 } | |
| 8498 return null; | |
| 8456 } | 8499 } |
| 8457 | 8500 |
| 8458 @override | 8501 @override |
| 8459 Object visitShowCombinator(ShowCombinator node) => null; | 8502 Object visitShowCombinator(ShowCombinator node) => null; |
| 8460 | 8503 |
| 8461 @override | 8504 @override |
| 8462 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 8505 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 8463 // | 8506 // |
| 8464 // We visit the argument list, but do not visit the optional identifier | 8507 // We visit the argument list, but do not visit the optional identifier |
| 8465 // because it needs to be visited in the context of the constructor | 8508 // because it needs to be visited in the context of the constructor |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8566 _implicitLabelScope = outerImplicitScope; | 8609 _implicitLabelScope = outerImplicitScope; |
| 8567 } | 8610 } |
| 8568 // TODO(brianwilkerson) If the loop can only be exited because the condition | 8611 // TODO(brianwilkerson) If the loop can only be exited because the condition |
| 8569 // is false, then propagateFalseState(condition); | 8612 // is false, then propagateFalseState(condition); |
| 8570 node.accept(elementResolver); | 8613 node.accept(elementResolver); |
| 8571 node.accept(typeAnalyzer); | 8614 node.accept(typeAnalyzer); |
| 8572 return null; | 8615 return null; |
| 8573 } | 8616 } |
| 8574 | 8617 |
| 8575 @override | 8618 @override |
| 8576 Object visitYieldStatement(YieldStatement node) { | 8619 Object visitYieldStatement(YieldStatement node) { |
|
Leaf
2016/02/23 02:17:47
It seems like there's an analogous inference for y
Jennifer Messerly
2016/02/23 17:41:46
Good catch. Completely forgot that sync*/async* co
Jennifer Messerly
2016/02/24 00:20:40
Done. This one was a little tricky, in particular
| |
| 8577 DartType returnType = inferenceContext.returnContext; | 8620 DartType returnType = inferenceContext.returnContext; |
| 8578 if (returnType != null && _enclosingFunction != null) { | 8621 if (returnType != null && _enclosingFunction != null) { |
| 8579 // If we're not in a generator ([a]sync*, then we shouldn't have a yield. | 8622 // If we're not in a generator ([a]sync*, then we shouldn't have a yield. |
| 8580 // so don't infer | 8623 // so don't infer |
| 8581 if (_enclosingFunction.isGenerator) { | 8624 if (_enclosingFunction.isGenerator) { |
| 8582 // If this just a yield, then we just pass on the element type | 8625 // If this just a yield, then we just pass on the element type |
| 8583 DartType type = returnType; | 8626 DartType type = returnType; |
| 8584 if (node.star != null) { | 8627 if (node.star != null) { |
| 8585 // If this is a yield*, then we wrap the element return type | 8628 // If this is a yield*, then we wrap the element return type |
| 8586 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> | 8629 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> |
| (...skipping 4196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12783 nonFields.add(node); | 12826 nonFields.add(node); |
| 12784 return null; | 12827 return null; |
| 12785 } | 12828 } |
| 12786 | 12829 |
| 12787 @override | 12830 @override |
| 12788 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12831 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12789 | 12832 |
| 12790 @override | 12833 @override |
| 12791 Object visitWithClause(WithClause node) => null; | 12834 Object visitWithClause(WithClause node) => null; |
| 12792 } | 12835 } |
| OLD | NEW |