blob: 602b5227a87198fa7158e4bffa0e2dc087051f1b [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../shared/shared_code_actions_refactor_tests.dart';
import 'code_actions_mixin.dart';
import 'request_helpers_mixin.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtractMethodRefactorCodeActionsTest);
defineReflectiveTests(ExtractWidgetRefactorCodeActionsTest);
defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineLocalVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineMethodRefactorCodeActionsTest);
defineReflectiveTests(ConvertGetterToMethodCodeActionsTest);
defineReflectiveTests(ConvertMethodToGetterCodeActionsTest);
});
}
@reflectiveTest
class ConvertGetterToMethodCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedConvertGetterToMethodRefactorCodeActionsTests {}
@reflectiveTest
class ConvertMethodToGetterCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedConvertMethodToGetterRefactorCodeActionsTests {}
@reflectiveTest
class ExtractMethodRefactorCodeActionsTest extends RefactorCodeActionsTest
with
LspProgressNotificationsMixin,
// Most tests are defined in a shared mixin.
SharedExtractMethodRefactorCodeActionsTests {
Future<void> test_progress_clientProvided() async {
const content = '''
void f() {
print('Test!');
[!print('Test!');!]
}
''';
const expectedContent = '''
void f() {
print('Test!');
newMethod();
}
void newMethod() {
print('Test!');
}
''';
// Expect begin/end progress updates without a create, since the
// token was supplied by us (the client).
expect(progressUpdates, emitsInOrder(['BEGIN', 'END']));
await verifyCodeActionLiteralEdits(
content,
expectedContent,
command: Commands.performRefactor,
title: extractMethodTitle,
commandWorkDoneToken: clientProvidedTestWorkDoneToken,
);
}
Future<void> test_progress_notSupported() async {
const content = '''
void f() {
print('Test!');
[!print('Test!');!]
}
''';
const expectedContent = '''
void f() {
print('Test!');
newMethod();
}
void newMethod() {
print('Test!');
}
''';
var didGetProgressNotifications = false;
progressUpdates.listen((_) => didGetProgressNotifications = true);
await verifyCodeActionLiteralEdits(
content,
expectedContent,
command: Commands.performRefactor,
title: extractMethodTitle,
);
expect(didGetProgressNotifications, isFalse);
}
Future<void> test_progress_serverGenerated() async {
const content = '''
void f() {
print('Test!');
[!print('Test!');!]
}
''';
const expectedContent = '''
void f() {
print('Test!');
newMethod();
}
void newMethod() {
print('Test!');
}
''';
// Expect create/begin/end progress updates, because in this case the server
// generates the token.
expect(progressUpdates, emitsInOrder(['CREATE', 'BEGIN', 'END']));
setWorkDoneProgressSupport();
await verifyCodeActionLiteralEdits(
content,
expectedContent,
command: Commands.performRefactor,
title: extractMethodTitle,
);
}
/// Test if the client does not call refactor.validate it still gets a
/// sensible `showMessage` call and not a failed request.
Future<void> test_validLocation_failsInitialValidation_noValidation() async {
const content = '''
f() {
var a = 0;
doFoo([!() => print(a)!]);
print(a);
}
void doFoo(void Function() a) => a();
''';
var codeAction = await expectCodeActionLiteral(
content,
command: Commands.performRefactor,
title: extractMethodTitle,
);
var command = codeAction.command!;
// Call the refactor without any validation and expected an error message
// without a request failure.
var errorNotification = await expectErrorNotification(() async {
var response = await executeCommand(
Command(
title: command.title,
command: command.command,
arguments: command.arguments,
),
);
expect(response, isNull);
});
expect(
errorNotification.message,
contains('Cannot extract the closure as a method'),
);
}
}
@reflectiveTest
class ExtractVariableRefactorCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedExtractVariableRefactorCodeActionsTests {}
@reflectiveTest
class ExtractWidgetRefactorCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedExtractWidgetRefactorCodeActionsTests {}
@reflectiveTest
class InlineLocalVariableRefactorCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedInlineLocalVariableRefactorCodeActionsTests {}
@reflectiveTest
class InlineMethodRefactorCodeActionsTest extends RefactorCodeActionsTest
with
// Tests are defined in a shared mixin.
SharedInlineMethodRefactorCodeActionsTests {}
abstract class RefactorCodeActionsTest extends AbstractLspAnalysisServerTest
with LspSharedTestMixin, CodeActionsTestMixin {
@override
void setUp() {
super.setUp();
setApplyEditSupport();
setDocumentChangesSupport();
setSupportedCodeActionKinds([CodeActionKind.Refactor]);
}
}