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 |
| 4621 * this is the same as the return type of the function. For async | 4629 * this is the same as the return type of the function. For async |
| 4622 * functions returning Future<T> and for generator functions | 4630 * functions returning Future<T> and for generator functions |
| 4623 * returning Stream<T> or Iterable<T>, this is T. | 4631 * returning Stream<T> or Iterable<T>, this is T. |
| 4624 */ | 4632 */ |
| 4625 DartType get returnContext => | 4633 DartType get returnContext => |
| 4626 _returnStack.isNotEmpty ? _returnStack.last : null; | 4634 _returnStack.isNotEmpty ? _returnStack.last : null; |
| 4627 | 4635 |
| 4628 /** | 4636 /** |
| 4637 * Records the type of the expression of a return statement. | |
| 4638 * | |
| 4639 * This will be used for inferring a block bodied lambda, if no context | |
| 4640 * type was available. | |
| 4641 */ | |
| 4642 void addReturnOrYieldType(DartType type) { | |
| 4643 if (_returnStack.isEmpty) { | |
| 4644 return; | |
| 4645 } | |
| 4646 DartType context = _returnStack.last; | |
| 4647 if (context == null || context.isDynamic) { | |
| 4648 DartType inferred = _inferredReturn.last; | |
| 4649 inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred); | |
| 4650 _inferredReturn[_inferredReturn.length - 1] = inferred; | |
| 4651 } | |
| 4652 } | |
| 4653 | |
| 4654 /** | |
| 4629 * Match type [t1] against type [t2] as follows. | 4655 * Match type [t1] against type [t2] as follows. |
| 4630 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype | 4656 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype |
| 4631 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` | 4657 * 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'` | 4658 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` |
| 4633 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, | 4659 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, |
| 4634 * such that `I<T0, .., Tn> <: t2` | 4660 * such that `I<T0, .., Tn> <: t2` |
| 4635 */ | 4661 */ |
| 4636 List<DartType> matchTypes(DartType t1, DartType t2) => | 4662 List<DartType> matchTypes(DartType t1, DartType t2) => |
| 4637 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null; | 4663 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null; |
| 4638 | 4664 |
| 4639 /** | 4665 /** |
| 4640 * Pop a return type off of the return stack. | 4666 * Pop a return type off of the return stack. |
| 4667 * | |
| 4668 * Also record any inferred return type using [setType], unless this node | |
| 4669 * already has a context type. This recorded type will be the least upper | |
| 4670 * bound of all types added with [addReturnOrYieldType]. | |
| 4641 */ | 4671 */ |
| 4642 void popReturnContext() { | 4672 void popReturnContext(BlockFunctionBody node) { |
| 4643 assert(_returnStack.isNotEmpty); | 4673 assert(_returnStack.isNotEmpty && _inferredReturn.isNotEmpty); |
| 4644 if (_returnStack.isNotEmpty) { | 4674 if (_returnStack.isNotEmpty) { |
| 4645 _returnStack.removeLast(); | 4675 _returnStack.removeLast(); |
| 4646 } | 4676 } |
| 4677 if (_inferredReturn.isNotEmpty) { | |
| 4678 DartType inferred = _inferredReturn.removeLast(); | |
| 4679 if (!inferred.isBottom) { | |
| 4680 setType(node, inferred); | |
| 4681 } | |
| 4682 } | |
| 4647 } | 4683 } |
| 4648 | 4684 |
| 4649 /** | 4685 /** |
| 4650 * Push a [returnType] onto the return stack. | 4686 * Push a block function body's return type onto the return stack. |
| 4651 */ | 4687 */ |
| 4652 void pushReturnContext(DartType returnType) { | 4688 void pushReturnContext(BlockFunctionBody node) { |
| 4689 DartType returnType = getType(node); | |
| 4653 _returnStack.add(returnType); | 4690 _returnStack.add(returnType); |
| 4691 _inferredReturn.add(BottomTypeImpl.instance); | |
| 4654 } | 4692 } |
| 4655 | 4693 |
| 4656 /** | 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; |
| (...skipping 2986 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 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8132 _currentFunctionBody = node.body; | 8170 _currentFunctionBody = node.body; |
| 8133 _enclosingFunction = node.element; | 8171 _enclosingFunction = node.element; |
| 8134 _overrideManager.enterScope(); | 8172 _overrideManager.enterScope(); |
| 8135 try { | 8173 try { |
| 8136 DartType functionType = InferenceContext.getType(node); | 8174 DartType functionType = InferenceContext.getType(node); |
| 8137 if (functionType is FunctionType) { | 8175 if (functionType is FunctionType) { |
| 8138 functionType = | 8176 functionType = |
| 8139 matchFunctionTypeParameters(node.typeParameters, functionType); | 8177 matchFunctionTypeParameters(node.typeParameters, functionType); |
| 8140 if (functionType is FunctionType) { | 8178 if (functionType is FunctionType) { |
| 8141 _inferFormalParameterList(node.parameters, functionType); | 8179 _inferFormalParameterList(node.parameters, functionType); |
| 8142 DartType returnType = _computeReturnOrYieldType( | 8180 DartType returnType = |
| 8143 functionType.returnType, | 8181 _computeReturnOrYieldType(functionType.returnType); |
| 8144 _enclosingFunction.isGenerator, | |
| 8145 _enclosingFunction.isAsynchronous); | |
| 8146 InferenceContext.setType(node.body, returnType); | 8182 InferenceContext.setType(node.body, returnType); |
| 8147 } | 8183 } |
| 8148 } | 8184 } |
| 8149 super.visitFunctionExpression(node); | 8185 super.visitFunctionExpression(node); |
| 8150 } finally { | 8186 } finally { |
| 8151 _overrideManager.exitScope(); | 8187 _overrideManager.exitScope(); |
| 8152 } | 8188 } |
| 8153 } finally { | 8189 } finally { |
| 8154 _currentFunctionBody = outerFunctionBody; | 8190 _currentFunctionBody = outerFunctionBody; |
| 8155 _enclosingFunction = outerFunction; | 8191 _enclosingFunction = outerFunction; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8345 return null; | 8381 return null; |
| 8346 } | 8382 } |
| 8347 | 8383 |
| 8348 @override | 8384 @override |
| 8349 Object visitMethodDeclaration(MethodDeclaration node) { | 8385 Object visitMethodDeclaration(MethodDeclaration node) { |
| 8350 ExecutableElement outerFunction = _enclosingFunction; | 8386 ExecutableElement outerFunction = _enclosingFunction; |
| 8351 FunctionBody outerFunctionBody = _currentFunctionBody; | 8387 FunctionBody outerFunctionBody = _currentFunctionBody; |
| 8352 try { | 8388 try { |
| 8353 _currentFunctionBody = node.body; | 8389 _currentFunctionBody = node.body; |
| 8354 _enclosingFunction = node.element; | 8390 _enclosingFunction = node.element; |
| 8355 DartType returnType = _computeReturnOrYieldType( | 8391 DartType returnType = |
| 8356 _enclosingFunction.type?.returnType, | 8392 _computeReturnOrYieldType(_enclosingFunction.type?.returnType); |
| 8357 _enclosingFunction.isGenerator, | |
| 8358 _enclosingFunction.isAsynchronous); | |
| 8359 InferenceContext.setType(node.body, returnType); | 8393 InferenceContext.setType(node.body, returnType); |
| 8360 super.visitMethodDeclaration(node); | 8394 super.visitMethodDeclaration(node); |
| 8361 } finally { | 8395 } finally { |
| 8362 _currentFunctionBody = outerFunctionBody; | 8396 _currentFunctionBody = outerFunctionBody; |
| 8363 _enclosingFunction = outerFunction; | 8397 _enclosingFunction = outerFunction; |
| 8364 } | 8398 } |
| 8365 return null; | 8399 return null; |
| 8366 } | 8400 } |
| 8367 | 8401 |
| 8368 @override | 8402 @override |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8444 // | 8478 // |
| 8445 InferenceContext.setType(node.argumentList, node.staticElement?.type); | 8479 InferenceContext.setType(node.argumentList, node.staticElement?.type); |
| 8446 safelyVisit(node.argumentList); | 8480 safelyVisit(node.argumentList); |
| 8447 node.accept(elementResolver); | 8481 node.accept(elementResolver); |
| 8448 node.accept(typeAnalyzer); | 8482 node.accept(typeAnalyzer); |
| 8449 return null; | 8483 return null; |
| 8450 } | 8484 } |
| 8451 | 8485 |
| 8452 @override | 8486 @override |
| 8453 Object visitReturnStatement(ReturnStatement node) { | 8487 Object visitReturnStatement(ReturnStatement node) { |
| 8454 InferenceContext.setType(node.expression, inferenceContext.returnContext); | 8488 Expression e = node.expression; |
| 8455 return super.visitReturnStatement(node); | 8489 InferenceContext.setType(e, inferenceContext.returnContext); |
| 8490 super.visitReturnStatement(node); | |
| 8491 DartType type = e?.staticType; | |
| 8492 // Generators cannot return values, so don't try to do any inference if | |
| 8493 // we're processing erroneous code. | |
| 8494 if (type != null && _enclosingFunction?.isGenerator == false) { | |
| 8495 if (_enclosingFunction.isAsynchronous) { | |
| 8496 type = type.flattenFutures(typeSystem); | |
| 8497 } | |
| 8498 inferenceContext.addReturnOrYieldType(type); | |
| 8499 } | |
| 8500 return null; | |
| 8456 } | 8501 } |
| 8457 | 8502 |
| 8458 @override | 8503 @override |
| 8459 Object visitShowCombinator(ShowCombinator node) => null; | 8504 Object visitShowCombinator(ShowCombinator node) => null; |
| 8460 | 8505 |
| 8461 @override | 8506 @override |
| 8462 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 8507 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 8463 // | 8508 // |
| 8464 // We visit the argument list, but do not visit the optional identifier | 8509 // 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 | 8510 // because it needs to be visited in the context of the constructor |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8567 } | 8612 } |
| 8568 // TODO(brianwilkerson) If the loop can only be exited because the condition | 8613 // TODO(brianwilkerson) If the loop can only be exited because the condition |
| 8569 // is false, then propagateFalseState(condition); | 8614 // is false, then propagateFalseState(condition); |
| 8570 node.accept(elementResolver); | 8615 node.accept(elementResolver); |
| 8571 node.accept(typeAnalyzer); | 8616 node.accept(typeAnalyzer); |
| 8572 return null; | 8617 return null; |
| 8573 } | 8618 } |
| 8574 | 8619 |
| 8575 @override | 8620 @override |
| 8576 Object visitYieldStatement(YieldStatement node) { | 8621 Object visitYieldStatement(YieldStatement node) { |
| 8622 Expression e = node.expression; | |
| 8577 DartType returnType = inferenceContext.returnContext; | 8623 DartType returnType = inferenceContext.returnContext; |
| 8578 if (returnType != null && _enclosingFunction != null) { | 8624 bool isGenerator = _enclosingFunction?.isGenerator ?? false; |
| 8625 if (returnType != null && isGenerator) { | |
| 8579 // If we're not in a generator ([a]sync*, then we shouldn't have a yield. | 8626 // If we're not in a generator ([a]sync*, then we shouldn't have a yield. |
| 8580 // so don't infer | 8627 // so don't infer |
| 8581 if (_enclosingFunction.isGenerator) { | 8628 |
| 8582 // If this just a yield, then we just pass on the element type | 8629 // If this just a yield, then we just pass on the element type |
| 8583 DartType type = returnType; | 8630 DartType type = returnType; |
| 8584 if (node.star != null) { | 8631 if (node.star != null) { |
| 8585 // If this is a yield*, then we wrap the element return type | 8632 // If this is a yield*, then we wrap the element return type |
| 8586 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> | 8633 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> |
| 8587 InterfaceType wrapperType = _enclosingFunction.isSynchronous | 8634 InterfaceType wrapperType = _enclosingFunction.isSynchronous |
| 8588 ? typeProvider.iterableType | 8635 ? typeProvider.iterableType |
| 8589 : typeProvider.streamType; | 8636 : typeProvider.streamType; |
| 8590 type = wrapperType.substitute4(<DartType>[type]); | 8637 type = wrapperType.substitute4(<DartType>[type]); |
| 8591 } | 8638 } |
| 8592 InferenceContext.setType(node.expression, type); | 8639 InferenceContext.setType(e, type); |
| 8640 | |
| 8641 } | |
| 8642 super.visitYieldStatement(node); | |
| 8643 DartType type = e?.staticType; | |
| 8644 if (type != null && isGenerator) { | |
| 8645 // If this just a yield, then we just pass on the element type | |
| 8646 if (node.star != null) { | |
| 8647 // If this is a yield*, then we unwrap the element return type | |
| 8648 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> | |
| 8649 InterfaceType wrapperType = _enclosingFunction.isSynchronous | |
| 8650 ? typeProvider.iterableType | |
| 8651 : typeProvider.streamType; | |
| 8652 List<DartType> candidates = _findImplementedTypeArgument(type, wrapperTy pe); | |
| 8653 type = InterfaceTypeImpl.findMostSpecificType(candidates, typeSystem); | |
| 8654 } | |
| 8655 if (type != null) { | |
| 8656 inferenceContext.addReturnOrYieldType(type); | |
| 8593 } | 8657 } |
| 8594 } | 8658 } |
| 8595 return super.visitYieldStatement(node); | 8659 return null; |
| 8596 } | 8660 } |
| 8597 | 8661 |
| 8598 /** | 8662 /** |
| 8599 * Checks each promoted variable in the current scope for compliance with the following | 8663 * Checks each promoted variable in the current scope for compliance with the following |
| 8600 * specification statement: | 8664 * specification statement: |
| 8601 * | 8665 * |
| 8602 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t hen the variable | 8666 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t hen the variable |
| 8603 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>. | 8667 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>. |
| 8604 */ | 8668 */ |
| 8605 void _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated( | 8669 void _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated( |
| 8606 AstNode target) { | 8670 AstNode target) { |
| 8607 for (Element element in _promoteManager.promotedElements) { | 8671 for (Element element in _promoteManager.promotedElements) { |
| 8608 if (_currentFunctionBody.isPotentiallyMutatedInScope(element)) { | 8672 if (_currentFunctionBody.isPotentiallyMutatedInScope(element)) { |
| 8609 if (_isVariableAccessedInClosure(element, target)) { | 8673 if (_isVariableAccessedInClosure(element, target)) { |
| 8610 _promoteManager.setType(element, null); | 8674 _promoteManager.setType(element, null); |
| 8611 } | 8675 } |
| 8612 } | 8676 } |
| 8613 } | 8677 } |
| 8614 } | 8678 } |
| 8615 | 8679 |
| 8680 | |
| 8616 /** | 8681 /** |
| 8617 * Checks each promoted variable in the current scope for compliance with the following | 8682 * Checks each promoted variable in the current scope for compliance with the following |
| 8618 * specification statement: | 8683 * specification statement: |
| 8619 * | 8684 * |
| 8620 * <i>v</i> is not potentially mutated in <i>s<sub>1</sub></i> or within a clo sure. | 8685 * <i>v</i> is not potentially mutated in <i>s<sub>1</sub></i> or within a clo sure. |
| 8621 */ | 8686 */ |
| 8622 void _clearTypePromotionsIfPotentiallyMutatedIn(AstNode target) { | 8687 void _clearTypePromotionsIfPotentiallyMutatedIn(AstNode target) { |
| 8623 for (Element element in _promoteManager.promotedElements) { | 8688 for (Element element in _promoteManager.promotedElements) { |
| 8624 if (_isVariablePotentiallyMutatedIn(element, target)) { | 8689 if (_isVariablePotentiallyMutatedIn(element, target)) { |
| 8625 _promoteManager.setType(element, null); | 8690 _promoteManager.setType(element, null); |
| 8626 } | 8691 } |
| 8627 } | 8692 } |
| 8628 } | 8693 } |
| 8629 | 8694 |
| 8630 /** | 8695 /** |
| 8631 * Given the declared return type of a function, compute the type of the | 8696 * Given the declared return type of a function, compute the type of the |
| 8632 * values which should be returned or yielded as appropriate. If a type | 8697 * values which should be returned or yielded as appropriate. If a type |
| 8633 * cannot be computed from the declared return type, return null. | 8698 * cannot be computed from the declared return type, return null. |
| 8634 */ | 8699 */ |
| 8635 DartType _computeReturnOrYieldType( | 8700 DartType _computeReturnOrYieldType(DartType declaredType) { |
| 8636 DartType declaredType, bool isGenerator, bool isAsynchronous) { | 8701 bool isGenerator = _enclosingFunction.isGenerator; |
| 8702 bool isAsynchronous = _enclosingFunction.isAsynchronous; | |
| 8703 | |
| 8637 // Ordinary functions just return their declared types. | 8704 // Ordinary functions just return their declared types. |
| 8638 if (!isGenerator && !isAsynchronous) { | 8705 if (!isGenerator && !isAsynchronous) { |
| 8639 return declaredType; | 8706 return declaredType; |
| 8640 } | 8707 } |
| 8641 if (isGenerator) { | 8708 if (isGenerator) { |
| 8642 if (declaredType is! InterfaceType) { | 8709 if (declaredType is! InterfaceType) { |
| 8643 return null; | 8710 return null; |
| 8644 } | 8711 } |
| 8645 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> | 8712 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> |
| 8646 InterfaceType rawType = isAsynchronous | 8713 InterfaceType rawType = isAsynchronous |
| 8647 ? typeProvider.streamDynamicType | 8714 ? typeProvider.streamDynamicType |
| 8648 : typeProvider.iterableDynamicType; | 8715 : typeProvider.iterableDynamicType; |
| 8649 // Match the types to instantiate the type arguments if possible | 8716 // Match the types to instantiate the type arguments if possible |
| 8650 List<DartType> typeArgs = | 8717 List<DartType> typeArgs = |
| 8651 inferenceContext.matchTypes(rawType, declaredType); | 8718 inferenceContext.matchTypes(rawType, declaredType); |
|
Leaf
2016/02/24 15:38:40
I think this code should be changed to use your ne
Jennifer Messerly
2016/02/24 17:43:16
Ah, thanks Leaf ... that makes so much more sense!
| |
| 8652 return (typeArgs?.length == 1) ? typeArgs[0] : null; | 8719 return (typeArgs?.length == 1) ? typeArgs[0] : null; |
| 8653 } | 8720 } |
| 8654 // Must be asynchronous to reach here, so strip off any layers of Future | 8721 // Must be asynchronous to reach here, so strip off any layers of Future |
| 8655 return declaredType.flattenFutures(typeSystem); | 8722 return declaredType.flattenFutures(typeSystem); |
| 8656 } | 8723 } |
| 8657 | 8724 |
| 8658 /** | 8725 /** |
| 8726 * Starting from t1, search its class hierarchy for types of the form | |
| 8727 * `t2<R>`, and return a list of the resulting R's | |
| 8728 * | |
| 8729 * For example, given t1 = `List<int>` and t2 = `Iterable<T>`, this will | |
| 8730 * return [int]. | |
| 8731 */ | |
| 8732 // TODO(jmesserly): this is very similar to code used for flattening futures. | |
| 8733 // The only difference is, because of a lack of TypeProvider, the other method | |
| 8734 // has to match the Future type by its name and library. Here was are passed | |
| 8735 // in the correct type. | |
| 8736 List<DartType> _findImplementedTypeArgument(DartType t1, InterfaceType t2) { | |
| 8737 List<DartType> result = <DartType>[]; | |
| 8738 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 8739 void recurse(InterfaceTypeImpl type) { | |
| 8740 if (type.element == t2.element && type.typeArguments.isNotEmpty) { | |
| 8741 result.add(type.typeArguments[0]); | |
| 8742 } | |
| 8743 if (visitedClasses.add(type.element)) { | |
| 8744 if (type.superclass != null) { | |
| 8745 recurse(type.superclass); | |
| 8746 } | |
| 8747 type.mixins.forEach(recurse); | |
| 8748 type.interfaces.forEach(recurse); | |
| 8749 visitedClasses.remove(type.element); | |
| 8750 } | |
| 8751 } | |
| 8752 if (t1 is InterfaceType) { | |
| 8753 recurse(t1); | |
| 8754 } | |
| 8755 return result; | |
| 8756 } | |
| 8757 | |
| 8758 /** | |
| 8659 * The given expression is the expression used to compute the iterator for a | 8759 * The given expression is the expression used to compute the iterator for a |
| 8660 * for-each statement. Attempt to compute the type of objects that will be | 8760 * for-each statement. Attempt to compute the type of objects that will be |
| 8661 * assigned to the loop variable and return that type. Return `null` if the | 8761 * assigned to the loop variable and return that type. Return `null` if the |
| 8662 * type could not be determined. The [iteratorExpression] is the expression | 8762 * type could not be determined. The [iteratorExpression] is the expression |
| 8663 * that will return the Iterable being iterated over. | 8763 * that will return the Iterable being iterated over. |
| 8664 */ | 8764 */ |
| 8665 DartType _getIteratorElementType(Expression iteratorExpression) { | 8765 DartType _getIteratorElementType(Expression iteratorExpression) { |
| 8666 DartType expressionType = iteratorExpression.bestType; | 8766 DartType expressionType = iteratorExpression.bestType; |
| 8667 if (expressionType is InterfaceType) { | 8767 if (expressionType is InterfaceType) { |
| 8668 InterfaceType interfaceType = expressionType; | 8768 InterfaceType interfaceType = expressionType; |
| (...skipping 4114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12783 nonFields.add(node); | 12883 nonFields.add(node); |
| 12784 return null; | 12884 return null; |
| 12785 } | 12885 } |
| 12786 | 12886 |
| 12787 @override | 12887 @override |
| 12788 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12888 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12789 | 12889 |
| 12790 @override | 12890 @override |
| 12791 Object visitWithClause(WithClause node) => null; | 12891 Object visitWithClause(WithClause node) => null; |
| 12792 } | 12892 } |
| OLD | NEW |