mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:00:09 +00:00
[analysis_server] Switch to LSP v3.17 spec + regenerate types
Change-Id: I6e1b79f3e814c44784dbf37d859ae46d303db2dc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244243 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
063ee76dc7
commit
6b6a199806
File diff suppressed because it is too large
Load diff
|
@ -71,7 +71,7 @@ abstract class SimpleEditCommandHandler
|
||||||
// sent - and may have failed to apply - was related to this command
|
// sent - and may have failed to apply - was related to this command
|
||||||
// execution).
|
// execution).
|
||||||
// We need to fromJson to convert the JSON map to the real types.
|
// We need to fromJson to convert the JSON map to the real types.
|
||||||
final editResponseResult = ApplyWorkspaceEditResponse.fromJson(
|
final editResponseResult = ApplyWorkspaceEditResult.fromJson(
|
||||||
editResponse.result as Map<String, Object?>);
|
editResponse.result as Map<String, Object?>);
|
||||||
if (editResponseResult.applied) {
|
if (editResponseResult.applied) {
|
||||||
return success(null);
|
return success(null);
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
|
import 'package:analysis_server/lsp_protocol/protocol_generated.dart'
|
||||||
|
hide TypeHierarchyItem;
|
||||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||||
import 'package:analysis_server/protocol/protocol_generated.dart';
|
import 'package:analysis_server/protocol/protocol_generated.dart';
|
||||||
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
|
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
|
||||||
|
|
|
@ -101,7 +101,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
|
||||||
ApplyWorkspaceEditParams? editParams;
|
ApplyWorkspaceEditParams? editParams;
|
||||||
|
|
||||||
final commandResponse = await handleExpectedRequest<Object?,
|
final commandResponse = await handleExpectedRequest<Object?,
|
||||||
ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
|
ApplyWorkspaceEditParams, ApplyWorkspaceEditResult>(
|
||||||
Method.workspace_applyEdit,
|
Method.workspace_applyEdit,
|
||||||
ApplyWorkspaceEditParams.fromJson,
|
ApplyWorkspaceEditParams.fromJson,
|
||||||
() => executeCommand(command, workDoneToken: workDoneToken),
|
() => executeCommand(command, workDoneToken: workDoneToken),
|
||||||
|
@ -109,7 +109,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
|
||||||
// When the server sends the edit back, just keep a copy and say we
|
// When the server sends the edit back, just keep a copy and say we
|
||||||
// applied successfully (it'll be verified below).
|
// applied successfully (it'll be verified below).
|
||||||
editParams = edit;
|
editParams = edit;
|
||||||
return ApplyWorkspaceEditResponse(applied: true);
|
return ApplyWorkspaceEditResult(applied: true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Successful edits return an empty success() response.
|
// Successful edits return an empty success() response.
|
||||||
|
|
|
@ -192,7 +192,7 @@ void newMethod() {
|
||||||
final params = ApplyWorkspaceEditParams.fromJson(
|
final params = ApplyWorkspaceEditParams.fromJson(
|
||||||
request.params as Map<String, Object?>);
|
request.params as Map<String, Object?>);
|
||||||
edit = params.edit;
|
edit = params.edit;
|
||||||
respondTo(request, ApplyWorkspaceEditResponse(applied: true));
|
respondTo(request, ApplyWorkspaceEditResult(applied: true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -322,14 +322,14 @@ class SortMembersSourceCodeActionsTest extends AbstractCodeActionsTest {
|
||||||
);
|
);
|
||||||
|
|
||||||
final commandResponse = handleExpectedRequest<Object?,
|
final commandResponse = handleExpectedRequest<Object?,
|
||||||
ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
|
ApplyWorkspaceEditParams, ApplyWorkspaceEditResult>(
|
||||||
Method.workspace_applyEdit,
|
Method.workspace_applyEdit,
|
||||||
ApplyWorkspaceEditParams.fromJson,
|
ApplyWorkspaceEditParams.fromJson,
|
||||||
() => executeCommand(command),
|
() => executeCommand(command),
|
||||||
// Claim that we failed tpo apply the edits. This is what the client
|
// 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
|
// would do if the edits provided were for an old version of the
|
||||||
// document.
|
// document.
|
||||||
handler: (edit) => ApplyWorkspaceEditResponse(
|
handler: (edit) => ApplyWorkspaceEditResult(
|
||||||
applied: false, failureReason: 'Document changed'),
|
applied: false, failureReason: 'Document changed'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2169,7 +2169,7 @@ void f() {
|
||||||
// Execute the associated command (which will handle edits in other files).
|
// Execute the associated command (which will handle edits in other files).
|
||||||
ApplyWorkspaceEditParams? editParams;
|
ApplyWorkspaceEditParams? editParams;
|
||||||
final commandResponse = await handleExpectedRequest<Object?,
|
final commandResponse = await handleExpectedRequest<Object?,
|
||||||
ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
|
ApplyWorkspaceEditParams, ApplyWorkspaceEditResult>(
|
||||||
Method.workspace_applyEdit,
|
Method.workspace_applyEdit,
|
||||||
ApplyWorkspaceEditParams.fromJson,
|
ApplyWorkspaceEditParams.fromJson,
|
||||||
() => executeCommand(resolved.command!),
|
() => executeCommand(resolved.command!),
|
||||||
|
@ -2177,7 +2177,7 @@ void f() {
|
||||||
// When the server sends the edit back, just keep a copy and say we
|
// When the server sends the edit back, just keep a copy and say we
|
||||||
// applied successfully (it'll be verified below).
|
// applied successfully (it'll be verified below).
|
||||||
editParams = edit;
|
editParams = edit;
|
||||||
return ApplyWorkspaceEditResponse(applied: true);
|
return ApplyWorkspaceEditResult(applied: true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Successful edits return an empty success() response.
|
// Successful edits return an empty success() response.
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
|
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
|
||||||
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
|
|
||||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
|
import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
|
||||||
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
|
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
|
||||||
|
|
||||||
|
@ -40,12 +39,12 @@ class MockLspServerChannel implements LspServerCommunicationChannel {
|
||||||
// `window/showMessage`.
|
// `window/showMessage`.
|
||||||
_serverToClient.stream.listen((message) {
|
_serverToClient.stream.listen((message) {
|
||||||
if (message is lsp.NotificationMessage &&
|
if (message is lsp.NotificationMessage &&
|
||||||
message.method == Method.window_showMessage) {
|
message.method == lsp.Method.window_showMessage) {
|
||||||
final params = message.params;
|
final params = message.params;
|
||||||
if (params is lsp.ShowMessageParams) {
|
if (params is lsp.ShowMessageParams) {
|
||||||
if (params.type == MessageType.Error) {
|
if (params.type == lsp.MessageType.Error) {
|
||||||
shownErrors.add(params);
|
shownErrors.add(params);
|
||||||
} else if (params.type == MessageType.Warning) {
|
} else if (params.type == lsp.MessageType.Warning) {
|
||||||
shownWarnings.add(params);
|
shownWarnings.add(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,13 +169,7 @@ class MockLspServerChannel implements LspServerCommunicationChannel {
|
||||||
}) async {
|
}) async {
|
||||||
final response = await _serverToClient.stream.firstWhere((message) =>
|
final response = await _serverToClient.stream.firstWhere((message) =>
|
||||||
(message is lsp.ResponseMessage && message.id == request.id) ||
|
(message is lsp.ResponseMessage && message.id == request.id) ||
|
||||||
(throwOnError &&
|
(throwOnError && _isShowErrorMessageNotification(message)));
|
||||||
message is lsp.NotificationMessage &&
|
|
||||||
message.method == Method.window_showMessage &&
|
|
||||||
lsp.ShowMessageParams.fromJson(
|
|
||||||
message.params as Map<String, Object?>)
|
|
||||||
.type ==
|
|
||||||
MessageType.Error));
|
|
||||||
|
|
||||||
if (response is lsp.ResponseMessage) {
|
if (response is lsp.ResponseMessage) {
|
||||||
return response;
|
return response;
|
||||||
|
@ -195,4 +188,19 @@ class MockLspServerChannel implements LspServerCommunicationChannel {
|
||||||
return constructor(
|
return constructor(
|
||||||
jsonDecode(jsonEncode(message.toJson())) as Map<String, Object?>);
|
jsonDecode(jsonEncode(message.toJson())) as Map<String, Object?>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether [message] is a `window/showMessage` notification with a
|
||||||
|
/// type of [lsp.MessageType.Error].
|
||||||
|
bool _isShowErrorMessageNotification(lsp.Message message) {
|
||||||
|
if (message is! lsp.NotificationMessage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (message.method != lsp.Method.window_showMessage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final params = lsp.ShowMessageParams.fromJson(
|
||||||
|
message.params as Map<String, Object?>,
|
||||||
|
);
|
||||||
|
return params.type == lsp.MessageType.Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ final Uri specLicenseUri = Uri.parse(
|
||||||
/// The URI of the version of the spec to generate from. This should be periodically updated as
|
/// The URI of the version of the spec to generate from. This should be periodically updated as
|
||||||
/// there's no longer a stable URI for the latest published version.
|
/// there's no longer a stable URI for the latest published version.
|
||||||
final Uri specUri = Uri.parse(
|
final Uri specUri = Uri.parse(
|
||||||
'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/specification-3-16.md');
|
'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/3.17/specification.md');
|
||||||
|
|
||||||
/// Pattern to extract inline types from the `result: {xx, yy }` notes in the spec.
|
/// Pattern to extract inline types from the `result: {xx, yy }` notes in the spec.
|
||||||
/// Doesn't parse past full stops as some of these have english sentences tagged on
|
/// Doesn't parse past full stops as some of these have english sentences tagged on
|
||||||
|
@ -90,7 +90,7 @@ To regenerate the generated code, run the script in
|
||||||
download the latest version of the specification before regenerating the
|
download the latest version of the specification before regenerating the
|
||||||
code, run the same script with an argument of "--download".''',
|
code, run the same script with an argument of "--download".''',
|
||||||
licenseResp.body,
|
licenseResp.body,
|
||||||
specResp.body
|
await _fetchIncludes(specResp.body, specUri),
|
||||||
];
|
];
|
||||||
await File(localSpecPath).writeAsString(text.join('\n\n---\n\n'));
|
await File(localSpecPath).writeAsString(text.join('\n\n---\n\n'));
|
||||||
}
|
}
|
||||||
|
@ -203,6 +203,16 @@ List<AstNode> getCustomClasses() {
|
||||||
}
|
}
|
||||||
|
|
||||||
final customTypes = <AstNode>[
|
final customTypes = <AstNode>[
|
||||||
|
TypeAlias(
|
||||||
|
null,
|
||||||
|
Token.identifier('LSPAny'),
|
||||||
|
Type.Any,
|
||||||
|
),
|
||||||
|
TypeAlias(
|
||||||
|
null,
|
||||||
|
Token.identifier('LSPObject'),
|
||||||
|
Type.Any,
|
||||||
|
),
|
||||||
interface('DartDiagnosticServer', [field('port', type: 'int')]),
|
interface('DartDiagnosticServer', [field('port', type: 'int')]),
|
||||||
interface('AnalyzerStatusParams', [field('isAnalyzing', type: 'boolean')]),
|
interface('AnalyzerStatusParams', [field('isAnalyzing', type: 'boolean')]),
|
||||||
interface('PublishClosingLabelsParams', [
|
interface('PublishClosingLabelsParams', [
|
||||||
|
@ -370,7 +380,8 @@ bool shouldIncludeScriptBlock(String input) {
|
||||||
// Skip over some typescript blocks that are known sample code and not part
|
// Skip over some typescript blocks that are known sample code and not part
|
||||||
// of the LSP spec.
|
// of the LSP spec.
|
||||||
if (input.trim() == r"export const EOL: string[] = ['\n', '\r\n', '\r'];" ||
|
if (input.trim() == r"export const EOL: string[] = ['\n', '\r\n', '\r'];" ||
|
||||||
input.startsWith('textDocument.codeAction.resolveSupport =')) {
|
input.startsWith('textDocument.codeAction.resolveSupport =') ||
|
||||||
|
input.startsWith('textDocument.inlayHint.resolveSupport =')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,3 +427,23 @@ AstNode withCustomFields(AstNode node) {
|
||||||
[...node.members, ...customFields],
|
[...node.members, ...customFields],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches and in-lines any includes that appear in [spec] in the form
|
||||||
|
/// `{% include_relative types/uri.md %}`.
|
||||||
|
Future<String> _fetchIncludes(String spec, Uri baseUri) async {
|
||||||
|
final pattern = RegExp(r'{% include_relative ([\w\-.\/]+.md) %}');
|
||||||
|
final includeStrings = <String, String>{};
|
||||||
|
for (final match in pattern.allMatches(spec)) {
|
||||||
|
final relativeUri = match.group(1)!;
|
||||||
|
final fullUri = baseUri.resolve(relativeUri);
|
||||||
|
final response = await http.get(fullUri);
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw 'Faild to fetch $fullUri (${response.statusCode} ${response.reasonPhrase})';
|
||||||
|
}
|
||||||
|
includeStrings[relativeUri] = response.body;
|
||||||
|
}
|
||||||
|
return spec.replaceAllMapped(
|
||||||
|
pattern,
|
||||||
|
(match) => includeStrings[match.group(1)!]!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,9 +2,8 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
final _methodNamesPattern = RegExp(
|
final _methodNamesPattern =
|
||||||
r'''_(?:Notification|Request):?_:?(?:\r?\n)+\* method: ['`](.*?)[`'],?\r?\n''',
|
RegExp(r'''\* method: ['`](.*?)[`'],?\r?\n''', multiLine: true);
|
||||||
multiLine: true);
|
|
||||||
final _typeScriptBlockPattern =
|
final _typeScriptBlockPattern =
|
||||||
RegExp(r'\B```typescript([\S\s]*?)\n\s*```', multiLine: true);
|
RegExp(r'\B```typescript([\S\s]*?)\n\s*```', multiLine: true);
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ List<String> getSpecialBaseTypes(Interface interface) {
|
||||||
|
|
||||||
/// Removes types that are in the spec that we don't want to emit.
|
/// Removes types that are in the spec that we don't want to emit.
|
||||||
bool includeTypeDefinitionInOutput(AstNode node) {
|
bool includeTypeDefinitionInOutput(AstNode node) {
|
||||||
// These types are not used for v3.0 (Feb 2017) and by dropping them we don't
|
// InitializeError is not used for v3.0 (Feb 2017) and by dropping it we don't
|
||||||
// have to handle any cases where both a namespace and interfaces are declared
|
// have to handle any cases where both a namespace and interfaces are declared
|
||||||
// with the same name.
|
// with the same name.
|
||||||
return node.name != 'InitializeError' &&
|
return node.name != 'InitializeError' &&
|
||||||
|
|
|
@ -27,7 +27,11 @@ final _keywords = const <String, TokenType>{
|
||||||
final _validIdentifierCharacters = RegExp('[a-zA-Z0-9_]');
|
final _validIdentifierCharacters = RegExp('[a-zA-Z0-9_]');
|
||||||
|
|
||||||
bool isAnyType(TypeBase t) =>
|
bool isAnyType(TypeBase t) =>
|
||||||
t is Type && (t.name == 'any' || t.name == 'object');
|
t is Type &&
|
||||||
|
(t.name == 'any' ||
|
||||||
|
t.name == 'LSPAny' ||
|
||||||
|
t.name == 'object' ||
|
||||||
|
t.name == 'LSPObject');
|
||||||
|
|
||||||
bool isLiteralType(TypeBase t) => t is LiteralType;
|
bool isLiteralType(TypeBase t) => t is LiteralType;
|
||||||
|
|
||||||
|
@ -251,6 +255,8 @@ class Parser {
|
||||||
if (_nodes.isEmpty) {
|
if (_nodes.isEmpty) {
|
||||||
while (!_isAtEnd) {
|
while (!_isAtEnd) {
|
||||||
_nodes.add(_topLevel());
|
_nodes.add(_topLevel());
|
||||||
|
// Consume any trailing semicolons.
|
||||||
|
_match([TokenType.SEMI_COLON]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _nodes;
|
return _nodes;
|
||||||
|
|
Loading…
Reference in a new issue