mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:09:48 +00:00
[analyzer] Remove LSP fix-all-in-file functionality
To be replaced by new functionality that works with LSP + original protocol. Change-Id: I59627e2c4e99b0a6aa0eb850168c870e5390e03b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/186360 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
191e95fa3e
commit
8f9cdb3b2f
|
@ -68,13 +68,11 @@ abstract class Commands {
|
|||
organizeImports,
|
||||
sendWorkspaceEdit,
|
||||
performRefactor,
|
||||
fixAllOfErrorCodeInFile,
|
||||
];
|
||||
static const sortMembers = 'edit.sortMembers';
|
||||
static const organizeImports = 'edit.organizeImports';
|
||||
static const sendWorkspaceEdit = 'edit.sendWorkspaceEdit';
|
||||
static const performRefactor = 'refactor.perform';
|
||||
static const fixAllOfErrorCodeInFile = 'edit.fixAll.errorCodeInFile';
|
||||
}
|
||||
|
||||
abstract class CustomMethods {
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright (c) 2020, 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_generated.dart';
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
import 'package:analysis_server/src/lsp/constants.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
|
||||
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
|
||||
import 'package:analysis_server/src/lsp/mapping.dart';
|
||||
import 'package:analysis_server/src/lsp/progress.dart';
|
||||
import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
|
||||
import 'package:analysis_server/src/services/correction/change_workspace.dart';
|
||||
|
||||
/// This command allows a client to request request applying all fixes for a
|
||||
/// type of error.
|
||||
class FixAllOfErrorCodeInFileCommandHandler extends SimpleEditCommandHandler {
|
||||
FixAllOfErrorCodeInFileCommandHandler(LspAnalysisServer server)
|
||||
: super(server);
|
||||
|
||||
@override
|
||||
String get commandName => 'Fix All of Error Code in File';
|
||||
|
||||
@override
|
||||
Future<ErrorOr<void>> handle(List<dynamic> arguments,
|
||||
ProgressReporter reporter, CancellationToken cancellationToken) async {
|
||||
if (arguments == null ||
|
||||
arguments.length != 3 ||
|
||||
arguments[0] is! String ||
|
||||
arguments[1] is! String ||
|
||||
(arguments[2] is! int && arguments[2] != null)) {
|
||||
return ErrorOr.error(ResponseError(
|
||||
code: ServerErrorCodes.InvalidCommandArguments,
|
||||
message: '$commandName requires three arguments: '
|
||||
'1) an ErrorCode, '
|
||||
'2) a file path, '
|
||||
'3) a document version',
|
||||
));
|
||||
}
|
||||
|
||||
final errorCode = arguments[0] as String;
|
||||
final path = arguments[1] as String;
|
||||
final clientDocumentVersion = arguments[2] as int;
|
||||
|
||||
if (fileHasBeenModified(path, clientDocumentVersion)) {
|
||||
return fileModifiedError;
|
||||
}
|
||||
|
||||
final result = await requireResolvedUnit(path);
|
||||
|
||||
if (cancellationToken.isCancellationRequested) {
|
||||
return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
|
||||
}
|
||||
|
||||
return result.mapResult((result) async {
|
||||
final workspace = DartChangeWorkspace(server.currentSessions);
|
||||
final processor =
|
||||
BulkFixProcessor(server.instrumentationService, workspace);
|
||||
|
||||
final changeBuilder = await processor.fixOfTypeInUnit(result, errorCode);
|
||||
|
||||
final edit =
|
||||
createWorkspaceEdit(server, changeBuilder.sourceChange.edits);
|
||||
|
||||
return await sendWorkspaceEditToClient(edit);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ import 'package:analysis_server/src/lsp/mapping.dart';
|
|||
import 'package:analysis_server/src/protocol_server.dart' hide Position;
|
||||
import 'package:analysis_server/src/services/correction/assist.dart';
|
||||
import 'package:analysis_server/src/services/correction/assist_internal.dart';
|
||||
import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
|
||||
import 'package:analysis_server/src/services/correction/change_workspace.dart';
|
||||
import 'package:analysis_server/src/services/correction/fix.dart';
|
||||
import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
|
||||
|
@ -26,7 +25,6 @@ import 'package:analyzer/dart/analysis/session.dart'
|
|||
show InconsistentAnalysisException;
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
import 'package:collection/collection.dart' show groupBy;
|
||||
|
||||
class CodeActionHandler extends MessageHandler<CodeActionParams,
|
||||
|
@ -172,26 +170,6 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
|
|||
);
|
||||
}
|
||||
|
||||
/// Creates a CodeAction command to apply a particular fix for all instances of
|
||||
/// a specific error in the file for [path].
|
||||
CodeAction _createFixAllCommand(Fix fix, Diagnostic diagnostic, String path) {
|
||||
final title = 'Apply all: ${fix.change.message}';
|
||||
return CodeAction(
|
||||
title: title,
|
||||
kind: CodeActionKind.QuickFix,
|
||||
diagnostics: [diagnostic],
|
||||
command: Command(
|
||||
command: Commands.fixAllOfErrorCodeInFile,
|
||||
title: title,
|
||||
arguments: [
|
||||
diagnostic.code,
|
||||
path,
|
||||
server.getVersionedDocumentIdentifier(path).version
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Dedupes/merges actions that have the same title, selecting the one nearest [pos].
|
||||
///
|
||||
/// If actions perform the same edit/command, their diagnostics will be merged
|
||||
|
@ -312,7 +290,6 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
|
|||
) async {
|
||||
final lineInfo = unit.lineInfo;
|
||||
final codeActions = <CodeAction>[];
|
||||
final fixAllCodeActions = <CodeAction>[];
|
||||
final fixContributor = DartFixContributor();
|
||||
|
||||
try {
|
||||
|
@ -323,13 +300,6 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
|
|||
(errorCodeCounts[error.errorCode] ?? 0) + 1;
|
||||
}
|
||||
|
||||
// Because an error code may appear multiple times, cache the possible fixes
|
||||
// as we discover them to avoid re-computing them for a given diagnostic.
|
||||
final possibleFixesForErrorCode = <ErrorCode, Set<FixKind>>{};
|
||||
final workspace = DartChangeWorkspace(server.currentSessions);
|
||||
final processor =
|
||||
BulkFixProcessor(server.instrumentationService, workspace);
|
||||
|
||||
for (final error in unit.errors) {
|
||||
// Server lineNumber is one-based so subtract one.
|
||||
var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
|
||||
|
@ -358,35 +328,9 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
|
|||
codeActions.addAll(
|
||||
fixes.map((fix) => _createFixAction(fix, diagnostic)),
|
||||
);
|
||||
|
||||
// Only consider an apply-all if there's more than one of these errors.
|
||||
if (errorCodeCounts[error.errorCode] > 1) {
|
||||
// Find out which fixes the bulk processor can handle.
|
||||
possibleFixesForErrorCode[error.errorCode] ??=
|
||||
processor.producableFixesForError(unit, error).toSet();
|
||||
|
||||
// Get the intersection of single-fix kinds we created and those
|
||||
// the bulk processor can handle.
|
||||
final possibleFixes = possibleFixesForErrorCode[error.errorCode]
|
||||
.intersection(fixes.map((f) => f.kind).toSet())
|
||||
// Exclude data-driven fixes as they're more likely to apply
|
||||
// different fixes for the same error/fix kind that users
|
||||
// might not expect.
|
||||
..remove(DartFixKind.DATA_DRIVEN);
|
||||
|
||||
// Until we can apply a specific fix, only include apply-all when
|
||||
// there's exactly one.
|
||||
if (possibleFixes.length == 1) {
|
||||
fixAllCodeActions.addAll(fixes.map(
|
||||
(fix) => _createFixAllCommand(fix, diagnostic, unit.path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append all fix-alls to the very end.
|
||||
codeActions.addAll(fixAllCodeActions);
|
||||
|
||||
final dedupedActions = _dedupeActions(codeActions, range.start);
|
||||
|
||||
return dedupedActions
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
import 'package:analysis_server/src/lsp/constants.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/commands/fix_all_of_error_code_in_file.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/commands/organize_imports.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/commands/perform_refactor.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/commands/send_workspace_edit.dart';
|
||||
|
@ -25,8 +24,6 @@ class ExecuteCommandHandler
|
|||
Commands.organizeImports: OrganizeImportsCommandHandler(server),
|
||||
Commands.performRefactor: PerformRefactorCommandHandler(server),
|
||||
Commands.sendWorkspaceEdit: SendWorkspaceEditCommandHandler(server),
|
||||
Commands.fixAllOfErrorCodeInFile:
|
||||
FixAllOfErrorCodeInFileCommandHandler(server),
|
||||
},
|
||||
super(server);
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
import 'package:analysis_server/src/lsp/constants.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'server_abstract.dart';
|
||||
|
@ -77,11 +76,13 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
|
|||
|
||||
Future<Either2<Command, CodeAction>> getFixAllAction(
|
||||
String title, Uri uri, String content) async {
|
||||
final codeActions =
|
||||
await getCodeActions(uri.toString(), range: rangeFromMarkers(content));
|
||||
final fixAction =
|
||||
findCommand(codeActions, Commands.fixAllOfErrorCodeInFile, title);
|
||||
return fixAction;
|
||||
// TODO(dantup): Fix this once new server support has landed.
|
||||
throw UnimplementedError();
|
||||
// final codeActions =
|
||||
// await getCodeActions(uri.toString(), range: rangeFromMarkers(content));
|
||||
// final fixAction =
|
||||
// findCommand(codeActions, Commands.fixAllOfErrorCodeInFile, title);
|
||||
// return fixAction;
|
||||
}
|
||||
|
||||
/// Verifies that executing the given code actions command on the server
|
||||
|
|
|
@ -272,43 +272,10 @@ class FixesCodeActionsWithNullSafetyTest extends AbstractCodeActionsTest {
|
|||
@override
|
||||
String get testPackageLanguageVersion => latestLanguageVersion;
|
||||
|
||||
Future<void> test_fixAll_notForAmbigiousProducers() async {
|
||||
// The ReplaceWithIsEmpty producer does not provide a FixKind up-front, as
|
||||
// it may produce `REPLACE_WITH_IS_EMPTY` or `REPLACE_WITH_IS_NOT_EMPTY`
|
||||
// depending on the code.
|
||||
// This test ensures this does not crash, and does not produce an apply-all.
|
||||
registerLintRules();
|
||||
newFile(analysisOptionsPath, content: '''
|
||||
linter:
|
||||
rules:
|
||||
- prefer_is_empty
|
||||
''');
|
||||
|
||||
const content = '''
|
||||
var a = [];
|
||||
var b = a.[[length]] == 0;
|
||||
var c = a.length == 0;
|
||||
''';
|
||||
|
||||
newFile(mainFilePath, content: withoutMarkers(content));
|
||||
await initialize(
|
||||
textDocumentCapabilities: withCodeActionKinds(
|
||||
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
|
||||
);
|
||||
|
||||
final allFixes = await getCodeActions(mainFileUri.toString(),
|
||||
range: rangeFromMarkers(content));
|
||||
|
||||
// Expect only the single-fix, there should be no apply-all.
|
||||
expect(allFixes, hasLength(1));
|
||||
final fixTitle = allFixes.first.map((f) => f.title, (f) => f.title);
|
||||
expect(fixTitle, equals("Replace with \'isEmpty\'"));
|
||||
}
|
||||
|
||||
Future<void> test_fixAll_notWhenNoBatchFix() async {
|
||||
// Some fixes (for example 'create function foo') are not available in the
|
||||
// batch processor, so should not generate Apply-all fixes even if there
|
||||
// are multiple.
|
||||
// batch processor, so should not generate fix-all-in-file fixes even if there
|
||||
// are multiple instances.
|
||||
const content = '''
|
||||
var a = [[foo]]();
|
||||
var b = bar();
|
||||
|
@ -329,7 +296,10 @@ var b = bar();
|
|||
expect(fixTitle, equals("Create function 'foo'"));
|
||||
}
|
||||
|
||||
@failingTest
|
||||
Future<void> test_fixAll_notWhenSingle() async {
|
||||
// TODO(dantup): Fix the text used to locate the fix once the
|
||||
// new server support has landed.
|
||||
const content = '''
|
||||
void f(String a) {
|
||||
[[print(a!)]];
|
||||
|
@ -349,7 +319,10 @@ void f(String a) {
|
|||
expect(fixAction, isNull);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
Future<void> test_fixAll_whenMultiple() async {
|
||||
// TODO(dantup): Fix this test up to use the new server support for
|
||||
// fix-all-in-file once landed.
|
||||
const content = '''
|
||||
void f(String a) {
|
||||
[[print(a!!)]];
|
||||
|
|
Loading…
Reference in a new issue