mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:47:36 +00:00
Change LSP edit mapping to support multi-file edits
Change-Id: I1f29b8b49d27b4e3b7f44ea86aa1a33c7b6ee48b Reviewed-on: https://dart-review.googlesource.com/c/86926 Commit-Queue: Danny Tuppeny <dantup@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
566ae2490d
commit
1c1a5a99ed
|
@ -8,6 +8,7 @@ import 'package:analysis_server/src/lsp/constants.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/source_edits.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/error/error.dart' as engine;
|
||||
import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
|
||||
|
@ -34,9 +35,7 @@ abstract class SimpleEditCommandHandler
|
|||
|
||||
final workspaceEdit = toWorkspaceEdit(
|
||||
server.clientCapabilities?.workspace,
|
||||
docIdentifier,
|
||||
unit.lineInfo,
|
||||
edits,
|
||||
[new FileEditInformation(docIdentifier, unit.lineInfo, edits)],
|
||||
);
|
||||
|
||||
// Send the edit to the client via a applyEdit request (this is a request
|
||||
|
|
|
@ -14,6 +14,9 @@ import 'package:analysis_server/src/lsp/mapping.dart';
|
|||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
|
||||
|
||||
typedef ActionHandler = Future<List<Either2<Command, CodeAction>>> Function(
|
||||
HashSet<CodeActionKind>, bool, String, Range, ResolvedUnitResult);
|
||||
|
||||
class CodeActionHandler extends MessageHandler<CodeActionParams,
|
||||
List<Either2<Command, CodeAction>>> {
|
||||
CodeActionHandler(LspAnalysisServer server) : super(server);
|
||||
|
@ -53,71 +56,78 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
|
|||
clientSupportedCodeActionKinds,
|
||||
clientSupportsLiteralCodeActions,
|
||||
path.result,
|
||||
params.range,
|
||||
unit));
|
||||
}
|
||||
|
||||
List<Either2<Command, CodeAction>> _getAssistActions(
|
||||
Future<List<Either2<Command, CodeAction>>> _getAssistActions(
|
||||
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
|
||||
bool clientSupportsLiteralCodeActions,
|
||||
String path,
|
||||
Range range,
|
||||
ResolvedUnitResult unit,
|
||||
) {
|
||||
) async {
|
||||
// TODO(dantup): Implement assists.
|
||||
return [];
|
||||
}
|
||||
|
||||
ErrorOr<List<Either2<Command, CodeAction>>> _getCodeActions(
|
||||
Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
|
||||
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
|
||||
bool clientSupportsLiteralCodeActions,
|
||||
String path,
|
||||
Range range,
|
||||
ResolvedUnitResult unit,
|
||||
) {
|
||||
) async {
|
||||
// Join the results of computing all of our different types.
|
||||
final allActions = [
|
||||
final List<ActionHandler> handlers = [
|
||||
_getSourceActions,
|
||||
_getAssistActions,
|
||||
_getRefactorActions,
|
||||
_getFixActions,
|
||||
]
|
||||
.expand((f) => f(
|
||||
clientSupportedCodeActionKinds,
|
||||
clientSupportsLiteralCodeActions,
|
||||
path,
|
||||
unit,
|
||||
))
|
||||
.toList();
|
||||
|
||||
return success(allActions);
|
||||
];
|
||||
final futures = handlers.map((f) => f(
|
||||
clientSupportedCodeActionKinds,
|
||||
clientSupportsLiteralCodeActions,
|
||||
path,
|
||||
range,
|
||||
unit,
|
||||
));
|
||||
final results = await Future.wait(futures);
|
||||
final flatResults = results.expand((x) => x).toList();
|
||||
return success(flatResults);
|
||||
}
|
||||
|
||||
List<Either2<Command, CodeAction>> _getFixActions(
|
||||
Future<List<Either2<Command, CodeAction>>> _getFixActions(
|
||||
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
|
||||
bool clientSupportsLiteralCodeActions,
|
||||
String path,
|
||||
Range range,
|
||||
ResolvedUnitResult unit,
|
||||
) {
|
||||
) async {
|
||||
// TODO(dantup): Implement fixes.
|
||||
return [];
|
||||
}
|
||||
|
||||
List<Either2<Command, CodeAction>> _getRefactorActions(
|
||||
Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
|
||||
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
|
||||
bool clientSupportsLiteralCodeActions,
|
||||
String path,
|
||||
Range range,
|
||||
ResolvedUnitResult unit,
|
||||
) {
|
||||
) async {
|
||||
// TODO(dantup): Implement refactors.
|
||||
return [];
|
||||
}
|
||||
|
||||
/// Gets "Source" CodeActions, which are actions that apply to whole files of
|
||||
/// source such as Sort Members and Organise Imports.
|
||||
List<Either2<Command, CodeAction>> _getSourceActions(
|
||||
Future<List<Either2<Command, CodeAction>>> _getSourceActions(
|
||||
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
|
||||
bool clientSupportsLiteralCodeActions,
|
||||
String path,
|
||||
Range range,
|
||||
ResolvedUnitResult unit,
|
||||
) {
|
||||
) async {
|
||||
// The source actions supported are only valid for Dart files.
|
||||
if (!AnalysisEngine.isDartFileName(path)) {
|
||||
return [];
|
||||
|
|
|
@ -7,12 +7,14 @@ import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
|||
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
|
||||
import 'package:analysis_server/src/lsp/dartdoc.dart';
|
||||
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp;
|
||||
import 'package:analysis_server/src/lsp/source_edits.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as server
|
||||
hide AnalysisError;
|
||||
import 'package:analyzer/dart/analysis/results.dart' as server;
|
||||
import 'package:analyzer/error/error.dart' as server;
|
||||
import 'package:analyzer/source/line_info.dart' as server;
|
||||
import 'package:analyzer/src/generated/source.dart' as server;
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart' as server;
|
||||
|
||||
const languageSourceName = 'dart';
|
||||
|
||||
|
@ -486,14 +488,10 @@ lsp.SignatureHelp toSignatureHelp(List<lsp.MarkupKind> preferredFormats,
|
|||
);
|
||||
}
|
||||
|
||||
lsp.TextDocumentEdit toTextDocumentEdit(
|
||||
VersionedTextDocumentIdentifier doc,
|
||||
server.LineInfo lineInfo,
|
||||
List<server.SourceEdit> edits,
|
||||
) {
|
||||
lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
|
||||
return new TextDocumentEdit(
|
||||
doc,
|
||||
edits.map((e) => toTextEdit(lineInfo, e)).toList(),
|
||||
edit.doc,
|
||||
edit.edits.map((e) => toTextEdit(edit.lineInfo, e)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -506,9 +504,7 @@ lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
|
|||
|
||||
lsp.WorkspaceEdit toWorkspaceEdit(
|
||||
WorkspaceClientCapabilities capabilities,
|
||||
VersionedTextDocumentIdentifier doc,
|
||||
server.LineInfo lineInfo,
|
||||
List<server.SourceEdit> edits,
|
||||
List<FileEditInformation> edits,
|
||||
) {
|
||||
final clientSupportsTextDocumentEdits =
|
||||
capabilities?.workspaceEdit?.documentChanges == true;
|
||||
|
@ -520,23 +516,22 @@ lsp.WorkspaceEdit toWorkspaceEdit(
|
|||
List<
|
||||
Either4<TextDocumentEdit, CreateFile, RenameFile,
|
||||
DeleteFile>>>.t1(
|
||||
[toTextDocumentEdit(doc, lineInfo, edits)],
|
||||
edits.map(toTextDocumentEdit).toList(),
|
||||
));
|
||||
} else {
|
||||
return new WorkspaceEdit(
|
||||
toWorkspaceEditChanges(doc, lineInfo, edits), null);
|
||||
return new WorkspaceEdit(toWorkspaceEditChanges(edits), null);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, List<TextEdit>> toWorkspaceEditChanges(
|
||||
VersionedTextDocumentIdentifier doc,
|
||||
server.LineInfo lineInfo,
|
||||
List<server.SourceEdit> edits,
|
||||
) {
|
||||
// TODO(dantup): Fix codegen for WorkspaceEditChanges to be Map<String, TextEdit>
|
||||
return Map<String, List<TextEdit>>.fromEntries(
|
||||
edits.map((e) => new MapEntry(doc.uri, [toTextEdit(lineInfo, e)])),
|
||||
);
|
||||
List<FileEditInformation> edits) {
|
||||
createEdit(FileEditInformation file) {
|
||||
final edits =
|
||||
file.edits.map((edit) => toTextEdit(file.lineInfo, edit)).toList();
|
||||
return new MapEntry(file.doc.uri, edits);
|
||||
}
|
||||
|
||||
return Map<String, List<TextEdit>>.fromEntries(edits.map(createEdit));
|
||||
}
|
||||
|
||||
lsp.MarkupContent _asMarkup(
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
import 'package:analysis_server/src/lsp/mapping.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as server
|
||||
show SourceEdit;
|
||||
import 'package:analyzer/source/line_info.dart';
|
||||
import 'package:dart_style/dart_style.dart';
|
||||
|
||||
|
@ -59,3 +61,13 @@ List<TextEdit> generateEditsForFormatting(String unformattedSource) {
|
|||
)
|
||||
];
|
||||
}
|
||||
|
||||
/// Helper class that bundles up all information required when converting server
|
||||
/// SourceEdits into LSP-compatible WorkspaceEdits.
|
||||
class FileEditInformation {
|
||||
final VersionedTextDocumentIdentifier doc;
|
||||
final LineInfo lineInfo;
|
||||
final List<server.SourceEdit> edits;
|
||||
|
||||
FileEditInformation(this.doc, this.lineInfo, this.edits);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue