[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:
Danny Tuppeny 2021-02-22 19:53:39 +00:00 committed by commit-bot@chromium.org
parent 191e95fa3e
commit 8f9cdb3b2f
6 changed files with 15 additions and 171 deletions

View file

@ -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 {

View file

@ -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);
});
}
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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!!)]];