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.error_verifier; | 5 library analyzer.src.generated.error_verifier; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import "dart:math" as math; | 8 import "dart:math" as math; |
| 9 | 9 |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 3422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3433 * respectively. If not, report the error using [returnType]. | 3433 * respectively. If not, report the error using [returnType]. |
| 3434 */ | 3434 */ |
| 3435 void _checkForIllegalReturnType(TypeName returnType) { | 3435 void _checkForIllegalReturnType(TypeName returnType) { |
| 3436 if (returnType == null) { | 3436 if (returnType == null) { |
| 3437 // No declared return type, so the return type must be dynamic, which is | 3437 // No declared return type, so the return type must be dynamic, which is |
| 3438 // assignable to everything. | 3438 // assignable to everything. |
| 3439 return; | 3439 return; |
| 3440 } | 3440 } |
| 3441 if (_enclosingFunction.isAsynchronous) { | 3441 if (_enclosingFunction.isAsynchronous) { |
| 3442 if (_enclosingFunction.isGenerator) { | 3442 if (_enclosingFunction.isGenerator) { |
| 3443 if (_options.strongMode) { | 3443 _checkForIllegalReturnTypeCode( |
| 3444 if (_enclosingFunction.returnType.element != | 3444 returnType, |
| 3445 _typeProvider.streamType.element) { | 3445 _typeProvider.streamDynamicType, |
| 3446 _errorReporter.reportErrorForNode( | 3446 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE); |
| 3447 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, | |
| 3448 returnType); | |
| 3449 } | |
| 3450 } else if (!_typeSystem.isAssignableTo( | |
| 3451 _enclosingFunction.returnType, _typeProvider.streamDynamicType)) { | |
| 3452 _errorReporter.reportErrorForNode( | |
| 3453 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, | |
| 3454 returnType); | |
| 3455 } | |
| 3456 } else { | 3447 } else { |
| 3457 if (_options.strongMode) { | 3448 _checkForIllegalReturnTypeCode( |
| 3458 if (_enclosingFunction.returnType.element != | 3449 returnType, |
| 3459 _typeProvider.futureType.element) { | 3450 _typeProvider.futureDynamicType, |
| 3460 _errorReporter.reportErrorForNode( | 3451 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE); |
| 3461 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType); | |
| 3462 } | |
| 3463 } else if (!_typeSystem.isAssignableTo( | |
| 3464 _enclosingFunction.returnType, _typeProvider.futureDynamicType)) { | |
| 3465 _errorReporter.reportErrorForNode( | |
| 3466 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType); | |
| 3467 } | |
| 3468 } | 3452 } |
| 3469 } else if (_enclosingFunction.isGenerator) { | 3453 } else if (_enclosingFunction.isGenerator) { |
| 3470 if (!_typeSystem.isAssignableTo( | 3454 _checkForIllegalReturnTypeCode( |
| 3471 _enclosingFunction.returnType, _typeProvider.iterableDynamicType)) { | 3455 returnType, |
| 3472 _errorReporter.reportErrorForNode( | 3456 _typeProvider.iterableDynamicType, |
| 3473 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, | 3457 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE); |
| 3474 returnType); | |
| 3475 } | |
| 3476 } | 3458 } |
| 3477 } | 3459 } |
| 3478 | 3460 |
| 3461 /** | |
| 3462 * If the current function is async, async*, or sync*, verify that its | |
| 3463 * declared return type is assignable to Future, Stream, or Iterable, | |
| 3464 * respectively. This is called by [_checkForIllegalReturnType] to check if | |
| 3465 * the declared [returnTypeName] is assignable to the required [expectedType] | |
| 3466 * and if not report [errorCode]. | |
| 3467 */ | |
| 3468 void _checkForIllegalReturnTypeCode(TypeName returnTypeName, | |
| 3469 DartType expectedType, StaticTypeWarningCode errorCode) { | |
| 3470 DartType returnType = _enclosingFunction.returnType; | |
| 3471 if (_options.strongMode) { | |
| 3472 // When checking an async/sync*/async* method, we know the exact type | |
| 3473 // that will be returned (e.g. Future, Iterable, or Stream). | |
| 3474 // | |
| 3475 // For example, an `async` function body will return a `Future<T>` for | |
| 3476 // some T (possibly `dynamic`). | |
| 3477 // | |
| 3478 // We allow the declared return type to be a supertype of that | |
| 3479 // (e.g. `dynamic`, `Object`), or Future<S> for some S. | |
| 3480 // (We assume the T <: S relation is checked elsewhere.) | |
| 3481 // | |
| 3482 // We do not allow user-defined subtypes of Future, because an `async` | |
| 3483 // method will never return those. | |
| 3484 // | |
| 3485 // Similar logic applies for sync* and async*. | |
| 3486 if (!_typeSystem.isSubtypeOf(expectedType, returnType) && | |
| 3487 returnType.element != expectedType.element) { | |
|
Leaf
2016/04/28 01:01:50
This is a little tricky. It might be clearer just
Jennifer Messerly
2016/04/28 01:25:04
DOH. Yes, Future<bottom> is what I should've done.
| |
| 3488 _errorReporter.reportErrorForNode(errorCode, returnTypeName); | |
| 3489 } | |
| 3490 } else if (!_typeSystem.isAssignableTo(returnType, expectedType)) { | |
| 3491 _errorReporter.reportErrorForNode(errorCode, returnTypeName); | |
| 3492 } | |
| 3493 } | |
| 3494 | |
| 3479 /** | 3495 /** |
| 3480 * Verify that the given implements [clause] does not implement classes that | 3496 * Verify that the given implements [clause] does not implement classes that |
| 3481 * are deferred. | 3497 * are deferred. |
| 3482 * | 3498 * |
| 3483 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS]. | 3499 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS]. |
| 3484 */ | 3500 */ |
| 3485 void _checkForImplementsDeferredClass(ImplementsClause clause) { | 3501 void _checkForImplementsDeferredClass(ImplementsClause clause) { |
| 3486 if (clause == null) { | 3502 if (clause == null) { |
| 3487 return; | 3503 return; |
| 3488 } | 3504 } |
| (...skipping 2649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6138 class _InvocationCollector extends RecursiveAstVisitor { | 6154 class _InvocationCollector extends RecursiveAstVisitor { |
| 6139 final List<String> superCalls = <String>[]; | 6155 final List<String> superCalls = <String>[]; |
| 6140 | 6156 |
| 6141 @override | 6157 @override |
| 6142 visitMethodInvocation(MethodInvocation node) { | 6158 visitMethodInvocation(MethodInvocation node) { |
| 6143 if (node.target is SuperExpression) { | 6159 if (node.target is SuperExpression) { |
| 6144 superCalls.add(node.methodName.name); | 6160 superCalls.add(node.methodName.name); |
| 6145 } | 6161 } |
| 6146 } | 6162 } |
| 6147 } | 6163 } |
| OLD | NEW |