mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
Fix for inlining async methods/getters.
R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org/2463493002 .
This commit is contained in:
parent
f9cf78a1af
commit
3319e6d0e3
|
@ -216,6 +216,7 @@ class InlineMethodRefactoringImpl extends RefactoringImpl
|
|||
_SourcePart _methodExpressionPart;
|
||||
_SourcePart _methodStatementsPart;
|
||||
List<_ReferenceProcessor> _referenceProcessors = [];
|
||||
Set<FunctionBody> _alreadyMadeAsync = new Set<FunctionBody>();
|
||||
|
||||
InlineMethodRefactoringImpl(this.searchEngine, this.unit, this.offset) {
|
||||
utils = new CorrectionUtils(unit);
|
||||
|
@ -287,6 +288,11 @@ class InlineMethodRefactoringImpl extends RefactoringImpl
|
|||
result = new RefactoringStatus.fatal('Cannot inline operator.');
|
||||
return new Future<RefactoringStatus>.value(result);
|
||||
}
|
||||
// maybe [a]sync*
|
||||
if (_methodElement.isGenerator) {
|
||||
result = new RefactoringStatus.fatal('Cannot inline a generator.');
|
||||
return new Future<RefactoringStatus>.value(result);
|
||||
}
|
||||
// analyze method body
|
||||
result.addStatus(_prepareMethodParts());
|
||||
// process references
|
||||
|
@ -560,6 +566,33 @@ class _ReferenceProcessor {
|
|||
if (!_shouldProcess()) {
|
||||
return;
|
||||
}
|
||||
// If the element being inlined is async, ensure that the function
|
||||
// body that encloses the method is also async.
|
||||
if (ref._methodElement.isAsynchronous) {
|
||||
FunctionBody body = _node.getAncestor((n) => n is FunctionBody);
|
||||
if (body != null) {
|
||||
if (body.isSynchronous) {
|
||||
if (body.isGenerator) {
|
||||
status.addFatalError(
|
||||
'Cannot inline async into sync*.', newLocation_fromNode(_node));
|
||||
return;
|
||||
}
|
||||
if (refElement is ExecutableElement) {
|
||||
var executable = refElement as ExecutableElement;
|
||||
if (!executable.returnType.isDartAsyncFuture) {
|
||||
status.addFatalError(
|
||||
'Cannot inline async into a function that does not return a Future.',
|
||||
newLocation_fromNode(_node));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ref._alreadyMadeAsync.add(body)) {
|
||||
SourceRange bodyStart = rangeStartLength(body.offset, 0);
|
||||
_addRefEdit(newSourceEdit_range(bodyStart, 'async '));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// may be invocation of inline method
|
||||
if (nodeParent is MethodInvocation) {
|
||||
MethodInvocation invocation = nodeParent;
|
||||
|
|
|
@ -66,6 +66,56 @@ class A {
|
|||
expect(refactoring.isDeclaration, isTrue);
|
||||
}
|
||||
|
||||
test_bad_async_intoSyncStar() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
Iterable<Future<int>> foo() sync* {
|
||||
yield test;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// error
|
||||
return _assertConditionsFatal('Cannot inline async into sync*.');
|
||||
}
|
||||
|
||||
test_bad_async_targetIsSync_doesNotReturnFuture() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
double foo() {
|
||||
test;
|
||||
return 1.2;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// error
|
||||
return _assertConditionsFatal(
|
||||
'Cannot inline async into a function that does not return a Future.');
|
||||
}
|
||||
|
||||
test_bad_asyncStar() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Stream<int> test() async* {
|
||||
yield 1;
|
||||
yield 2;
|
||||
}
|
||||
foo() {
|
||||
test();
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test() async*');
|
||||
// error
|
||||
return _assertConditionsFatal('Cannot inline a generator.');
|
||||
}
|
||||
|
||||
test_bad_cascadeInvocation() async {
|
||||
indexTestUnit(r'''
|
||||
class A {
|
||||
|
@ -711,6 +761,100 @@ main() {
|
|||
''');
|
||||
}
|
||||
|
||||
test_getter_async_targetIsAsync() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
Future<int> foo() async {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> foo() async {
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_getter_async_targetIsAsyncStar() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
Stream<int> foo() async {
|
||||
return await test;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Stream<int> foo() async {
|
||||
return await 42;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_getter_async_targetIsSync() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
Future<int> foo() {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> foo() async {
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_getter_async_targetIsSync2() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> get test async => 42;
|
||||
Future<int> foo1() {
|
||||
return test;
|
||||
}
|
||||
Future<int> foo2() {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> foo1() async {
|
||||
return 42;
|
||||
}
|
||||
Future<int> foo2() async {
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_getter_classMember_instance() {
|
||||
indexTestUnit(r'''
|
||||
class A {
|
||||
|
@ -803,6 +947,50 @@ main() {
|
|||
expect(refactoring.inlineAll, false);
|
||||
}
|
||||
|
||||
test_method_async() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> test() async => 42;
|
||||
Future<int> foo() {
|
||||
return test();
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test() async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> foo() async {
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_method_async2() {
|
||||
indexTestUnit(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future<int> test() async => 42;
|
||||
Future foo() {
|
||||
return [test(), test()];
|
||||
}
|
||||
}
|
||||
''');
|
||||
_createRefactoring('test() async');
|
||||
// validate change
|
||||
return _assertSuccessfulRefactoring(r'''
|
||||
import 'dart:async';
|
||||
class A {
|
||||
Future foo() async {
|
||||
return [42, 42];
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_method_emptyBody() {
|
||||
indexTestUnit(r'''
|
||||
abstract class A {
|
||||
|
|
Loading…
Reference in a new issue