Switch all generated LSP classes to use named constructor arguments

Change-Id: I111b58fa5d04314247d5f92650491cdeef6bd4a3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153841
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Danny Tuppeny <danny@tuppeny.com>
This commit is contained in:
Danny Tuppeny 2020-07-09 17:18:07 +00:00 committed by commit-bot@chromium.org
parent 6db0396c83
commit c4a2efd6e7
51 changed files with 1880 additions and 1318 deletions

View file

@ -22,6 +22,7 @@ import 'package:analysis_server/src/lsp/json_parsing.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart'
show listEqual, mapEqual;
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:meta/meta.dart';
const jsonEncoder = JsonEncoder.withIndent(' ');
@ -29,14 +30,14 @@ class AnalyzerStatusParams implements ToJsonable {
static const jsonHandler = LspJsonHandler(
AnalyzerStatusParams.canParse, AnalyzerStatusParams.fromJson);
AnalyzerStatusParams(this.isAnalyzing) {
AnalyzerStatusParams({@required this.isAnalyzing}) {
if (isAnalyzing == null) {
throw 'isAnalyzing is required but was not provided';
}
}
static AnalyzerStatusParams fromJson(Map<String, dynamic> json) {
final isAnalyzing = json['isAnalyzing'];
return AnalyzerStatusParams(isAnalyzing);
return AnalyzerStatusParams(isAnalyzing: isAnalyzing);
}
final bool isAnalyzing;
@ -98,7 +99,7 @@ class ClosingLabel implements ToJsonable {
static const jsonHandler =
LspJsonHandler(ClosingLabel.canParse, ClosingLabel.fromJson);
ClosingLabel(this.range, this.label) {
ClosingLabel({@required this.range, @required this.label}) {
if (range == null) {
throw 'range is required but was not provided';
}
@ -109,7 +110,7 @@ class ClosingLabel implements ToJsonable {
static ClosingLabel fromJson(Map<String, dynamic> json) {
final range = json['range'] != null ? Range.fromJson(json['range']) : null;
final label = json['label'];
return ClosingLabel(range, label);
return ClosingLabel(range: range, label: label);
}
final String label;
@ -190,8 +191,13 @@ class CompletionItemResolutionInfo implements ToJsonable {
CompletionItemResolutionInfo.canParse,
CompletionItemResolutionInfo.fromJson);
CompletionItemResolutionInfo(this.file, this.offset, this.libId,
this.displayUri, this.rOffset, this.rLength) {
CompletionItemResolutionInfo(
{@required this.file,
@required this.offset,
@required this.libId,
@required this.displayUri,
@required this.rOffset,
@required this.rLength}) {
if (file == null) {
throw 'file is required but was not provided';
}
@ -219,7 +225,12 @@ class CompletionItemResolutionInfo implements ToJsonable {
final rOffset = json['rOffset'];
final rLength = json['rLength'];
return CompletionItemResolutionInfo(
file, offset, libId, displayUri, rOffset, rLength);
file: file,
offset: offset,
libId: libId,
displayUri: displayUri,
rOffset: rOffset,
rLength: rLength);
}
final String displayUri;
@ -389,14 +400,14 @@ class DartDiagnosticServer implements ToJsonable {
static const jsonHandler = LspJsonHandler(
DartDiagnosticServer.canParse, DartDiagnosticServer.fromJson);
DartDiagnosticServer(this.port) {
DartDiagnosticServer({@required this.port}) {
if (port == null) {
throw 'port is required but was not provided';
}
}
static DartDiagnosticServer fromJson(Map<String, dynamic> json) {
final port = json['port'];
return DartDiagnosticServer(port);
return DartDiagnosticServer(port: port);
}
final num port;
@ -456,8 +467,13 @@ class DartDiagnosticServer implements ToJsonable {
class Element implements ToJsonable {
static const jsonHandler = LspJsonHandler(Element.canParse, Element.fromJson);
Element(this.range, this.name, this.kind, this.parameters,
this.typeParameters, this.returnType) {
Element(
{this.range,
@required this.name,
@required this.kind,
this.parameters,
this.typeParameters,
this.returnType}) {
if (name == null) {
throw 'name is required but was not provided';
}
@ -472,7 +488,13 @@ class Element implements ToJsonable {
final parameters = json['parameters'];
final typeParameters = json['typeParameters'];
final returnType = json['returnType'];
return Element(range, name, kind, parameters, typeParameters, returnType);
return Element(
range: range,
name: name,
kind: kind,
parameters: parameters,
typeParameters: typeParameters,
returnType: returnType);
}
final String kind;
@ -616,15 +638,15 @@ class FlutterOutline implements ToJsonable {
LspJsonHandler(FlutterOutline.canParse, FlutterOutline.fromJson);
FlutterOutline(
this.kind,
{@required this.kind,
this.label,
this.className,
this.variableName,
this.attributes,
this.dartElement,
this.range,
this.codeRange,
this.children) {
@required this.range,
@required this.codeRange,
this.children}) {
if (kind == null) {
throw 'kind is required but was not provided';
}
@ -655,8 +677,16 @@ class FlutterOutline implements ToJsonable {
?.map((item) => item != null ? FlutterOutline.fromJson(item) : null)
?.cast<FlutterOutline>()
?.toList();
return FlutterOutline(kind, label, className, variableName, attributes,
dartElement, range, codeRange, children);
return FlutterOutline(
kind: kind,
label: label,
className: className,
variableName: variableName,
attributes: attributes,
dartElement: dartElement,
range: range,
codeRange: codeRange,
children: children);
}
final List<FlutterOutlineAttribute> attributes;
@ -862,7 +892,8 @@ class FlutterOutlineAttribute implements ToJsonable {
static const jsonHandler = LspJsonHandler(
FlutterOutlineAttribute.canParse, FlutterOutlineAttribute.fromJson);
FlutterOutlineAttribute(this.name, this.label, this.valueRange) {
FlutterOutlineAttribute(
{@required this.name, @required this.label, this.valueRange}) {
if (name == null) {
throw 'name is required but was not provided';
}
@ -875,7 +906,8 @@ class FlutterOutlineAttribute implements ToJsonable {
final label = json['label'];
final valueRange =
json['valueRange'] != null ? Range.fromJson(json['valueRange']) : null;
return FlutterOutlineAttribute(name, label, valueRange);
return FlutterOutlineAttribute(
name: name, label: label, valueRange: valueRange);
}
final String label;
@ -973,7 +1005,11 @@ class FlutterOutlineAttribute implements ToJsonable {
class Outline implements ToJsonable {
static const jsonHandler = LspJsonHandler(Outline.canParse, Outline.fromJson);
Outline(this.element, this.range, this.codeRange, this.children) {
Outline(
{@required this.element,
@required this.range,
@required this.codeRange,
this.children}) {
if (element == null) {
throw 'element is required but was not provided';
}
@ -994,7 +1030,11 @@ class Outline implements ToJsonable {
?.map((item) => item != null ? Outline.fromJson(item) : null)
?.cast<Outline>()
?.toList();
return Outline(element, range, codeRange, children);
return Outline(
element: element,
range: range,
codeRange: codeRange,
children: children);
}
final List<Outline> children;
@ -1118,7 +1158,7 @@ class PublishClosingLabelsParams implements ToJsonable {
static const jsonHandler = LspJsonHandler(
PublishClosingLabelsParams.canParse, PublishClosingLabelsParams.fromJson);
PublishClosingLabelsParams(this.uri, this.labels) {
PublishClosingLabelsParams({@required this.uri, @required this.labels}) {
if (uri == null) {
throw 'uri is required but was not provided';
}
@ -1132,7 +1172,7 @@ class PublishClosingLabelsParams implements ToJsonable {
?.map((item) => item != null ? ClosingLabel.fromJson(item) : null)
?.cast<ClosingLabel>()
?.toList();
return PublishClosingLabelsParams(uri, labels);
return PublishClosingLabelsParams(uri: uri, labels: labels);
}
final List<ClosingLabel> labels;
@ -1219,7 +1259,7 @@ class PublishFlutterOutlineParams implements ToJsonable {
PublishFlutterOutlineParams.canParse,
PublishFlutterOutlineParams.fromJson);
PublishFlutterOutlineParams(this.uri, this.outline) {
PublishFlutterOutlineParams({@required this.uri, @required this.outline}) {
if (uri == null) {
throw 'uri is required but was not provided';
}
@ -1232,7 +1272,7 @@ class PublishFlutterOutlineParams implements ToJsonable {
final outline = json['outline'] != null
? FlutterOutline.fromJson(json['outline'])
: null;
return PublishFlutterOutlineParams(uri, outline);
return PublishFlutterOutlineParams(uri: uri, outline: outline);
}
final FlutterOutline outline;
@ -1314,7 +1354,7 @@ class PublishOutlineParams implements ToJsonable {
static const jsonHandler = LspJsonHandler(
PublishOutlineParams.canParse, PublishOutlineParams.fromJson);
PublishOutlineParams(this.uri, this.outline) {
PublishOutlineParams({@required this.uri, @required this.outline}) {
if (uri == null) {
throw 'uri is required but was not provided';
}
@ -1326,7 +1366,7 @@ class PublishOutlineParams implements ToJsonable {
final uri = json['uri'];
final outline =
json['outline'] != null ? Outline.fromJson(json['outline']) : null;
return PublishOutlineParams(uri, outline);
return PublishOutlineParams(uri: uri, outline: outline);
}
final Outline outline;

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@ ErrorOr<R> cancelled<R>([R t]) =>
error(ErrorCodes.RequestCancelled, 'Request was cancelled', null);
ErrorOr<R> error<R>(ErrorCodes code, String message, [String data]) =>
ErrorOr<R>.error(ResponseError(code, message, data));
ErrorOr<R>.error(ResponseError(code: code, message: message, data: data));
ErrorOr<R> failure<R>(ErrorOr<dynamic> error) => ErrorOr<R>.error(error.error);

View file

@ -119,10 +119,9 @@ class LspByteStreamServerChannel implements LspServerCommunicationChannel {
void _sendParseError() {
final error = ResponseMessage(
null,
null,
ResponseError(ErrorCodes.ParseError, 'Unable to parse message', null),
jsonRpcVersion);
error: ResponseError(
code: ErrorCodes.ParseError, message: 'Unable to parse message'),
jsonrpc: jsonRpcVersion);
sendResponse(error);
}

View file

@ -21,9 +21,9 @@ class OrganizeImportsCommandHandler extends SimpleEditCommandHandler {
Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
return ErrorOr.error(ResponseError(
ServerErrorCodes.InvalidCommandArguments,
'$commandName requires a single String parameter containing the path of a Dart file',
null,
code: ServerErrorCodes.InvalidCommandArguments,
message:
'$commandName requires a single String parameter containing the path of a Dart file',
));
}

View file

@ -33,9 +33,9 @@ class PerformRefactorCommandHandler extends SimpleEditCommandHandler {
(arguments[5] != null && arguments[5] is! Map<String, dynamic>)) {
// length
return ErrorOr.error(ResponseError(
ServerErrorCodes.InvalidCommandArguments,
'$commandName requires 6 parameters: RefactoringKind, docVersion, filePath, offset, length, options (optional)',
null,
code: ServerErrorCodes.InvalidCommandArguments,
message:
'$commandName requires 6 parameters: RefactoringKind, docVersion, filePath, offset, length, options (optional)',
));
}

View file

@ -29,9 +29,9 @@ class SendWorkspaceEditCommandHandler extends SimpleEditCommandHandler {
arguments.length != 1 ||
arguments[0] is! Map<String, dynamic>) {
return ErrorOr.error(ResponseError(
ServerErrorCodes.InvalidCommandArguments,
'$commandName requires a single List argument of WorkspaceEdit',
null,
code: ServerErrorCodes.InvalidCommandArguments,
message:
'$commandName requires a single List argument of WorkspaceEdit',
));
}

View file

@ -52,7 +52,7 @@ abstract class SimpleEditCommandHandler
// Send the edit to the client via a applyEdit request (this is a request
// from server -> client and the client will provide a response).
final editResponse = await server.sendRequest(Method.workspace_applyEdit,
ApplyWorkspaceEditParams(commandName, workspaceEdit));
ApplyWorkspaceEditParams(label: commandName, edit: workspaceEdit));
if (editResponse.error != null) {
return error(

View file

@ -21,9 +21,9 @@ class SortMembersCommandHandler extends SimpleEditCommandHandler {
Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
return ErrorOr.error(ResponseError(
ServerErrorCodes.InvalidCommandArguments,
'$commandName requires a single String parameter containing the path of a Dart file',
null,
code: ServerErrorCodes.InvalidCommandArguments,
message:
'$commandName requires a single String parameter containing the path of a Dart file',
));
}
@ -37,9 +37,8 @@ class SortMembersCommandHandler extends SimpleEditCommandHandler {
final result = await driver?.parseFile(path);
if (result == null) {
return ErrorOr.error(ResponseError(
ServerErrorCodes.FileNotAnalyzed,
'$commandName is only available for analyzed files',
null,
code: ServerErrorCodes.FileNotAnalyzed,
message: '$commandName is only available for analyzed files',
));
}
final code = result.content;
@ -47,9 +46,10 @@ class SortMembersCommandHandler extends SimpleEditCommandHandler {
if (hasScanParseErrors(result.errors)) {
return ErrorOr.error(ResponseError(
ServerErrorCodes.FileHasErrors,
'Unable to $commandName because the file contains parse errors',
path,
code: ServerErrorCodes.FileHasErrors,
message:
'Unable to $commandName because the file contains parse errors',
data: path,
));
}

View file

@ -24,6 +24,6 @@ class DiagnosticServerHandler
Future<ErrorOr<DartDiagnosticServer>> handle(
void _, CancellationToken token) async {
final port = await server.diagnosticServer.getServerPort();
return success(DartDiagnosticServer(port));
return success(DartDiagnosticServer(port: port));
}
}

View file

@ -89,7 +89,7 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
) {
return clientSupportsLiteralCodeActions
? Either2<Command, CodeAction>.t2(
CodeAction(command.title, kind, null, false, null, command),
CodeAction(title: command.title, kind: kind, command: command),
)
: Either2<Command, CodeAction>.t1(command);
}
@ -100,12 +100,10 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
/// before the version number is read.
CodeAction _createAssistAction(Assist assist) {
return CodeAction(
assist.change.message,
toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
const [],
false,
createWorkspaceEdit(server, assist.change.edits),
null,
title: assist.change.message,
kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
diagnostics: const [],
edit: createWorkspaceEdit(server, assist.change.edits),
);
}
@ -115,12 +113,10 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
/// before the version number is read.
CodeAction _createFixAction(Fix fix, Diagnostic diagnostic) {
return CodeAction(
fix.change.message,
toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
[diagnostic],
false,
createWorkspaceEdit(server, fix.change.edits),
null,
title: fix.change.message,
kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
diagnostics: [diagnostic],
edit: createWorkspaceEdit(server, fix.change.edits),
);
}
@ -139,13 +135,12 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
// Build a new CodeAction that merges the diagnostics from each same
// code action onto a single one.
return CodeAction(
first.title,
first.kind,
title: first.title,
kind: first.kind,
// Merge diagnostics from all of the CodeActions.
groups[edit].expand((r) => r.diagnostics).toList(),
false,
first.edit,
first.command);
diagnostics: groups[edit].expand((r) => r.diagnostics).toList(),
edit: first.edit,
command: first.command);
}).toList();
}
@ -294,14 +289,18 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
return _commandOrCodeAction(
clientSupportsLiteralCodeActions,
actionKind,
Command(name, Commands.performRefactor, [
refactorKind.toJson(),
path,
server.getVersionedDocumentIdentifier(path).version,
offset,
length,
options,
]));
Command(
title: name,
command: Commands.performRefactor,
arguments: [
refactorKind.toJson(),
path,
server.getVersionedDocumentIdentifier(path).version,
offset,
length,
options,
],
));
}
try {
@ -360,12 +359,18 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
_commandOrCodeAction(
clientSupportsLiteralCodeActions,
DartCodeActionKind.SortMembers,
Command('Sort Members', Commands.sortMembers, [path]),
Command(
title: 'Sort Members',
command: Commands.sortMembers,
arguments: [path]),
),
_commandOrCodeAction(
clientSupportsLiteralCodeActions,
CodeActionKind.SourceOrganizeImports,
Command('Organize Imports', Commands.organizeImports, [path]),
Command(
title: 'Organize Imports',
command: Commands.organizeImports,
arguments: [path]),
),
];
}

View file

@ -135,7 +135,9 @@ class CompletionResolveHandler
if (otherFilesChanges.isNotEmpty) {
final workspaceEdit = createWorkspaceEdit(server, otherFilesChanges);
command = Command(
'Add import', Commands.sendWorkspaceEdit, [workspaceEdit]);
title: 'Add import',
command: Commands.sendWorkspaceEdit,
arguments: [workspaceEdit]);
}
// Documentation is added on during resolve for LSP.
@ -146,36 +148,36 @@ class CompletionResolveHandler
final documentation = asStringOrMarkupContent(formats, dartDoc);
return success(CompletionItem(
item.label,
item.kind,
null, // TODO(dantup): CompletionItemTags (eg. deprecated)
data.displayUri != null && thisFilesChanges.isNotEmpty
label: item.label,
kind: item.kind,
tags: null, // TODO(dantup): CompletionItemTags (eg. deprecated)
detail: data.displayUri != null && thisFilesChanges.isNotEmpty
? "Auto import from '${data.displayUri}'\n\n${item.detail ?? ''}"
.trim()
: item.detail,
documentation,
documentation: documentation,
// The deprecated field is deprecated, but we should still supply it
// for clients that have not adopted CompletionItemTags.
// ignore: deprecated_member_use_from_same_package
item.deprecated,
item.preselect,
item.sortText,
item.filterText,
newInsertText,
item.insertTextFormat,
TextEdit(
deprecated: item.deprecated,
preselect: item.preselect,
sortText: item.sortText,
filterText: item.filterText,
insertText: newInsertText,
insertTextFormat: item.insertTextFormat,
textEdit: TextEdit(
// TODO(dantup): If `clientSupportsSnippets == true` then we should map
// `selection` in to a snippet (see how Dart Code does this).
toRange(lineInfo, item.data.rOffset, item.data.rLength),
newInsertText,
range: toRange(lineInfo, item.data.rOffset, item.data.rLength),
newText: newInsertText,
),
thisFilesChanges
additionalTextEdits: thisFilesChanges
.expand((change) =>
change.edits.map((edit) => toTextEdit(lineInfo, edit)))
.toList(),
item.commitCharacters,
command ?? item.command,
item.data,
commitCharacters: item.commitCharacters,
command: command ?? item.command,
data: item.data,
));
} on InconsistentAnalysisException {
// Loop around to try again.

View file

@ -80,14 +80,15 @@ class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams,
Outline outline,
) {
return DocumentSymbol(
toElementName(outline.element),
outline.element.parameters,
elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind),
outline.element.isDeprecated,
toRange(lineInfo, outline.codeOffset, outline.codeLength),
toRange(lineInfo, outline.element.location.offset,
name: toElementName(outline.element),
detail: outline.element.parameters,
kind: elementKindToSymbolKind(
clientSupportedSymbolKinds, outline.element.kind),
deprecated: outline.element.isDeprecated,
range: toRange(lineInfo, outline.codeOffset, outline.codeLength),
selectionRange: toRange(lineInfo, outline.element.location.offset,
outline.element.location.length),
outline.children
children: outline.children
?.map((child) =>
_asDocumentSymbol(clientSupportedSymbolKinds, lineInfo, child))
?.toList(),
@ -102,15 +103,16 @@ class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams,
Outline outline,
) {
return SymbolInformation(
toElementName(outline.element),
elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind),
outline.element.isDeprecated,
Location(
documentUri,
toRange(lineInfo, outline.element.location.offset,
name: toElementName(outline.element),
kind: elementKindToSymbolKind(
clientSupportedSymbolKinds, outline.element.kind),
deprecated: outline.element.isDeprecated,
location: Location(
uri: documentUri,
range: toRange(lineInfo, outline.element.location.offset,
outline.element.location.length),
),
containerName,
containerName: containerName,
);
}

View file

@ -78,8 +78,9 @@ class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover> {
final formats =
server?.clientCapabilities?.textDocument?.hover?.contentFormat;
return Hover(
asStringOrMarkupContent(formats, content.toString().trimRight()),
toRange(lineInfo, hover.offset, hover.length),
contents:
asStringOrMarkupContent(formats, content.toString().trimRight()),
range: toRange(lineInfo, hover.offset, hover.length),
);
}

View file

@ -82,8 +82,9 @@ class ImplementationHandler
item.memberElement?.location ?? item.classElement?.location;
final lineInfo = server.getLineInfo(elementLocation.file);
return Location(
Uri.file(elementLocation.file).toString(),
toRange(lineInfo, elementLocation.offset, elementLocation.length),
uri: Uri.file(elementLocation.file).toString(),
range:
toRange(lineInfo, elementLocation.offset, elementLocation.length),
);
}).toList();

View file

@ -64,10 +64,10 @@ class InitializeMessageHandler
}
return success(InitializeResult(
server.capabilities,
InitializeResultServerInfo(
'Dart SDK LSP Analysis Server',
sdkVersion,
capabilities: server.capabilities,
serverInfo: InitializeResultServerInfo(
name: 'Dart SDK LSP Analysis Server',
version: sdkVersion,
),
));
}

View file

@ -55,7 +55,7 @@ class PrepareRenameHandler
}
return success(RangeAndPlaceholder(
toRange(
range: toRange(
unit.result.lineInfo,
// If the offset is set to -1 it means there is no location for the
// old name. However since we must provide a range for LSP, we'll use
@ -64,7 +64,7 @@ class PrepareRenameHandler
refactorDetails.offset == -1 ? offset : refactorDetails.offset,
refactorDetails.length,
),
refactoring.oldName,
placeholder: refactoring.oldName,
));
});
}

View file

@ -149,8 +149,8 @@ class TextDocumentOpenHandler
// We don't get a VersionedTextDocumentIdentifier with a didOpen but we
// do get the necessary info to create one.
server.documentVersions[path] = VersionedTextDocumentIdentifier(
params.textDocument.version,
params.textDocument.uri,
version: params.textDocument.version,
uri: params.textDocument.uri,
);
server.onOverlayCreated(path, doc.text);

View file

@ -93,8 +93,8 @@ class WorkspaceSymbolHandler
declaration.codeLength,
);
final location = Location(
Uri.file(filePath).toString(),
range,
uri: Uri.file(filePath).toString(),
range: range,
);
final hasParameters =
@ -103,10 +103,10 @@ class WorkspaceSymbolHandler
hasParameters ? (declaration.parameters == '()' ? '()' : '(…)') : '';
return SymbolInformation(
'${declaration.name}$nameSuffix',
kind,
null, // We don't have easy access to isDeprecated here.
location,
declaration.className ?? declaration.mixinName);
name: '${declaration.name}$nameSuffix',
kind: kind,
deprecated: null, // We don't have easy access to isDeprecated here.
location: location,
containerName: declaration.className ?? declaration.mixinName);
}
}

View file

@ -182,8 +182,8 @@ class LspAnalysisServer extends AbstractAnalysisServer {
// others (for example "flutter").
final response = await sendRequest(
Method.workspace_configuration,
ConfigurationParams([
ConfigurationItem(null, 'dart'),
ConfigurationParams(items: [
ConfigurationItem(section: 'dart'),
]));
final result = response.result;
@ -218,7 +218,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
/// version is not known.
VersionedTextDocumentIdentifier getVersionedDocumentIdentifier(String path) {
return documentVersions[path] ??
VersionedTextDocumentIdentifier(null, Uri.file(path).toString());
VersionedTextDocumentIdentifier(uri: Uri.file(path).toString());
}
void handleClientConnection(
@ -269,7 +269,9 @@ class LspAnalysisServer extends AbstractAnalysisServer {
sendErrorResponse(message, result.error);
} else {
channel.sendResponse(ResponseMessage(
message.id, result.result, null, jsonRpcVersion));
id: message.id,
result: result.result,
jsonrpc: jsonRpcVersion));
}
} else if (message is NotificationMessage) {
final result = await messageHandler.handleMessage(message);
@ -290,9 +292,8 @@ class LspAnalysisServer extends AbstractAnalysisServer {
sendErrorResponse(
message,
ResponseError(
ServerErrorCodes.UnhandledError,
errorMessage,
null,
code: ServerErrorCodes.UnhandledError,
message: errorMessage,
));
logException(errorMessage, error, stackTrace);
}
@ -303,9 +304,9 @@ class LspAnalysisServer extends AbstractAnalysisServer {
/// Logs the error on the client using window/logMessage.
void logErrorToClient(String message) {
channel.sendNotification(NotificationMessage(
Method.window_logMessage,
LogMessageParams(MessageType.Error, message),
jsonRpcVersion,
method: Method.window_logMessage,
params: LogMessageParams(type: MessageType.Error, message: message),
jsonrpc: jsonRpcVersion,
));
}
@ -366,44 +367,45 @@ class LspAnalysisServer extends AbstractAnalysisServer {
}
void publishClosingLabels(String path, List<ClosingLabel> labels) {
final params =
PublishClosingLabelsParams(Uri.file(path).toString(), labels);
final params = PublishClosingLabelsParams(
uri: Uri.file(path).toString(), labels: labels);
final message = NotificationMessage(
CustomMethods.PublishClosingLabels,
params,
jsonRpcVersion,
method: CustomMethods.PublishClosingLabels,
params: params,
jsonrpc: jsonRpcVersion,
);
sendNotification(message);
}
void publishDiagnostics(String path, List<Diagnostic> errors) {
final params =
PublishDiagnosticsParams(Uri.file(path).toString(), null, errors);
final params = PublishDiagnosticsParams(
uri: Uri.file(path).toString(), diagnostics: errors);
final message = NotificationMessage(
Method.textDocument_publishDiagnostics,
params,
jsonRpcVersion,
method: Method.textDocument_publishDiagnostics,
params: params,
jsonrpc: jsonRpcVersion,
);
sendNotification(message);
}
void publishFlutterOutline(String path, FlutterOutline outline) {
final params =
PublishFlutterOutlineParams(Uri.file(path).toString(), outline);
final params = PublishFlutterOutlineParams(
uri: Uri.file(path).toString(), outline: outline);
final message = NotificationMessage(
CustomMethods.PublishFlutterOutline,
params,
jsonRpcVersion,
method: CustomMethods.PublishFlutterOutline,
params: params,
jsonrpc: jsonRpcVersion,
);
sendNotification(message);
}
void publishOutline(String path, Outline outline) {
final params = PublishOutlineParams(Uri.file(path).toString(), outline);
final params =
PublishOutlineParams(uri: Uri.file(path).toString(), outline: outline);
final message = NotificationMessage(
CustomMethods.PublishOutline,
params,
jsonRpcVersion,
method: CustomMethods.PublishOutline,
params: params,
jsonrpc: jsonRpcVersion,
);
sendNotification(message);
}
@ -418,8 +420,8 @@ class LspAnalysisServer extends AbstractAnalysisServer {
void sendErrorResponse(Message message, ResponseError error) {
if (message is RequestMessage) {
channel.sendResponse(
ResponseMessage(message.id, null, error, jsonRpcVersion));
channel.sendResponse(ResponseMessage(
id: message.id, error: error, jsonrpc: jsonRpcVersion));
} else if (message is ResponseMessage) {
// For bad response messages where we can't respond with an error, send it
// as show instead of log.
@ -456,10 +458,10 @@ class LspAnalysisServer extends AbstractAnalysisServer {
completers[requestId] = completer;
channel.sendRequest(RequestMessage(
Either2<num, String>.t1(requestId),
method,
params,
jsonRpcVersion,
id: Either2<num, String>.t1(requestId),
method: method,
params: params,
jsonrpc: jsonRpcVersion,
));
return completer.future;
@ -485,9 +487,9 @@ class LspAnalysisServer extends AbstractAnalysisServer {
/// the [status] information.
void sendStatusNotification(nd.AnalysisStatus status) {
channel.sendNotification(NotificationMessage(
CustomMethods.AnalyzerStatus,
AnalyzerStatusParams(status.isAnalyzing),
jsonRpcVersion,
method: CustomMethods.AnalyzerStatus,
params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
jsonrpc: jsonRpcVersion,
));
}
@ -539,9 +541,9 @@ class LspAnalysisServer extends AbstractAnalysisServer {
void showMessageToUser(MessageType type, String message) {
channel.sendNotification(NotificationMessage(
Method.window_showMessage,
ShowMessageParams(type, message),
jsonRpcVersion,
method: Method.window_showMessage,
params: ShowMessageParams(type: type, message: message),
jsonrpc: jsonRpcVersion,
));
}

View file

@ -46,19 +46,19 @@ class LspSocketServer implements AbstractSocketServer {
void createAnalysisServer(LspServerCommunicationChannel serverChannel) {
if (analysisServer != null) {
final error = ResponseError(
ServerErrorCodes.ServerAlreadyStarted,
'Server already started',
null,
code: ServerErrorCodes.ServerAlreadyStarted,
message: 'Server already started',
);
serverChannel.sendNotification(NotificationMessage(
Method.window_showMessage,
ShowMessageParams(MessageType.Error, error.message),
jsonRpcVersion,
method: Method.window_showMessage,
params:
ShowMessageParams(type: MessageType.Error, message: error.message),
jsonrpc: jsonRpcVersion,
));
serverChannel.listen((Message message) {
if (message is RequestMessage) {
serverChannel.sendResponse(
ResponseMessage(message.id, null, error, jsonRpcVersion));
serverChannel.sendResponse(ResponseMessage(
id: message.id, error: error, jsonrpc: jsonRpcVersion));
}
});
return;

View file

@ -241,34 +241,32 @@ lsp.CompletionItem declarationToCompletionItem(
// the generated JSON as much as possible - for example using nulls in place
// of empty lists/false where possible.
return lsp.CompletionItem(
label,
completionKind,
null, // TODO(dantup): CompletionItemTags
getDeclarationCompletionDetail(declaration, completionKind, useDeprecated),
null, // documentation - will be added during resolve.
useDeprecated && declaration.isDeprecated ? true : null,
null, // preselect
label: label,
kind: completionKind,
tags: null, // TODO(dantup): CompletionItemTags
detail: getDeclarationCompletionDetail(
declaration, completionKind, useDeprecated),
deprecated: useDeprecated && declaration.isDeprecated ? true : null,
// Relevance is a number, highest being best. LSP does text sort so subtract
// from a large number so that a text sort will result in the correct order.
// 555 -> 999455
// 10 -> 999990
// 1 -> 999999
(1000000 - itemRelevance).toString(),
filterText != label ? filterText : null, // filterText uses label if not set
insertText != label ? insertText : null, // insertText uses label if not set
null, // insertTextFormat (we always use plain text so can ommit this)
null, // textEdit - added on during resolve
null, // additionalTextEdits, used for adding imports, etc.
null, // commitCharacters
null, // command
sortText: (1000000 - itemRelevance).toString(),
filterText: filterText != label
? filterText
: null, // filterText uses label if not set
insertText: insertText != label
? insertText
: null, // insertText uses label if not set
// data, used for completionItem/resolve.
lsp.CompletionItemResolutionInfo(
file,
offset,
includedSuggestionSet.id,
includedSuggestionSet.displayUri ?? library.uri?.toString(),
replacementOffset,
replacementLength),
data: lsp.CompletionItemResolutionInfo(
file: file,
offset: offset,
libId: includedSuggestionSet.id,
displayUri: includedSuggestionSet.displayUri ?? library.uri?.toString(),
rOffset: replacementOffset,
rLength: replacementLength),
);
}
@ -510,8 +508,8 @@ lsp.Location navigationTargetToLocation(String targetFilePath,
}
return lsp.Location(
Uri.file(targetFilePath).toString(),
toRange(lineInfo, target.offset, target.length),
uri: Uri.file(targetFilePath).toString(),
range: toRange(lineInfo, target.offset, target.length),
);
}
@ -527,16 +525,17 @@ ErrorOr<String> pathOfDocItem(lsp.TextDocumentItem doc) =>
ErrorOr<String> pathOfUri(Uri uri) {
if (uri == null) {
return ErrorOr<String>.error(ResponseError(
lsp.ServerErrorCodes.InvalidFilePath,
'Document URI was not supplied',
null));
code: lsp.ServerErrorCodes.InvalidFilePath,
message: 'Document URI was not supplied',
));
}
final isValidFileUri = (uri?.isScheme('file') ?? false);
if (!isValidFileUri) {
return ErrorOr<String>.error(ResponseError(
lsp.ServerErrorCodes.InvalidFilePath,
'URI was not a valid file:// URI',
uri.toString()));
code: lsp.ServerErrorCodes.InvalidFilePath,
message: 'URI was not a valid file:// URI',
data: uri.toString(),
));
}
try {
return ErrorOr<String>.success(uri.toFilePath());
@ -544,9 +543,9 @@ ErrorOr<String> pathOfUri(Uri uri) {
// Even if tryParse() works and file == scheme, toFilePath() can throw on
// Windows if there are invalid characters.
return ErrorOr<String>.error(ResponseError(
lsp.ServerErrorCodes.InvalidFilePath,
'File URI did not contain a valid file path',
uri.toString()));
code: lsp.ServerErrorCodes.InvalidFilePath,
message: 'File URI did not contain a valid file path',
data: uri.toString()));
}
}
@ -569,13 +568,13 @@ lsp.Diagnostic pluginToDiagnostic(
var lineInfo = getLineInfo(error.location.file);
return lsp.Diagnostic(
toRange(lineInfo, error.location.offset, error.location.length),
pluginToDiagnosticSeverity(error.severity),
error.code,
languageSourceName,
message,
null, // TODO(dantup): DiagnosticTags
relatedInformation,
range: toRange(lineInfo, error.location.offset, error.location.length),
severity: pluginToDiagnosticSeverity(error.severity),
code: error.code,
source: languageSourceName,
message: message,
tags: null, // TODO(dantup): DiagnosticTags
relatedInformation: relatedInformation,
);
}
@ -585,15 +584,15 @@ lsp.DiagnosticRelatedInformation pluginToDiagnosticRelatedInformation(
var file = message.location.file;
var lineInfo = getLineInfo(file);
return lsp.DiagnosticRelatedInformation(
lsp.Location(
Uri.file(file).toString(),
toRange(
location: lsp.Location(
uri: Uri.file(file).toString(),
range: toRange(
lineInfo,
message.location.offset,
message.location.length,
),
),
message.message);
message: message.message);
}
lsp.DiagnosticSeverity pluginToDiagnosticSeverity(
@ -623,8 +622,8 @@ lsp.Location searchResultToLocation(
}
return lsp.Location(
Uri.file(result.location.file).toString(),
toRange(lineInfo, location.offset, location.length),
uri: Uri.file(result.location.file).toString(),
range: toRange(lineInfo, location.offset, location.length),
);
}
@ -677,7 +676,8 @@ lsp.CompletionItemKind suggestionKindToCompletionItemKind(
lsp.ClosingLabel toClosingLabel(
server.LineInfo lineInfo, server.ClosingLabel label) =>
lsp.ClosingLabel(
toRange(lineInfo, label.offset, label.length), label.label);
range: toRange(lineInfo, label.offset, label.length),
label: label.label);
CodeActionKind toCodeActionKind(String id, lsp.CodeActionKind fallback) {
if (id == null) {
@ -749,32 +749,32 @@ lsp.CompletionItem toCompletionItem(
// the generated JSON as much as possible - for example using nulls in place
// of empty lists/false where possible.
return lsp.CompletionItem(
label,
completionKind,
null, // TODO(dantup): CompletionItemTags
getCompletionDetail(suggestion, completionKind, useDeprecated),
asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)),
useDeprecated && suggestion.isDeprecated ? true : null,
null, // preselect
label: label,
kind: completionKind,
tags: null, // TODO(dantup): CompletionItemTags
detail: getCompletionDetail(suggestion, completionKind, useDeprecated),
documentation:
asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)),
deprecated: useDeprecated && suggestion.isDeprecated ? true : null,
// Relevance is a number, highest being best. LSP does text sort so subtract
// from a large number so that a text sort will result in the correct order.
// 555 -> 999455
// 10 -> 999990
// 1 -> 999999
(1000000 - suggestion.relevance).toString(),
filterText != label ? filterText : null, // filterText uses label if not set
insertText != label ? insertText : null, // insertText uses label if not set
insertTextFormat != lsp.InsertTextFormat.PlainText
sortText: (1000000 - suggestion.relevance).toString(),
filterText: filterText != label
? filterText
: null, // filterText uses label if not set
insertText: insertText != label
? insertText
: null, // insertText uses label if not set
insertTextFormat: insertTextFormat != lsp.InsertTextFormat.PlainText
? insertTextFormat
: null, // Defaults to PlainText if not supplied
lsp.TextEdit(
toRange(lineInfo, replacementOffset, replacementLength),
insertText,
textEdit: lsp.TextEdit(
range: toRange(lineInfo, replacementOffset, replacementLength),
newText: insertText,
),
null, // additionalTextEdits, used for adding imports, etc.
null, // commitCharacters
null, // command
null, // data, useful for if using lazy resolve, this comes back to us
);
}
@ -799,13 +799,13 @@ lsp.Diagnostic toDiagnostic(
}
return lsp.Diagnostic(
toRange(result.lineInfo, error.offset, error.length),
toDiagnosticSeverity(errorSeverity),
errorCode.name.toLowerCase(),
languageSourceName,
message,
null, // TODO(dantup): DiagnosticTags
relatedInformation,
range: toRange(result.lineInfo, error.offset, error.length),
severity: toDiagnosticSeverity(errorSeverity),
code: errorCode.name.toLowerCase(),
source: languageSourceName,
message: message,
tags: null, // TODO(dantup): DiagnosticTags
relatedInformation: relatedInformation,
);
}
@ -814,15 +814,15 @@ lsp.DiagnosticRelatedInformation toDiagnosticRelatedInformation(
var file = message.filePath;
var lineInfo = result.session.getFile(file).lineInfo;
return lsp.DiagnosticRelatedInformation(
lsp.Location(
Uri.file(file).toString(),
toRange(
location: lsp.Location(
uri: Uri.file(file).toString(),
range: toRange(
lineInfo,
message.offset,
message.length,
),
),
message.message);
message: message.message);
}
lsp.DiagnosticSeverity toDiagnosticSeverity(server.ErrorSeverity severity) {
@ -844,14 +844,14 @@ lsp.DiagnosticSeverity toDiagnosticSeverity(server.ErrorSeverity severity) {
lsp.Element toElement(server.LineInfo lineInfo, server.Element element) =>
lsp.Element(
element.location != null
range: element.location != null
? toRange(lineInfo, element.location.offset, element.location.length)
: null,
toElementName(element),
element.kind.name,
element.parameters,
element.typeParameters,
element.returnType,
name: toElementName(element),
kind: element.kind.name,
parameters: element.parameters,
typeParameters: element.typeParameters,
returnType: element.returnType,
);
String toElementName(server.Element element) {
@ -865,22 +865,22 @@ String toElementName(server.Element element) {
lsp.FlutterOutline toFlutterOutline(
server.LineInfo lineInfo, server.FlutterOutline outline) =>
lsp.FlutterOutline(
outline.kind.name,
outline.label,
outline.className,
outline.variableName,
outline.attributes != null
kind: outline.kind.name,
label: outline.label,
className: outline.className,
variableName: outline.variableName,
attributes: outline.attributes != null
? outline.attributes
.map(
(attribute) => toFlutterOutlineAttribute(lineInfo, attribute))
.toList()
: null,
outline.dartElement != null
dartElement: outline.dartElement != null
? toElement(lineInfo, outline.dartElement)
: null,
toRange(lineInfo, outline.offset, outline.length),
toRange(lineInfo, outline.codeOffset, outline.codeLength),
outline.children != null
range: toRange(lineInfo, outline.offset, outline.length),
codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
children: outline.children != null
? outline.children.map((c) => toFlutterOutline(lineInfo, c)).toList()
: null,
);
@ -888,9 +888,9 @@ lsp.FlutterOutline toFlutterOutline(
lsp.FlutterOutlineAttribute toFlutterOutlineAttribute(
server.LineInfo lineInfo, server.FlutterOutlineAttribute attribute) =>
lsp.FlutterOutlineAttribute(
attribute.name,
attribute.label,
attribute.valueLocation != null
name: attribute.name,
label: attribute.label,
valueRange: attribute.valueLocation != null
? toRange(lineInfo, attribute.valueLocation.offset,
attribute.valueLocation.length)
: null);
@ -898,8 +898,12 @@ lsp.FlutterOutlineAttribute toFlutterOutlineAttribute(
lsp.FoldingRange toFoldingRange(
server.LineInfo lineInfo, server.FoldingRegion region) {
final range = toRange(lineInfo, region.offset, region.length);
return lsp.FoldingRange(range.start.line, range.start.character,
range.end.line, range.end.character, toFoldingRangeKind(region.kind));
return lsp.FoldingRange(
startLine: range.start.line,
startCharacter: range.start.character,
endLine: range.end.line,
endCharacter: range.end.character,
kind: toFoldingRangeKind(region.kind));
}
lsp.FoldingRangeKind toFoldingRangeKind(server.FoldingKind kind) {
@ -921,14 +925,14 @@ List<lsp.DocumentHighlight> toHighlights(
server.LineInfo lineInfo, server.Occurrences occurrences) {
return occurrences.offsets
.map((offset) => lsp.DocumentHighlight(
toRange(lineInfo, offset, occurrences.length), null))
range: toRange(lineInfo, offset, occurrences.length)))
.toList();
}
lsp.Location toLocation(server.Location location, server.LineInfo lineInfo) =>
lsp.Location(
Uri.file(location.file).toString(),
toRange(
uri: Uri.file(location.file).toString(),
range: toRange(
lineInfo,
location.offset,
location.length,
@ -942,11 +946,11 @@ ErrorOr<int> toOffset(
}) {
if (pos.line > lineInfo.lineCount) {
return ErrorOr<int>.error(lsp.ResponseError(
failureIsCritial
code: failureIsCritial
? lsp.ServerErrorCodes.ClientServerInconsistentState
: lsp.ServerErrorCodes.InvalidFileLineCol,
'Invalid line number',
pos.line.toString()));
message: 'Invalid line number',
data: pos.line.toString()));
}
// TODO(dantup): Is there any way to validate the character? We could ensure
// it's less than the offset of the next line, but that would only work for
@ -957,17 +961,18 @@ ErrorOr<int> toOffset(
lsp.Outline toOutline(server.LineInfo lineInfo, server.Outline outline) =>
lsp.Outline(
toElement(lineInfo, outline.element),
toRange(lineInfo, outline.offset, outline.length),
toRange(lineInfo, outline.codeOffset, outline.codeLength),
outline.children != null
element: toElement(lineInfo, outline.element),
range: toRange(lineInfo, outline.offset, outline.length),
codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
children: outline.children != null
? outline.children.map((c) => toOutline(lineInfo, c)).toList()
: null,
);
lsp.Position toPosition(server.CharacterLocation location) {
// LSP is zero-based, but analysis server is 1-based.
return lsp.Position(location.lineNumber - 1, location.columnNumber - 1);
return lsp.Position(
line: location.lineNumber - 1, character: location.columnNumber - 1);
}
lsp.Range toRange(server.LineInfo lineInfo, int offset, int length) {
@ -975,8 +980,8 @@ lsp.Range toRange(server.LineInfo lineInfo, int offset, int length) {
server.CharacterLocation end = lineInfo.getLocation(offset + length);
return lsp.Range(
toPosition(start),
toPosition(end),
start: toPosition(start),
end: toPosition(end),
);
}
@ -1023,20 +1028,20 @@ lsp.SignatureHelp toSignatureHelp(List<lsp.MarkupKind> preferredFormats,
// to guess based on substrings). We should check the
// signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport
// capability when deciding to send that.
return lsp.ParameterInformation(getParamLabel(param), null);
return lsp.ParameterInformation(label: getParamLabel(param));
}
final cleanDoc = cleanDartdoc(signature.dartdoc);
return lsp.SignatureHelp(
[
signatures: [
lsp.SignatureInformation(
getSignatureLabel(signature),
asStringOrMarkupContent(preferredFormats, cleanDoc),
signature.parameters.map(toParameterInfo).toList(),
label: getSignatureLabel(signature),
documentation: asStringOrMarkupContent(preferredFormats, cleanDoc),
parameters: signature.parameters.map(toParameterInfo).toList(),
),
],
0, // activeSignature
activeSignature: 0, // activeSignature
// TODO(dantup): The LSP spec says this value will default to 0 if it's
// not supplied or outside of the value range. However, setting -1 results
// in no parameters being selected in VS Code, whereas null/0 will select the first.
@ -1045,21 +1050,21 @@ lsp.SignatureHelp toSignatureHelp(List<lsp.MarkupKind> preferredFormats,
// (because you could also be on param 5 of an invalid call to a function
// taking only 3 arguments) here:
// https://github.com/Microsoft/language-server-protocol/issues/456#issuecomment-452318297
-1, // activeParameter
activeParameter: -1, // activeParameter
);
}
lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
return lsp.TextDocumentEdit(
edit.doc,
edit.edits.map((e) => toTextEdit(edit.lineInfo, e)).toList(),
textDocument: edit.doc,
edits: edit.edits.map((e) => toTextEdit(edit.lineInfo, e)).toList(),
);
}
lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
return lsp.TextEdit(
toRange(lineInfo, edit.offset, edit.length),
edit.replacement,
range: toRange(lineInfo, edit.offset, edit.length),
newText: edit.replacement,
);
}
@ -1071,16 +1076,15 @@ lsp.WorkspaceEdit toWorkspaceEdit(
capabilities?.workspaceEdit?.documentChanges == true;
if (clientSupportsTextDocumentEdits) {
return lsp.WorkspaceEdit(
null,
Either2<
documentChanges: Either2<
List<lsp.TextDocumentEdit>,
List<
Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
lsp.DeleteFile>>>.t1(
edits.map(toTextDocumentEdit).toList(),
));
edits.map(toTextDocumentEdit).toList(),
));
} else {
return lsp.WorkspaceEdit(toWorkspaceEditChanges(edits), null);
return lsp.WorkspaceEdit(changes: toWorkspaceEditChanges(edits));
}
}
@ -1118,5 +1122,5 @@ lsp.MarkupContent _asMarkup(
? lsp.MarkupKind.PlainText
: lsp.MarkupKind.Markdown;
return lsp.MarkupContent(format, content);
return lsp.MarkupContent(kind: format, value: content);
}

View file

@ -33,11 +33,11 @@ class LspNotificationManager extends AbstractNotificationManager {
.toList();
final params = PublishDiagnosticsParams(
Uri.file(filePath).toString(), null, diagnostics);
uri: Uri.file(filePath).toString(), diagnostics: diagnostics);
final message = NotificationMessage(
Method.textDocument_publishDiagnostics,
params,
jsonRpcVersion,
method: Method.textDocument_publishDiagnostics,
params: params,
jsonrpc: jsonRpcVersion,
);
channel.sendNotification(message);

View file

@ -116,106 +116,93 @@ class ServerCapabilitiesComputer {
// list of what files types we support (and allows them to avoid sending
// requests where we have only partial support for some types).
return ServerCapabilities(
dynamicRegistrations.textSync
? null
: Either2<TextDocumentSyncOptions, num>.t1(TextDocumentSyncOptions(
// The open/close and sync kind flags are registered dynamically if the
// client supports them, so these static registrations are based on whether
// the client supports dynamic registration.
true,
TextDocumentSyncKind.Incremental,
false,
false,
null,
)),
dynamicRegistrations.completion
? null
: CompletionOptions(
dartCompletionTriggerCharacters,
null, // allCommitCharacters
true, // resolveProvider
null, // workDoneProgress
), // completionProvider
dynamicRegistrations.hover
? null
: Either2<bool, HoverOptions>.t1(true), // hoverProvider
dynamicRegistrations.signatureHelp
? null
: SignatureHelpOptions(
dartSignatureHelpTriggerCharacters,
null, // retriggerCharacters
null, // workDoneProgress
),
null, // declarationProvider
dynamicRegistrations.definition
? null
: Either2<bool, DefinitionOptions>.t1(true), // definitionProvider
null,
dynamicRegistrations.implementation
? null
: Either3<bool, ImplementationOptions,
ImplementationRegistrationOptions>.t1(
true,
), // implementationProvider
dynamicRegistrations.references
? null
: Either2<bool, ReferenceOptions>.t1(true), // referencesProvider
dynamicRegistrations.documentHighlights
? null
: Either2<bool, DocumentHighlightOptions>.t1(
true), // documentHighlightProvider
dynamicRegistrations.documentSymbol
? null
: Either2<bool, DocumentSymbolOptions>.t1(
true), // documentSymbolProvider
// "The `CodeActionOptions` return type is only valid if the client
// signals code action literal support via the property
// `textDocument.codeAction.codeActionLiteralSupport`."
dynamicRegistrations.codeActions
? null
: codeActionLiteralSupport != null
? Either2<bool, CodeActionOptions>.t2(CodeActionOptions(
DartCodeActionKind.serverSupportedKinds,
null, // workDoneProgress
))
: Either2<bool, CodeActionOptions>.t1(true),
null, // codeLensProvider
null, // documentLinkProvider
null, // colorProvider
dynamicRegistrations.formatting
? null
: Either2<bool, DocumentFormattingOptions>.t1(
enableFormatter), // documentFormattingProvider
null, // documentRangeFormattingProvider
dynamicRegistrations.typeFormatting
? null
: enableFormatter
? DocumentOnTypeFormattingOptions(
dartTypeFormattingCharacters.first,
dartTypeFormattingCharacters.skip(1).toList())
: null,
dynamicRegistrations.rename
? null
: renameOptionsSupport
? Either2<bool, RenameOptions>.t2(RenameOptions(true, null))
: Either2<bool, RenameOptions>.t1(true),
dynamicRegistrations.folding
? null
: Either3<bool, FoldingRangeOptions,
FoldingRangeRegistrationOptions>.t1(
true,
),
ExecuteCommandOptions(
Commands.serverSupportedCommands,
null, // workDoneProgress
),
null, // selectionRangeProvider
true, // workspaceSymbolProvider
ServerCapabilitiesWorkspace(WorkspaceFoldersServerCapabilities(
true,
Either2<String, bool>.t2(true),
)),
null);
textDocumentSync: dynamicRegistrations.textSync
? null
: Either2<TextDocumentSyncOptions, num>.t1(TextDocumentSyncOptions(
// The open/close and sync kind flags are registered dynamically if the
// client supports them, so these static registrations are based on whether
// the client supports dynamic registration.
openClose: true,
change: TextDocumentSyncKind.Incremental,
willSave: false,
willSaveWaitUntil: false,
save: null,
)),
completionProvider: dynamicRegistrations.completion
? null
: CompletionOptions(
triggerCharacters: dartCompletionTriggerCharacters,
resolveProvider: true,
),
hoverProvider: dynamicRegistrations.hover
? null
: Either2<bool, HoverOptions>.t1(true),
signatureHelpProvider: dynamicRegistrations.signatureHelp
? null
: SignatureHelpOptions(
triggerCharacters: dartSignatureHelpTriggerCharacters,
),
definitionProvider: dynamicRegistrations.definition
? null
: Either2<bool, DefinitionOptions>.t1(true),
implementationProvider: dynamicRegistrations.implementation
? null
: Either3<bool, ImplementationOptions,
ImplementationRegistrationOptions>.t1(
true,
),
referencesProvider: dynamicRegistrations.references
? null
: Either2<bool, ReferenceOptions>.t1(true),
documentHighlightProvider: dynamicRegistrations.documentHighlights
? null
: Either2<bool, DocumentHighlightOptions>.t1(true),
documentSymbolProvider: dynamicRegistrations.documentSymbol
? null
: Either2<bool, DocumentSymbolOptions>.t1(true),
// "The `CodeActionOptions` return type is only valid if the client
// signals code action literal support via the property
// `textDocument.codeAction.codeActionLiteralSupport`."
codeActionProvider: dynamicRegistrations.codeActions
? null
: codeActionLiteralSupport != null
? Either2<bool, CodeActionOptions>.t2(CodeActionOptions(
codeActionKinds: DartCodeActionKind.serverSupportedKinds,
))
: Either2<bool, CodeActionOptions>.t1(true),
documentFormattingProvider: dynamicRegistrations.formatting
? null
: Either2<bool, DocumentFormattingOptions>.t1(enableFormatter),
documentOnTypeFormattingProvider: dynamicRegistrations.typeFormatting
? null
: enableFormatter
? DocumentOnTypeFormattingOptions(
firstTriggerCharacter: dartTypeFormattingCharacters.first,
moreTriggerCharacter:
dartTypeFormattingCharacters.skip(1).toList())
: null,
renameProvider: dynamicRegistrations.rename
? null
: renameOptionsSupport
? Either2<bool, RenameOptions>.t2(
RenameOptions(prepareProvider: true))
: Either2<bool, RenameOptions>.t1(true),
foldingRangeProvider: dynamicRegistrations.folding
? null
: Either3<bool, FoldingRangeOptions,
FoldingRangeRegistrationOptions>.t1(
true,
),
executeCommandProvider: ExecuteCommandOptions(
commands: Commands.serverSupportedCommands,
),
workspaceSymbolProvider: true,
workspace: ServerCapabilitiesWorkspace(
workspaceFolders: WorkspaceFoldersServerCapabilities(
supported: true,
changeNotifications: Either2<String, bool>.t2(true),
)),
);
}
/// If the client supports dynamic registrations we can tell it what methods
@ -226,17 +213,18 @@ class ServerCapabilitiesComputer {
/// support and it will be up to them to decide which file types they will
/// send requests for.
Future<void> performDynamicRegistration() async {
final dartFiles = DocumentFilter('dart', 'file', null);
final pubspecFile = DocumentFilter('yaml', 'file', '**/pubspec.yaml');
final analysisOptionsFile =
DocumentFilter('yaml', 'file', '**/analysis_options.yaml');
final dartFiles = DocumentFilter(language: 'dart', scheme: 'file');
final pubspecFile = DocumentFilter(
language: 'yaml', scheme: 'file', pattern: '**/pubspec.yaml');
final analysisOptionsFile = DocumentFilter(
language: 'yaml', scheme: 'file', pattern: '**/analysis_options.yaml');
final pluginTypes = _server.pluginManager.plugins
.expand((plugin) => plugin.currentSession?.interestingFiles ?? const [])
// All published plugins use something like `*.extension` as
// interestingFiles. Prefix a `**/` so that the glob matches nested
// folders as well.
.map((glob) => DocumentFilter(null, 'file', '**/$glob'));
.map((glob) => DocumentFilter(scheme: 'file', pattern: '**/$glob'));
final allTypes = {dartFiles, ...pluginTypes}.toList();
@ -259,7 +247,9 @@ class ServerCapabilitiesComputer {
void register(bool condition, Method method, [ToJsonable options]) {
if (condition == true) {
registrations.add(Registration(
(_lastRegistrationId++).toString(), method.toJson(), options));
id: (_lastRegistrationId++).toString(),
method: method.toJson(),
registerOptions: options));
}
}
@ -269,102 +259,99 @@ class ServerCapabilitiesComputer {
register(
dynamicRegistrations.textSync,
Method.textDocument_didOpen,
TextDocumentRegistrationOptions(allSynchronisedTypes),
TextDocumentRegistrationOptions(documentSelector: allSynchronisedTypes),
);
register(
dynamicRegistrations.textSync,
Method.textDocument_didClose,
TextDocumentRegistrationOptions(allSynchronisedTypes),
TextDocumentRegistrationOptions(documentSelector: allSynchronisedTypes),
);
register(
dynamicRegistrations.textSync,
Method.textDocument_didChange,
TextDocumentChangeRegistrationOptions(
TextDocumentSyncKind.Incremental, allSynchronisedTypes),
syncKind: TextDocumentSyncKind.Incremental,
documentSelector: allSynchronisedTypes),
);
register(
dynamicRegistrations.completion,
Method.textDocument_completion,
CompletionRegistrationOptions(
allTypes,
dartCompletionTriggerCharacters,
null,
true,
null,
documentSelector: allTypes,
triggerCharacters: dartCompletionTriggerCharacters,
resolveProvider: true,
),
);
register(
dynamicRegistrations.hover,
Method.textDocument_hover,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.signatureHelp,
Method.textDocument_signatureHelp,
SignatureHelpRegistrationOptions(
allTypes,
dartSignatureHelpTriggerCharacters,
null,
null,
documentSelector: allTypes,
triggerCharacters: dartSignatureHelpTriggerCharacters,
),
);
register(
dynamicRegistrations.references,
Method.textDocument_references,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.documentHighlights,
Method.textDocument_documentHighlight,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.documentSymbol,
Method.textDocument_documentSymbol,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
enableFormatter && dynamicRegistrations.formatting,
Method.textDocument_formatting,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
enableFormatter && dynamicRegistrations.typeFormatting,
Method.textDocument_onTypeFormatting,
DocumentOnTypeFormattingRegistrationOptions(
[dartFiles], // This one is currently Dart-specific
dartTypeFormattingCharacters.first,
dartTypeFormattingCharacters.skip(1).toList(),
documentSelector: [dartFiles], // This one is currently Dart-specific
firstTriggerCharacter: dartTypeFormattingCharacters.first,
moreTriggerCharacter: dartTypeFormattingCharacters.skip(1).toList(),
),
);
register(
dynamicRegistrations.definition,
Method.textDocument_definition,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.implementation,
Method.textDocument_implementation,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.codeActions,
Method.textDocument_codeAction,
CodeActionRegistrationOptions(
allTypes,
DartCodeActionKind.serverSupportedKinds,
null,
documentSelector: allTypes,
codeActionKinds: DartCodeActionKind.serverSupportedKinds,
),
);
register(
dynamicRegistrations.rename,
Method.textDocument_rename,
RenameRegistrationOptions(allTypes, true, null),
RenameRegistrationOptions(
documentSelector: allTypes, prepareProvider: true),
);
register(
dynamicRegistrations.folding,
Method.textDocument_foldingRange,
TextDocumentRegistrationOptions(allTypes),
TextDocumentRegistrationOptions(documentSelector: allTypes),
);
register(
dynamicRegistrations.didChangeConfiguration,
@ -395,8 +382,8 @@ class ServerCapabilitiesComputer {
registration.registerOptions;
if (entryRemovedOrChanged) {
removedRegistrations
.add(Unregistration(registration.id, registration.method));
removedRegistrations.add(
Unregistration(id: registration.id, method: registration.method));
} else {
// Replace the registration in our new set with the original registration
// so that we retain the original ID sent to the client (otherwise we
@ -410,7 +397,7 @@ class ServerCapabilitiesComputer {
if (removedRegistrations.isNotEmpty) {
await _server.sendRequest(Method.client_unregisterCapability,
UnregistrationParams(removedRegistrations));
UnregistrationParams(unregisterations: removedRegistrations));
}
// Only send the registration request if we have at least one (since
@ -418,7 +405,7 @@ class ServerCapabilitiesComputer {
if (additionalRegistrations.isNotEmpty) {
final registrationResponse = await _server.sendRequest(
Method.client_registerCapability,
RegistrationParams(additionalRegistrations),
RegistrationParams(registrations: additionalRegistrations),
);
if (registrationResponse.error != null) {

View file

@ -91,8 +91,9 @@ List<TextEdit> generateEditsForFormatting(String unformattedSource) {
final end = lineInfo.getLocation(unformattedSource.length);
return [
TextEdit(
Range(Position(0, 0), toPosition(end)),
formattedSource,
range:
Range(start: Position(line: 0, character: 0), end: toPosition(end)),
newText: formattedSource,
)
];
}

View file

@ -20,10 +20,10 @@ class InitializationTest extends AbstractLspAnalysisServerIntegrationTest {
Future<void> test_initialize_invalidParams() async {
final params = {'processId': 'invalid'};
final request = RequestMessage(
Either2<num, String>.t1(1),
Method.initialize,
params,
jsonRpcVersion,
id: Either2<num, String>.t1(1),
method: Method.initialize,
params: params,
jsonrpc: jsonRpcVersion,
);
final response = await sendRequestToServer(request);
expect(response.id, equals(request.id));

View file

@ -33,16 +33,13 @@ main() {
final completionRequest = makeRequest(
Method.textDocument_completion,
CompletionParams(
null,
TextDocumentIdentifier(mainFileUri.toString()),
positionFromMarker(content),
null,
null,
textDocument: TextDocumentIdentifier(uri: mainFileUri.toString()),
position: positionFromMarker(content),
),
);
// And a request to cancel it.
final cancelNotification = makeNotification(
Method.cancelRequest, CancelParams(completionRequest.id));
Method.cancelRequest, CancelParams(id: completionRequest.id));
// Send both (without waiting for the results of the first).
final completionRequestFuture = sendRequestToServer(completionRequest);

View file

@ -105,7 +105,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
// When the server sends the edit back, just keep a copy and say we
// applied successfully (it'll be verified below).
editParams = edit;
return ApplyWorkspaceEditResponse(true, null);
return ApplyWorkspaceEditResponse(applied: true);
},
);
// Successful edits return an empty success() response.

View file

@ -281,7 +281,8 @@ class SortMembersSourceCodeActionsTest extends AbstractCodeActionsTest {
// Claim that we failed tpo apply the edits. This is what the client
// would do if the edits provided were for an old version of the
// document.
handler: (edit) => ApplyWorkspaceEditResponse(false, 'Document changed'),
handler: (edit) => ApplyWorkspaceEditResponse(
applied: false, failureReason: 'Document changed'),
);
// Ensure the request returned an error (error repsonses are thrown by

View file

@ -108,8 +108,9 @@ class CompletionTest extends AbstractLspAnalysisServerTest {
final invalidTriggerKind = CompletionTriggerKind.fromJson(-1);
final request = getCompletion(
mainFileUri,
Position(0, 0),
context: CompletionContext(invalidTriggerKind, 'A'),
Position(line: 0, character: 0),
context: CompletionContext(
triggerKind: invalidTriggerKind, triggerCharacter: 'A'),
);
await expectLater(
@ -365,7 +366,9 @@ class CompletionTest extends AbstractLspAnalysisServerTest {
expect(item.textEdit.newText, equals(r'one: ${1:}'));
expect(
item.textEdit.range,
equals(Range(positionFromMarker(content), positionFromMarker(content))),
equals(Range(
start: positionFromMarker(content),
end: positionFromMarker(content))),
);
}
@ -852,7 +855,7 @@ main() {
// When the server sends the edit back, just keep a copy and say we
// applied successfully (it'll be verified below).
editParams = edit;
return ApplyWorkspaceEditResponse(true, null);
return ApplyWorkspaceEditResponse(applied: true);
},
);
// Successful edits return an empty success() response.

View file

@ -69,12 +69,16 @@ class DefinitionTest extends AbstractLspAnalysisServerTest {
newFile(pluginAnalyzedFilePath);
await initialize();
final res = await getDefinition(pluginAnalyzedFileUri, lsp.Position(0, 0));
final res = await getDefinition(
pluginAnalyzedFileUri, lsp.Position(line: 0, character: 0));
expect(res, hasLength(1));
var loc = res.single;
expect(
loc.range, equals(lsp.Range(lsp.Position(0, 0), lsp.Position(0, 5))));
loc.range,
equals(lsp.Range(
start: lsp.Position(line: 0, character: 0),
end: lsp.Position(line: 0, character: 5))));
expect(loc.uri, equals(pluginAnalyzedFileUri.toString()));
}

View file

@ -139,7 +139,7 @@ void f() {
// Send a request for a hover.
await initialize();
await getHover(dotFolderFileUri, Position(0, 0));
await getHover(dotFolderFileUri, Position(line: 0, character: 0));
// Ensure that as part of responding to getHover, diagnostics were not
// transmitted.

View file

@ -32,15 +32,17 @@ class Bar {
await changeFile(2, mainFileUri, [
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(0, 6), Position(0, 9)),
0,
'Bar',
range: Range(
start: Position(line: 0, character: 6),
end: Position(line: 0, character: 9)),
text: 'Bar',
)),
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(1, 21), Position(1, 24)),
0,
'updated',
range: Range(
start: Position(line: 1, character: 21),
end: Position(line: 1, character: 24)),
text: 'updated',
)),
]);
@ -58,15 +60,17 @@ class Bar {
await changeFile(2, mainFileUri, [
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(0, 6), Position(0, 9)),
0,
'Bar',
range: Range(
start: Position(line: 0, character: 6),
end: Position(line: 0, character: 9)),
text: 'Bar',
)),
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(1, 21), Position(1, 24)),
0,
'updated',
range: Range(
start: Position(line: 1, character: 21),
end: Position(line: 1, character: 24)),
text: 'updated',
)),
]);

View file

@ -29,9 +29,10 @@ class FileModificationTest extends AbstractLspAnalysisServerTest {
await changeFile(222, mainFileUri, [
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(999, 999), Position(999, 999)),
null,
' ',
range: Range(
start: Position(line: 999, character: 999),
end: Position(line: 999, character: 999)),
text: ' ',
))
]);
});
@ -62,9 +63,10 @@ class FileModificationTest extends AbstractLspAnalysisServerTest {
// Replace line1:5-1:8 with spaces.
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(1, 5), Position(1, 8)),
null,
' ',
range: Range(
start: Position(line: 1, character: 5),
end: Position(line: 1, character: 8)),
text: ' ',
))
]);
expect(_getOverlay(mainFilePath), equals(expectedUpdatedContent));
@ -79,9 +81,10 @@ class FileModificationTest extends AbstractLspAnalysisServerTest {
// ensure it generates an obvious error that the user can understand.
final simpleEdit = Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
Range(Position(1, 1), Position(1, 1)),
null,
'test',
range: Range(
start: Position(line: 1, character: 1),
end: Position(line: 1, character: 1)),
text: 'test',
));
await initialize();
final notificationParams = await expectErrorNotification<ShowMessageParams>(

View file

@ -88,18 +88,33 @@ Widget build(BuildContext context) => Container(
expect(outline, isNotNull);
// Root node is entire document
expect(outline.range, equals(Range(Position(0, 0), Position(15, 0))));
expect(
outline.range,
equals(Range(
start: Position(line: 0, character: 0),
end: Position(line: 15, character: 0))));
expect(outline.children, hasLength(1));
final build = outline.children[0];
expect(build.kind, equals('DART_ELEMENT'));
expect(build.range, equals(Range(Position(2, 0), Position(14, 6))));
expect(build.codeRange, equals(Range(Position(3, 0), Position(14, 6))));
expect(
build.range,
equals(Range(
start: Position(line: 2, character: 0),
end: Position(line: 14, character: 6))));
expect(
build.codeRange,
equals(Range(
start: Position(line: 3, character: 0),
end: Position(line: 14, character: 6))));
expect(build.dartElement.kind, equals('FUNCTION'));
expect(build.dartElement.name, equals('build'));
expect(build.dartElement.parameters, equals('(BuildContext context)'));
expect(build.dartElement.range,
equals(Range(Position(3, 7), Position(3, 12))));
expect(
build.dartElement.range,
equals(Range(
start: Position(line: 3, character: 7),
end: Position(line: 3, character: 12))));
expect(build.dartElement.returnType, equals('Widget'));
expect(build.children, hasLength(1));
@ -107,13 +122,20 @@ Widget build(BuildContext context) => Container(
build.children[0].children[0].children[0].children[0].children[0];
expect(icon.kind, equals('NEW_INSTANCE'));
expect(icon.className, 'Icon');
expect(icon.range, equals(Range(Position(8, 31), Position(8, 50))));
expect(
icon.range,
equals(Range(
start: Position(line: 8, character: 31),
end: Position(line: 8, character: 50))));
expect(icon.codeRange, equals(icon.range));
expect(icon.attributes, hasLength(1));
expect(icon.attributes[0].name, equals('icon'));
expect(icon.attributes[0].label, equals('Icons.ac_unit'));
expect(icon.attributes[0].valueRange,
equals(Range(Position(8, 36), Position(8, 49))));
expect(
icon.attributes[0].valueRange,
equals(Range(
start: Position(line: 8, character: 36),
end: Position(line: 8, character: 49))));
expect(icon.dartElement, isNull);
expect(icon.children, hasLength(0));
}

View file

@ -28,11 +28,10 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
final range1 = rangeFromMarkers(content);
final expectedRegions = [
FoldingRange(
range1.start.line,
range1.start.character,
range1.end.line,
range1.end.character,
null,
startLine: range1.start.line,
startCharacter: range1.start.character,
endLine: range1.end.line,
endCharacter: range1.end.character,
)
];
@ -53,11 +52,11 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
final range1 = rangeFromMarkers(content);
final expectedRegions = [
FoldingRange(
range1.start.line,
range1.start.character,
range1.end.line,
range1.end.character,
FoldingRangeKind.Comment,
startLine: range1.start.line,
startCharacter: range1.start.character,
endLine: range1.end.line,
endCharacter: range1.end.character,
kind: FoldingRangeKind.Comment,
)
];
@ -91,11 +90,10 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
final ranges = rangesFromMarkers(content);
final expectedRegions = ranges
.map((range) => FoldingRange(
range.start.line,
range.start.character,
range.end.line,
range.end.character,
null,
startLine: range.start.line,
startCharacter: range.start.character,
endLine: range.end.line,
endCharacter: range.end.character,
))
.toList();
@ -219,11 +217,10 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
final ranges = rangesFromMarkers(content);
final expectedRegions = ranges
.map((range) => FoldingRange(
range.start.line,
range.start.character,
range.end.line,
range.end.character,
null,
startLine: range.start.line,
startCharacter: range.start.character,
endLine: range.end.line,
endCharacter: range.end.character,
))
.toList();
@ -265,11 +262,10 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
final ranges = rangesFromMarkers(content);
final expectedRegions = ranges
.map((range) => FoldingRange(
range.start.line,
range.start.character,
range.end.line,
range.end.character,
null,
startLine: range.start.line,
startCharacter: range.start.character,
endLine: range.end.line,
endCharacter: range.end.character,
))
.toList();
@ -282,11 +278,11 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
FoldingRange _toFoldingRange(Range range, FoldingRangeKind kind) {
return FoldingRange(
range.start.line,
range.start.character,
range.end.line,
range.end.character,
kind,
startLine: range.start.line,
startCharacter: range.start.character,
endLine: range.end.line,
endCharacter: range.end.character,
kind: kind,
);
}
}

View file

@ -43,7 +43,7 @@ class HoverTest extends AbstractLspAnalysisServerTest {
await initialize();
await openFile(mainFileUri, '');
await expectLater(
() => getHover(mainFileUri, Position(999, 999)),
() => getHover(mainFileUri, Position(line: 999, character: 999)),
throwsA(isResponseError(ServerErrorCodes.InvalidFileLineCol)),
);
}

View file

@ -173,7 +173,7 @@ class ImplementationTest extends AbstractLspAnalysisServerTest {
);
final expectedLocations = rangesFromMarkers(content)
.map((r) => Location(mainFileUri.toString(), r));
.map((r) => Location(uri: mainFileUri.toString(), range: r));
if (shouldMatch) {
expect(res, equals(expectedLocations));

View file

@ -237,8 +237,9 @@ class InitializationTest extends AbstractLspAnalysisServerTest {
final registrations = (request.params as RegistrationParams).registrations;
final documentFilterSql = DocumentFilter(null, 'file', '**/*.sql');
final documentFilterDart = DocumentFilter('dart', 'file', null);
final documentFilterSql =
DocumentFilter(scheme: 'file', pattern: '**/*.sql');
final documentFilterDart = DocumentFilter(language: 'dart', scheme: 'file');
final expectedFoldingRegistration =
isA<TextDocumentRegistrationOptions>().having(
(o) => o.documentSelector,
@ -279,10 +280,10 @@ class InitializationTest extends AbstractLspAnalysisServerTest {
Future<void> test_initialize_invalidParams() async {
final params = {'processId': 'invalid'};
final request = RequestMessage(
Either2<num, String>.t1(1),
Method.initialize,
params,
jsonRpcVersion,
id: Either2<num, String>.t1(1),
method: Method.initialize,
params: params,
jsonrpc: jsonRpcVersion,
);
final response = await sendRequestToServer(request);
expect(response.id, equals(request.id));

View file

@ -78,16 +78,32 @@ class A {
expect(outline, isNotNull);
// Root node is entire document
expect(outline.range, equals(Range(Position(0, 0), Position(11, 0))));
expect(
outline.range,
equals(Range(
start: Position(line: 0, character: 0),
end: Position(line: 11, character: 0))));
expect(outline.children, hasLength(1));
// class A
final classA = outline.children[0];
expect(classA.element.name, equals('A'));
expect(classA.element.kind, equals('CLASS'));
expect(classA.element.range, equals(Range(Position(1, 6), Position(1, 7))));
expect(classA.range, equals(Range(Position(0, 0), Position(10, 1))));
expect(classA.codeRange, equals(Range(Position(1, 0), Position(10, 1))));
expect(
classA.element.range,
equals(Range(
start: Position(line: 1, character: 6),
end: Position(line: 1, character: 7))));
expect(
classA.range,
equals(Range(
start: Position(line: 0, character: 0),
end: Position(line: 10, character: 1))));
expect(
classA.codeRange,
equals(Range(
start: Position(line: 1, character: 0),
end: Position(line: 10, character: 1))));
expect(classA.children, hasLength(2));
// b()
@ -95,9 +111,20 @@ class A {
expect(methodB.element.name, equals('b'));
expect(methodB.element.kind, equals('METHOD'));
expect(
methodB.element.range, equals(Range(Position(3, 2), Position(3, 3))));
expect(methodB.range, equals(Range(Position(2, 2), Position(6, 3))));
expect(methodB.codeRange, equals(Range(Position(3, 2), Position(6, 3))));
methodB.element.range,
equals(Range(
start: Position(line: 3, character: 2),
end: Position(line: 3, character: 3))));
expect(
methodB.range,
equals(Range(
start: Position(line: 2, character: 2),
end: Position(line: 6, character: 3))));
expect(
methodB.codeRange,
equals(Range(
start: Position(line: 3, character: 2),
end: Position(line: 6, character: 3))));
expect(methodB.children, hasLength(1));
// c()
@ -105,12 +132,23 @@ class A {
expect(methodC.element.name, equals('c'));
expect(methodC.element.kind, equals('FUNCTION'));
expect(
methodC.element.range, equals(Range(Position(5, 4), Position(5, 5))));
methodC.element.range,
equals(Range(
start: Position(line: 5, character: 4),
end: Position(line: 5, character: 5))));
// TODO(dantup): This one seems to be excluding its dartdoc?
// should be line 4 for the starting range.
// https://github.com/dart-lang/sdk/issues/39746
expect(methodC.range, equals(Range(Position(5, 4), Position(5, 10))));
expect(methodC.codeRange, equals(Range(Position(5, 4), Position(5, 10))));
expect(
methodC.range,
equals(Range(
start: Position(line: 5, character: 4),
end: Position(line: 5, character: 10))));
expect(
methodC.codeRange,
equals(Range(
start: Position(line: 5, character: 4),
end: Position(line: 5, character: 10))));
expect(methodC.children, isNull);
// num get d
@ -118,9 +156,20 @@ class A {
expect(fieldD.element.name, equals('d'));
expect(fieldD.element.kind, equals('GETTER'));
expect(
fieldD.element.range, equals(Range(Position(9, 10), Position(9, 11))));
expect(fieldD.range, equals(Range(Position(8, 2), Position(9, 17))));
expect(fieldD.codeRange, equals(Range(Position(9, 2), Position(9, 17))));
fieldD.element.range,
equals(Range(
start: Position(line: 9, character: 10),
end: Position(line: 9, character: 11))));
expect(
fieldD.range,
equals(Range(
start: Position(line: 8, character: 2),
end: Position(line: 9, character: 17))));
expect(
fieldD.codeRange,
equals(Range(
start: Position(line: 9, character: 2),
end: Position(line: 9, character: 17))));
expect(fieldD.children, isNull);
}
}

View file

@ -54,12 +54,14 @@ class ReferencesTest extends AbstractLspAnalysisServerTest {
expect(res, hasLength(2));
expect(
res,
contains(
Location(mainFileUri.toString(), rangeFromMarkers(mainContents))));
contains(Location(
uri: mainFileUri.toString(),
range: rangeFromMarkers(mainContents))));
expect(
res,
contains(Location(referencedFileUri.toString(),
rangeFromMarkers(referencedContents))));
contains(Location(
uri: referencedFileUri.toString(),
range: rangeFromMarkers(referencedContents))));
}
Future<void> test_acrossFiles_withoutDeclaration() async {
@ -122,7 +124,8 @@ class ReferencesTest extends AbstractLspAnalysisServerTest {
expect(
res,
contains(
Location(mainFileUri.toString(), rangeFromMarkers(contents)),
Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(contents)),
),
);
}
@ -142,7 +145,8 @@ class ReferencesTest extends AbstractLspAnalysisServerTest {
expect(
res,
contains(
Location(mainFileUri.toString(), rangeFromMarkers(contents)),
Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(contents)),
),
);
}

View file

@ -80,8 +80,8 @@ class RenameTest extends AbstractLspAnalysisServerTest {
final request = makeRequest(
Method.textDocument_prepareRename,
TextDocumentPositionParams(
TextDocumentIdentifier(mainFileUri.toString()),
positionFromMarker(content),
textDocument: TextDocumentIdentifier(uri: mainFileUri.toString()),
position: positionFromMarker(content),
),
);
final response = await channel.sendRequestToServer(request);
@ -296,10 +296,9 @@ class RenameTest extends AbstractLspAnalysisServerTest {
final request = makeRequest(
Method.textDocument_rename,
RenameParams(
'Object2',
TextDocumentIdentifier(mainFileUri.toString()),
positionFromMarker(content),
null,
newName: 'Object2',
textDocument: TextDocumentIdentifier(uri: mainFileUri.toString()),
position: positionFromMarker(content),
),
);
final response = await channel.sendRequestToServer(request);

View file

@ -35,7 +35,9 @@ const dartLanguageId = 'dart';
/// communication to be printed to stdout.
const debugPrintCommunication = false;
final beginningOfDocument = Range(Position(0, 0), Position(0, 0));
final beginningOfDocument = Range(
start: Position(line: 0, character: 0),
end: Position(line: 0, character: 0));
abstract class AbstractLspAnalysisServerTest
with
@ -145,32 +147,9 @@ abstract class AbstractLspAnalysisServerTest
}
mixin ClientCapabilitiesHelperMixin {
final emptyTextDocumentClientCapabilities = TextDocumentClientCapabilities(
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null);
final emptyTextDocumentClientCapabilities = TextDocumentClientCapabilities();
final emptyWorkspaceClientCapabilities = ClientCapabilitiesWorkspace(
null, null, null, null, null, null, null, null);
final emptyWorkspaceClientCapabilities = ClientCapabilitiesWorkspace();
TextDocumentClientCapabilities extendTextDocumentCapabilities(
TextDocumentClientCapabilities source,
@ -371,8 +350,10 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
String projectFolderPath, mainFilePath, pubspecFilePath, analysisOptionsPath;
Uri projectFolderUri, mainFileUri, pubspecFileUri, analysisOptionsUri;
final String simplePubspecContent = 'name: my_project';
final startOfDocPos = Position(0, 0);
final startOfDocRange = Range(Position(0, 0), Position(0, 0));
final startOfDocPos = Position(line: 0, character: 0);
final startOfDocRange = Range(
start: Position(line: 0, character: 0),
end: Position(line: 0, character: 0));
/// A stream of [NotificationMessage]s from the server that may be errors.
Stream<NotificationMessage> get errorNotificationsFromServer {
@ -523,8 +504,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
var notification = makeNotification(
Method.textDocument_didChange,
DidChangeTextDocumentParams(
VersionedTextDocumentIdentifier(newVersion, uri.toString()),
changes,
textDocument: VersionedTextDocumentIdentifier(
version: newVersion, uri: uri.toString()),
contentChanges: changes,
),
);
await sendNotificationToServer(notification);
@ -534,9 +516,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
var notification = makeNotification(
Method.workspace_didChangeWorkspaceFolders,
DidChangeWorkspaceFoldersParams(
WorkspaceFoldersChangeEvent(
add?.map(toWorkspaceFolder)?.toList() ?? const [],
remove?.map(toWorkspaceFolder)?.toList() ?? const [],
event: WorkspaceFoldersChangeEvent(
added: add?.map(toWorkspaceFolder)?.toList() ?? const [],
removed: remove?.map(toWorkspaceFolder)?.toList() ?? const [],
),
),
);
@ -546,7 +528,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
Future closeFile(Uri uri) async {
var notification = makeNotification(
Method.textDocument_didClose,
DidCloseTextDocumentParams(TextDocumentIdentifier(uri.toString())),
DidCloseTextDocumentParams(
textDocument: TextDocumentIdentifier(uri: uri.toString())),
);
await sendNotificationToServer(notification);
}
@ -555,9 +538,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.workspace_executeCommand,
ExecuteCommandParams(
command.command,
command.arguments,
null,
command: command.command,
arguments: command.arguments,
),
);
return expectSuccessfulResponseTo(request);
@ -651,10 +633,10 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_formatting,
DocumentFormattingParams(
TextDocumentIdentifier(fileUri),
FormattingOptions(
2, true, false, false, false), // These currently don't do anything
null,
textDocument: TextDocumentIdentifier(uri: fileUri),
options: FormattingOptions(
tabSize: 2,
insertSpaces: true), // These currently don't do anything
),
);
return expectSuccessfulResponseTo(request);
@ -665,11 +647,12 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_onTypeFormatting,
DocumentOnTypeFormattingParams(
character,
FormattingOptions(
2, true, false, false, false), // These currently don't do anything
TextDocumentIdentifier(fileUri),
pos,
ch: character,
options: FormattingOptions(
tabSize: 2,
insertSpaces: true), // These currently don't do anything
textDocument: TextDocumentIdentifier(uri: fileUri),
position: pos,
),
);
return expectSuccessfulResponseTo(request);
@ -683,14 +666,12 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_codeAction,
CodeActionParams(
TextDocumentIdentifier(fileUri),
range ?? beginningOfDocument,
textDocument: TextDocumentIdentifier(uri: fileUri),
range: range ?? beginningOfDocument,
// TODO(dantup): We may need to revise the tests/implementation when
// it's clear how we're supposed to handle diagnostics:
// https://github.com/Microsoft/language-server-protocol/issues/583
CodeActionContext([], kinds),
null,
null,
context: CodeActionContext(diagnostics: [], only: kinds),
),
);
return expectSuccessfulResponseTo(request);
@ -701,11 +682,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_completion,
CompletionParams(
context,
TextDocumentIdentifier(uri.toString()),
pos,
null,
null,
context: context,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<List<CompletionItem>>(request);
@ -715,8 +694,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_definition,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<List<Location>>(request);
@ -734,8 +713,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_documentHighlight,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<List<DocumentHighlight>>(request);
@ -746,9 +725,7 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_documentSymbol,
DocumentSymbolParams(
TextDocumentIdentifier(fileUri),
null,
null,
textDocument: TextDocumentIdentifier(uri: fileUri),
),
);
return expectSuccessfulResponseTo(request);
@ -758,9 +735,7 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_foldingRange,
FoldingRangeParams(
TextDocumentIdentifier(uri.toString()),
null,
null,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
),
);
return expectSuccessfulResponseTo<List<FoldingRange>>(request);
@ -769,7 +744,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
Future<Hover> getHover(Uri uri, Position pos) {
final request = makeRequest(
Method.textDocument_hover,
TextDocumentPositionParams(TextDocumentIdentifier(uri.toString()), pos),
TextDocumentPositionParams(
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos),
);
return expectSuccessfulResponseTo<Hover>(request);
}
@ -782,8 +759,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_implementation,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<List<Location>>(request);
@ -797,11 +774,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_references,
ReferenceParams(
ReferenceContext(includeDeclarations),
TextDocumentIdentifier(uri.toString()),
pos,
null,
null,
context: ReferenceContext(includeDeclaration: includeDeclarations),
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<List<Location>>(request);
@ -811,8 +786,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_signatureHelp,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<SignatureHelp>(request);
@ -825,8 +800,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
CustomMethods.Super,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<Location>(request);
@ -835,11 +810,7 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
Future<List<SymbolInformation>> getWorkspaceSymbols(String query) {
final request = makeRequest(
Method.workspace_symbol,
WorkspaceSymbolParams(
query,
null,
null,
),
WorkspaceSymbolParams(query: query),
);
return expectSuccessfulResponseTo(request);
}
@ -910,20 +881,15 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.initialize,
InitializeParams(
null,
null,
rootPath,
rootUri?.toString(),
initializationOptions,
ClientCapabilities(
workspaceCapabilities,
textDocumentCapabilities,
windowCapabilities,
null,
rootPath: rootPath,
rootUri: rootUri?.toString(),
initializationOptions: initializationOptions,
capabilities: ClientCapabilities(
workspace: workspaceCapabilities,
textDocument: textDocumentCapabilities,
window: windowCapabilities,
),
null,
workspaceFolders?.map(toWorkspaceFolder)?.toList(),
null,
workspaceFolders: workspaceFolders?.map(toWorkspaceFolder)?.toList(),
));
final response = await sendRequestToServer(request);
expect(response.id, equals(request.id));
@ -942,24 +908,27 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
}
NotificationMessage makeNotification(Method method, ToJsonable params) {
return NotificationMessage(method, params, jsonRpcVersion);
return NotificationMessage(
method: method, params: params, jsonrpc: jsonRpcVersion);
}
RequestMessage makeRenameRequest(
int version, Uri uri, Position pos, String newName) {
final docIdentifier = version != null
? VersionedTextDocumentIdentifier(version, uri.toString())
: TextDocumentIdentifier(uri.toString());
? VersionedTextDocumentIdentifier(version: version, uri: uri.toString())
: TextDocumentIdentifier(uri: uri.toString());
final request = makeRequest(
Method.textDocument_rename,
RenameParams(newName, docIdentifier, pos, null),
RenameParams(
newName: newName, textDocument: docIdentifier, position: pos),
);
return request;
}
RequestMessage makeRequest(Method method, ToJsonable params) {
final id = Either2<num, String>.t1(_id++);
return RequestMessage(id, method, params, jsonRpcVersion);
return RequestMessage(
id: id, method: method, params: params, jsonrpc: jsonRpcVersion);
}
/// Watches for `client/registerCapability` requests and updates
@ -998,7 +967,11 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
var notification = makeNotification(
Method.textDocument_didOpen,
DidOpenTextDocumentParams(
TextDocumentItem(uri.toString(), dartLanguageId, version, content)),
textDocument: TextDocumentItem(
uri: uri.toString(),
languageId: dartLanguageId,
version: version,
text: content)),
);
await sendNotificationToServer(notification);
await pumpEventQueue();
@ -1026,8 +999,8 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
final request = makeRequest(
Method.textDocument_prepareRename,
TextDocumentPositionParams(
TextDocumentIdentifier(uri.toString()),
pos,
textDocument: TextDocumentIdentifier(uri: uri.toString()),
position: pos,
),
);
return expectSuccessfulResponseTo<RangeAndPlaceholder>(request);
@ -1078,9 +1051,9 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
throw 'Found unclosed range starting at offset $startMarker';
}
yield Range(
positionFromOffset(
start: positionFromOffset(
startMarker + offsetForEarlierMarkers, contentsWithoutMarkers),
positionFromOffset(
end: positionFromOffset(
endMarker + offsetForEarlierMarkers - rangeMarkerStart.length,
contentsWithoutMarkers),
);
@ -1123,7 +1096,7 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
[
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t2(
TextDocumentContentChangeEvent2(content))
TextDocumentContentChangeEvent2(text: content))
],
);
}
@ -1139,14 +1112,14 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
/// Sends [responseParams] to the server as a successful response to
/// a server-initiated [request].
void respondTo<T>(RequestMessage request, T responseParams) {
sendResponseToServer(
ResponseMessage(request.id, responseParams, null, jsonRpcVersion));
sendResponseToServer(ResponseMessage(
id: request.id, result: responseParams, jsonrpc: jsonRpcVersion));
}
Future<ResponseMessage> sendDidChangeConfiguration() {
final request = makeRequest(
Method.workspace_didChangeConfiguration,
DidChangeConfigurationParams(null),
DidChangeConfigurationParams(),
);
return sendRequestToServer(request);
}
@ -1168,7 +1141,10 @@ mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
}
WorkspaceFolder toWorkspaceFolder(Uri uri) {
return WorkspaceFolder(uri.toString(), path.basename(uri.toFilePath()));
return WorkspaceFolder(
uri: uri.toString(),
name: path.basename(uri.toFilePath()),
);
}
/// Tells the server the config has changed, and provides the supplied config

View file

@ -27,7 +27,10 @@ class ServerTest extends AbstractLspAnalysisServerTest {
Either2<TextDocumentContentChangeEvent1,
TextDocumentContentChangeEvent2>.t1(
TextDocumentContentChangeEvent1(
Range(Position(99, 99), Position(99, 99)), null, ' ')),
range: Range(
start: Position(line: 99, character: 99),
end: Position(line: 99, character: 99)),
text: ' ')),
]);
});

View file

@ -40,8 +40,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
expectedFormat: null,
);
@ -66,8 +66,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
expectedFormat: MarkupKind.Markdown,
);
@ -90,8 +90,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
expectedFormat: null,
);
@ -116,8 +116,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
expectedFormat: MarkupKind.PlainText,
);
@ -146,8 +146,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
expectedFormat: MarkupKind.Markdown,
);
@ -182,9 +182,9 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('bool b = true', null),
ParameterInformation('bool a', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'bool b = true'),
ParameterInformation(label: 'bool a'),
],
);
}
@ -209,9 +209,9 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('bool b = true', null),
ParameterInformation('bool a', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'bool b = true'),
ParameterInformation(label: 'bool a'),
],
);
}
@ -236,8 +236,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('bool b = true', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'bool b = true'),
],
);
}
@ -262,8 +262,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('bool b = true', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'bool b = true'),
],
);
}
@ -287,8 +287,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
);
}
@ -312,8 +312,8 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
expectedLabel,
expectedDoc,
[
ParameterInformation('String s', null),
ParameterInformation('int i', null),
ParameterInformation(label: 'String s'),
ParameterInformation(label: 'int i'),
],
);
}
@ -345,7 +345,7 @@ class SignatureHelpTest extends AbstractLspAnalysisServerTest {
// Plain string.
expect(doc.valueEquals(expectedDoc), isTrue);
} else {
final expected = MarkupContent(expectedFormat, expectedDoc);
final expected = MarkupContent(kind: expectedFormat, value: expectedDoc);
expect(doc.valueEquals(expected), isTrue);
}
}

View file

@ -31,8 +31,10 @@ class C^ extends B {}
positionFromMarker(content),
);
expect(res,
equals(Location(mainFileUri.toString(), rangeFromMarkers(content))));
expect(
res,
equals(Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(content))));
}
Future<void> test_insideClass() async {
@ -52,8 +54,10 @@ class C extends B {
positionFromMarker(content),
);
expect(res,
equals(Location(mainFileUri.toString(), rangeFromMarkers(content))));
expect(
res,
equals(Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(content))));
}
Future<void> test_insideMethod() async {
@ -78,8 +82,10 @@ class C extends B {
positionFromMarker(content),
);
expect(res,
equals(Location(mainFileUri.toString(), rangeFromMarkers(content))));
expect(
res,
equals(Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(content))));
}
Future<void> test_methodName() async {
@ -104,8 +110,10 @@ class C extends B {
positionFromMarker(content),
);
expect(res,
equals(Location(mainFileUri.toString(), rangeFromMarkers(content))));
expect(
res,
equals(Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(content))));
}
Future<void> test_methodReturnType() async {
@ -130,7 +138,9 @@ class C extends B {
positionFromMarker(content),
);
expect(res,
equals(Location(mainFileUri.toString(), rangeFromMarkers(content))));
expect(
res,
equals(Location(
uri: mainFileUri.toString(), range: rangeFromMarkers(content))));
}
}

View file

@ -91,10 +91,10 @@ class WorkspaceSymbolsTest extends AbstractLspAnalysisServerTest {
// Create a request that doesn't supply the query param.
final request = RequestMessage(
Either2<num, String>.t1(1),
Method.workspace_symbol,
<String, dynamic>{},
jsonRpcVersion,
id: Either2<num, String>.t1(1),
method: Method.workspace_symbol,
params: <String, dynamic>{},
jsonrpc: jsonRpcVersion,
);
final response = await sendRequestToServer(request);

View file

@ -9,8 +9,8 @@ import 'package:test/test.dart';
void main() {
group('generated classes', () {
test('can be checked for equality', () {
final a = TextDocumentIdentifier('/a');
final b = TextDocumentIdentifier('/a');
final a = TextDocumentIdentifier(uri: '/a');
final b = TextDocumentIdentifier(uri: '/a');
expect(a, equals(b));
expect(a.hashCode, equals(b.hashCode));
@ -18,10 +18,10 @@ void main() {
test('with list fields can be checked for equality', () {
final a = CodeActionClientCapabilitiesCodeActionKind(
[CodeActionKind.QuickFix],
valueSet: [CodeActionKind.QuickFix],
);
final b = CodeActionClientCapabilitiesCodeActionKind(
[CodeActionKind.QuickFix],
valueSet: [CodeActionKind.QuickFix],
);
expect(a, equals(b));
@ -30,21 +30,33 @@ void main() {
test('with aliased list fields can be checked for equality', () {
final a = TextDocumentRegistrationOptions(
[DocumentFilter('dart', 'file', null)]);
documentSelector: [DocumentFilter(language: 'dart', scheme: 'file')]);
final b = TextDocumentRegistrationOptions(
[DocumentFilter('dart', 'file', null)]);
documentSelector: [DocumentFilter(language: 'dart', scheme: 'file')]);
expect(a, equals(b));
expect(a.hashCode, equals(b.hashCode));
});
test('with map fields can be checked for equality', () {
final a = WorkspaceEdit({
'a': [TextEdit(Range(Position(0, 0), Position(0, 0)), 'a')]
}, null);
final b = WorkspaceEdit({
'a': [TextEdit(Range(Position(0, 0), Position(0, 0)), 'a')]
}, null);
final a = WorkspaceEdit(changes: {
'a': [
TextEdit(
range: Range(
start: Position(line: 0, character: 0),
end: Position(line: 0, character: 0)),
newText: 'a')
]
});
final b = WorkspaceEdit(changes: {
'a': [
TextEdit(
range: Range(
start: Position(line: 0, character: 0),
end: Position(line: 0, character: 0)),
newText: 'a')
]
});
expect(a, equals(b));
expect(a.hashCode, equals(b.hashCode));
@ -59,10 +71,14 @@ void main() {
});
test('with union fields can be checked for equality', () {
final a =
SignatureInformation('a', Either2<String, MarkupContent>.t1('a'), []);
final b =
SignatureInformation('a', Either2<String, MarkupContent>.t1('a'), []);
final a = SignatureInformation(
label: 'a',
documentation: Either2<String, MarkupContent>.t1('a'),
parameters: []);
final b = SignatureInformation(
label: 'a',
documentation: Either2<String, MarkupContent>.t1('a'),
parameters: []);
expect(a, equals(b));
expect(a.hashCode, equals(b.hashCode));
@ -70,9 +86,10 @@ void main() {
test('consider subclasses when checking for equality', () {
final a = TextDocumentRegistrationOptions(
[DocumentFilter('dart', 'file', null)]);
documentSelector: [DocumentFilter(language: 'dart', scheme: 'file')]);
final b = TextDocumentSaveRegistrationOptions(
true, [DocumentFilter('dart', 'file', null)]);
includeText: true,
documentSelector: [DocumentFilter(language: 'dart', scheme: 'file')]);
expect(a, isNot(equals(b)));
expect(b, isNot(equals(a)));

View file

@ -20,15 +20,17 @@ void main() {
test('returns correct output for union types', () {
final message = RequestMessage(
Either2<num, String>.t1(1), Method.shutdown, null, 'test');
id: Either2<num, String>.t1(1),
method: Method.shutdown,
jsonrpc: 'test');
final output = json.encode(message.toJson());
expect(output, equals('{"id":1,"method":"shutdown","jsonrpc":"test"}'));
});
test('returns correct output for union types containing interface types',
() {
final params = Either2<String, TextDocumentItem>.t2(
TextDocumentItem('!uri', '!language', 1, '!text'));
final params = Either2<String, TextDocumentItem>.t2(TextDocumentItem(
uri: '!uri', languageId: '!language', version: 1, text: '!text'));
final output = json.encode(params);
expect(
output,
@ -37,18 +39,19 @@ void main() {
});
test('returns correct output for types with lists', () {
final start = Position(1, 1);
final end = Position(2, 2);
final range = Range(start, end);
final location = Location('y-uri', range);
final start = Position(line: 1, character: 1);
final end = Position(line: 2, character: 2);
final range = Range(start: start, end: end);
final location = Location(uri: 'y-uri', range: range);
final codeAction = Diagnostic(
range,
DiagnosticSeverity.Error,
'test_err',
'/tmp/source.dart',
'err!!',
null,
[DiagnosticRelatedInformation(location, 'message')],
range: range,
severity: DiagnosticSeverity.Error,
code: 'test_err',
source: '/tmp/source.dart',
message: 'err!!',
relatedInformation: [
DiagnosticRelatedInformation(location: location, message: 'message')
],
);
final output = json.encode(codeAction.toJson());
final expected = '''{
@ -78,7 +81,12 @@ void main() {
});
test('serialises enums to their underlying values', () {
final foldingRange = FoldingRange(1, 2, 3, 4, FoldingRangeKind.Comment);
final foldingRange = FoldingRange(
startLine: 1,
startCharacter: 2,
endLine: 3,
endCharacter: 4,
kind: FoldingRangeKind.Comment);
final output = json.encode(foldingRange.toJson());
final expected = '''{
"startLine":1,
@ -94,7 +102,8 @@ void main() {
test('ResponseMessage does not include an error with a result', () {
final id = Either2<num, String>.t1(1);
final result = 'my result';
final resp = ResponseMessage(id, result, null, jsonRpcVersion);
final resp =
ResponseMessage(id: id, result: result, jsonrpc: jsonRpcVersion);
final jsonMap = resp.toJson();
expect(jsonMap, contains('result'));
expect(jsonMap, isNot(contains('error')));
@ -237,7 +246,7 @@ void main() {
test('ResponseMessage can include a null result', () {
final id = Either2<num, String>.t1(1);
final resp = ResponseMessage(id, null, null, jsonRpcVersion);
final resp = ResponseMessage(id: id, jsonrpc: jsonRpcVersion);
final jsonMap = resp.toJson();
expect(jsonMap, contains('result'));
expect(jsonMap, isNot(contains('error')));
@ -245,8 +254,10 @@ void main() {
test('ResponseMessage does not include a result for an error', () {
final id = Either2<num, String>.t1(1);
final error = ResponseError(ErrorCodes.ParseError, 'Error', null);
final resp = ResponseMessage(id, null, error, jsonRpcVersion);
final error =
ResponseError(code: ErrorCodes.ParseError, message: 'Error');
final resp =
ResponseMessage(id: id, error: error, jsonrpc: jsonRpcVersion);
final jsonMap = resp.toJson();
expect(jsonMap, contains('error'));
expect(jsonMap, isNot(contains('result')));
@ -255,8 +266,10 @@ void main() {
test('ResponseMessage throws if both result and error are non-null', () {
final id = Either2<num, String>.t1(1);
final result = 'my result';
final error = ResponseError(ErrorCodes.ParseError, 'Error', null);
final resp = ResponseMessage(id, result, error, jsonRpcVersion);
final error =
ResponseError(code: ErrorCodes.ParseError, message: 'Error');
final resp = ResponseMessage(
id: id, result: result, error: error, jsonrpc: jsonRpcVersion);
expect(resp.toJson, throwsA(TypeMatcher<String>()));
});
});
@ -296,8 +309,9 @@ void main() {
// Create some JSON that includes a VersionedTextDocumentIdenfitier but
// where the class definition only references a TextDocumentIdemntifier.
final input = jsonEncode(TextDocumentPositionParams(
VersionedTextDocumentIdentifier(111, 'file:///foo/bar.dart'),
Position(1, 1),
textDocument: VersionedTextDocumentIdentifier(
version: 111, uri: 'file:///foo/bar.dart'),
position: Position(line: 1, character: 1),
).toJson());
final params = TextDocumentPositionParams.fromJson(jsonDecode(input));
expect(params.textDocument,
@ -317,18 +331,16 @@ void main() {
test('objects with lists can round-trip through to json and back', () {
final obj = InitializeParams(
1,
InitializeParamsClientInfo('server name', '1.2.3'),
'!root',
null,
null,
ClientCapabilities(null, null, null, null),
'!trace',
[
WorkspaceFolder('!uri1', '!name1'),
WorkspaceFolder('!uri2', '!name2'),
processId: 1,
clientInfo:
InitializeParamsClientInfo(name: 'server name', version: '1.2.3'),
rootPath: '!root',
capabilities: ClientCapabilities(),
trace: '!trace',
workspaceFolders: [
WorkspaceFolder(uri: '!uri1', name: '!name1'),
WorkspaceFolder(uri: '!uri2', name: '!name2'),
],
null,
);
final json = jsonEncode(obj);
final restoredObj = InitializeParams.fromJson(jsonDecode(json));
@ -344,7 +356,12 @@ void main() {
});
test('objects with enums can round-trip through to json and back', () {
final obj = FoldingRange(1, 2, 3, 4, FoldingRangeKind.Comment);
final obj = FoldingRange(
startLine: 1,
startCharacter: 2,
endLine: 3,
endCharacter: 4,
kind: FoldingRangeKind.Comment);
final json = jsonEncode(obj);
final restoredObj = FoldingRange.fromJson(jsonDecode(json));
@ -356,13 +373,13 @@ void main() {
});
test('objects with maps can round-trip through to json and back', () {
final start = Position(1, 1);
final end = Position(2, 2);
final range = Range(start, end);
final obj = WorkspaceEdit(<String, List<TextEdit>>{
'fileA': [TextEdit(range, 'text A')],
'fileB': [TextEdit(range, 'text B')]
}, null);
final start = Position(line: 1, character: 1);
final end = Position(line: 2, character: 2);
final range = Range(start: start, end: end);
final obj = WorkspaceEdit(changes: <String, List<TextEdit>>{
'fileA': [TextEdit(range: range, newText: 'text A')],
'fileB': [TextEdit(range: range, newText: 'text B')]
});
final json = jsonEncode(obj);
final restoredObj = WorkspaceEdit.fromJson(jsonDecode(json));

View file

@ -258,9 +258,13 @@ void _writeConstructor(IndentableStringBuffer buffer, Interface interface) {
return;
}
buffer
..writeIndented('${interface.name}(')
..write(allFields.map((field) => 'this.${field.name}').join(', '))
..write(')');
..writeIndented('${interface.name}({')
..write(allFields.map((field) {
final annotation =
!field.allowsNull && !field.allowsUndefined ? '@required' : '';
return '$annotation this.${field.name}';
}).join(', '))
..write('})');
final fieldsWithValidation =
allFields.where((f) => !f.allowsNull && !f.allowsUndefined).toList();
if (fieldsWithValidation.isNotEmpty) {
@ -522,7 +526,7 @@ void _writeFromJsonConstructor(
}
buffer
..writeIndented('return ${interface.nameWithTypeArgs}(')
..write(allFields.map((field) => '${field.name}').join(', '))
..write(allFields.map((field) => '${field.name}: ${field.name}').join(', '))
..writeln(');')
..outdent()
..writeIndented('}');

View file

@ -176,6 +176,7 @@ import 'package:analysis_server/src/lsp/json_parsing.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart'
show listEqual, mapEqual;
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:meta/meta.dart';
const jsonEncoder = JsonEncoder.withIndent(' ');