Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(486)

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 1724543002: fix #25487, infer block lambdas from return statements (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698