mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 13:28:03 +00:00
Add some special cases for types we can't/don't need to parse
Includes a fabricated base type for file operations to avoid a List of a Union. Change-Id: I0ddc7c6428cc8f1535c3a8d7d0b042b1725969f3 Reviewed-on: https://dart-review.googlesource.com/c/79323 Commit-Queue: Danny Tuppeny <dantup@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
49b121f20d
commit
2989116219
|
@ -6,6 +6,8 @@
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/lsp_spec/generate_all.dart".
|
||||
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
|
||||
class ApplyWorkspaceEditParams {
|
||||
/// The edits to apply.
|
||||
WorkspaceEdit edit;
|
||||
|
@ -177,7 +179,7 @@ class CodeLensParams {
|
|||
TextDocumentIdentifier textDocument;
|
||||
}
|
||||
|
||||
class CodeLensRegistrationOptions {
|
||||
class CodeLensRegistrationOptions extends TextDocumentRegistrationOptions {
|
||||
/// Code lens has a resolve provider as well.
|
||||
bool resolveProvider;
|
||||
}
|
||||
|
@ -410,14 +412,14 @@ class CompletionOptions {
|
|||
List<String> triggerCharacters;
|
||||
}
|
||||
|
||||
class CompletionParams {
|
||||
class CompletionParams extends TextDocumentPositionParams {
|
||||
/// The completion context. This is only available if the client specifies to
|
||||
/// send this using `ClientCapabilities.textDocument.completion.contextSupport
|
||||
/// === true`
|
||||
CompletionContext context;
|
||||
}
|
||||
|
||||
class CompletionRegistrationOptions {
|
||||
class CompletionRegistrationOptions extends TextDocumentRegistrationOptions {
|
||||
/// The server provides support to resolve additional information for a
|
||||
/// completion item.
|
||||
bool resolveProvider;
|
||||
|
@ -462,7 +464,7 @@ class ConfigurationParams {
|
|||
}
|
||||
|
||||
/// Create file operation
|
||||
class CreateFile {
|
||||
class CreateFile extends FileOperation {
|
||||
/// Additional options
|
||||
CreateFileOptions options;
|
||||
|
||||
|
@ -480,7 +482,7 @@ class CreateFileOptions {
|
|||
}
|
||||
|
||||
/// Delete file operation
|
||||
class DeleteFile {
|
||||
class DeleteFile extends FileOperation {
|
||||
/// Delete options.
|
||||
DeleteFileOptions options;
|
||||
|
||||
|
@ -664,7 +666,7 @@ class DocumentLinkParams {
|
|||
TextDocumentIdentifier textDocument;
|
||||
}
|
||||
|
||||
class DocumentLinkRegistrationOptions {
|
||||
class DocumentLinkRegistrationOptions extends TextDocumentRegistrationOptions {
|
||||
/// Document links have a resolve provider as well.
|
||||
bool resolveProvider;
|
||||
}
|
||||
|
@ -692,7 +694,8 @@ class DocumentOnTypeFormattingParams {
|
|||
TextDocumentIdentifier textDocument;
|
||||
}
|
||||
|
||||
class DocumentOnTypeFormattingRegistrationOptions {
|
||||
class DocumentOnTypeFormattingRegistrationOptions
|
||||
extends TextDocumentRegistrationOptions {
|
||||
/// A character on which formatting should be triggered, like `}`.
|
||||
String firstTriggerCharacter;
|
||||
|
||||
|
@ -1003,7 +1006,7 @@ abstract class MessageType {
|
|||
static const Warning = 2;
|
||||
}
|
||||
|
||||
class NotificationMessage {
|
||||
class NotificationMessage extends Message {
|
||||
/// The method to be invoked.
|
||||
String method;
|
||||
}
|
||||
|
@ -1053,7 +1056,7 @@ class ReferenceContext {
|
|||
bool includeDeclaration;
|
||||
}
|
||||
|
||||
class ReferenceParams {
|
||||
class ReferenceParams extends TextDocumentPositionParams {
|
||||
ReferenceContext context;
|
||||
}
|
||||
|
||||
|
@ -1075,7 +1078,7 @@ class RegistrationParams {
|
|||
}
|
||||
|
||||
/// Rename file operation
|
||||
class RenameFile {
|
||||
class RenameFile extends FileOperation {
|
||||
/// The new location.
|
||||
String newUri;
|
||||
|
||||
|
@ -1113,12 +1116,12 @@ class RenameParams {
|
|||
TextDocumentIdentifier textDocument;
|
||||
}
|
||||
|
||||
class RenameRegistrationOptions {
|
||||
class RenameRegistrationOptions extends TextDocumentRegistrationOptions {
|
||||
/// Renames should be checked and tested for validity before being executed.
|
||||
bool prepareProvider;
|
||||
}
|
||||
|
||||
class RequestMessage {
|
||||
class RequestMessage extends Message {
|
||||
/// The request id.
|
||||
Object /*Either<num, String>*/ id;
|
||||
|
||||
|
@ -1137,7 +1140,7 @@ abstract class ResourceOperationKind {
|
|||
static const Rename = 'rename';
|
||||
}
|
||||
|
||||
class ResponseMessage {
|
||||
class ResponseMessage extends Message {
|
||||
/// The request id.
|
||||
Object /*Either<num, String>*/ id;
|
||||
|
||||
|
@ -1270,7 +1273,7 @@ class SignatureHelpOptions {
|
|||
List<String> triggerCharacters;
|
||||
}
|
||||
|
||||
class SignatureHelpRegistrationOptions {
|
||||
class SignatureHelpRegistrationOptions extends TextDocumentRegistrationOptions {
|
||||
/// The characters that trigger signature help automatically.
|
||||
List<String> triggerCharacters;
|
||||
}
|
||||
|
@ -1383,7 +1386,8 @@ abstract class SymbolKind {
|
|||
|
||||
/// Describe options to be used when registering for text document change
|
||||
/// events.
|
||||
class TextDocumentChangeRegistrationOptions {
|
||||
class TextDocumentChangeRegistrationOptions
|
||||
extends TextDocumentRegistrationOptions {
|
||||
/// How documents are synced to the server. See TextDocumentSyncKind.Full and
|
||||
/// TextDocumentSyncKind.Incremental.
|
||||
num syncKind;
|
||||
|
@ -1420,7 +1424,7 @@ class TextDocumentContentChangeEvent {
|
|||
String text;
|
||||
}
|
||||
|
||||
class TextDocumentEdit {
|
||||
class TextDocumentEdit extends FileOperation {
|
||||
/// The edits to be applied.
|
||||
List<TextEdit> edits;
|
||||
|
||||
|
@ -1475,7 +1479,8 @@ abstract class TextDocumentSaveReason {
|
|||
static const Manual = 1;
|
||||
}
|
||||
|
||||
class TextDocumentSaveRegistrationOptions {
|
||||
class TextDocumentSaveRegistrationOptions
|
||||
extends TextDocumentRegistrationOptions {
|
||||
/// The client is supposed to include the content on save.
|
||||
bool includeText;
|
||||
}
|
||||
|
@ -1537,7 +1542,7 @@ class UnregistrationParams {
|
|||
List<Unregistration> unregisterations;
|
||||
}
|
||||
|
||||
class VersionedTextDocumentIdentifier {
|
||||
class VersionedTextDocumentIdentifier extends TextDocumentIdentifier {
|
||||
/// The version number of this document. If a versioned text document
|
||||
/// identifier is sent from the server to the client and the file is not open
|
||||
/// in the editor (the server has not received an open notification before)
|
||||
|
@ -1587,7 +1592,25 @@ class WorkspaceClientCapabilities {
|
|||
List<ResourceOperationKind> resourceOperations;
|
||||
}
|
||||
|
||||
class WorkspaceEdit {}
|
||||
class WorkspaceEdit {
|
||||
/// Holds changes to existing resources.
|
||||
Map<String, List<TextEdit>> changes;
|
||||
|
||||
/// Depending on the client capability
|
||||
/// `workspace.workspaceEdit.resourceOperations` document changes are either
|
||||
/// an array of `TextDocumentEdit`s to express changes to n different text
|
||||
/// documents where each text document edit addresses a specific version of a
|
||||
/// text document. Or it can contain above `TextDocumentEdit`s mixed with
|
||||
/// create, rename and delete file / folder operations.
|
||||
///
|
||||
/// Whether a client supports versioned document edits is expressed via
|
||||
/// `workspace.workspaceEdit.documentChanges` client capability.
|
||||
///
|
||||
/// If a client neither supports `documentChanges` nor
|
||||
/// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
|
||||
/// using the `changes` property are supported.
|
||||
List<FileOperation> documentChanges;
|
||||
}
|
||||
|
||||
class WorkspaceFolder {
|
||||
/// The name of the workspace folder. Defaults to the uri's basename.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
class FileOperation {}
|
|
@ -32,6 +32,7 @@ String _mapType(String type) {
|
|||
'string': 'String',
|
||||
'number': 'num',
|
||||
'any': 'Object',
|
||||
'{ [uri: string]: TextEdit[]; }': 'Map<String, List<TextEdit>>',
|
||||
};
|
||||
return types[type] ?? type;
|
||||
}
|
||||
|
@ -114,8 +115,12 @@ void _writeInterface(IndentableStringBuffer buffer, Interface interface) {
|
|||
return;
|
||||
}
|
||||
|
||||
buffer.writeIndented('class ${interface.name} ');
|
||||
if (interface.baseTypes.isNotEmpty) {
|
||||
buffer.writeIndented('extends ${interface.baseTypes.join(', ')} ');
|
||||
}
|
||||
buffer
|
||||
..writeln('class ${interface.name} {')
|
||||
..writeln('{')
|
||||
..indent();
|
||||
// TODO(dantup): Generate constructors (inc. type checks for unions)
|
||||
_writeMembers(buffer, interface.members);
|
||||
|
@ -123,7 +128,7 @@ void _writeInterface(IndentableStringBuffer buffer, Interface interface) {
|
|||
// TODO(dantup): Generate fromJson()
|
||||
buffer
|
||||
..outdent()
|
||||
..writeln('}')
|
||||
..writeIndentedLn('}')
|
||||
..writeln();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ const _generatedFileHeader = '''
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/lsp_spec/generate_all.dart".
|
||||
|
||||
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
|
||||
|
||||
''';
|
||||
|
||||
main() async {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// TODO(dantup): Regex seemed like a good choice when parsing the first few...
|
||||
// maybe it's not so great now. We should parse this properly if it turns out
|
||||
// there are issues with what we have here.
|
||||
const String _blockBody = r'\{([\s\S]*?)\s+\}';
|
||||
const String _blockBody = r'\{([\s\S]*?)\s*\n\s*\}';
|
||||
const String _comment = r'(?:\/\*\*((?:[\S\s](?!\*\/))+?)\s\*\/)?\s*';
|
||||
|
||||
List<ApiItem> extractAllTypes(List<String> code) {
|
||||
|
@ -60,6 +60,11 @@ List<ApiItem> _mergeTypes(List<ApiItem> items) {
|
|||
}
|
||||
|
||||
List<String> _parseTypes(String baseTypes, String sep) {
|
||||
// Special case for a single complicated type we can't parse easily...
|
||||
if (baseTypes ==
|
||||
'(TextDocumentEdit[] | (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[])') {
|
||||
return ['FileOperation[]'];
|
||||
}
|
||||
return baseTypes?.split(sep)?.map((t) => t.trim())?.toList() ?? [];
|
||||
}
|
||||
|
||||
|
@ -115,13 +120,26 @@ class Field extends Member {
|
|||
: super(name, comment);
|
||||
|
||||
static List<Field> extractFrom(String code) {
|
||||
final RegExp _fieldPattern =
|
||||
new RegExp(_comment + r'(\w+\??)\s*:\s*([\w\[\]\s|]+)\s*(?:;|$)');
|
||||
final RegExp _fieldPattern = new RegExp(
|
||||
_comment + r'([\w\[\]]+\??)\s*:\s*([\w\[\] \|\{\}\(\):;]+)\s*(?:;|$)');
|
||||
|
||||
final fields = _fieldPattern.allMatches(code).map((m) {
|
||||
final fields = _fieldPattern.allMatches(code).where((m) {
|
||||
// Skip over the indexer in FormattingOptions since we don't need this
|
||||
// (for now) and it's complicated to represent.
|
||||
if (m.group(0).contains('[key: string]: boolean | number | string;')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).map((m) {
|
||||
final String comment = m.group(1);
|
||||
String name = m.group(2);
|
||||
final List<String> types = _parseTypes(m.group(3), '|');
|
||||
String typesString = m.group(3).trim();
|
||||
// Our regex may result in semicolons on the end...
|
||||
// TODO(dantup): Fix this, or make a simple parser.
|
||||
if (typesString.endsWith(';')) {
|
||||
typesString = typesString.substring(0, typesString.length - 1);
|
||||
}
|
||||
final List<String> types = _parseTypes(typesString, '|');
|
||||
final bool allowsNull = types.contains('null');
|
||||
if (allowsNull) {
|
||||
types.remove('null');
|
||||
|
@ -155,6 +173,10 @@ class Interface extends ApiItem {
|
|||
final List<String> baseTypes = _parseTypes(match.group(3), ',');
|
||||
final String body = match.group(4);
|
||||
final List<Member> members = Member.extractFrom(body);
|
||||
|
||||
// Add any special base classes we've added to simplify types.
|
||||
baseTypes.addAll(_getSpecialBaseClasses(name));
|
||||
|
||||
return new Interface(name, comment, baseTypes, members);
|
||||
}).toList();
|
||||
_sort(interfaces);
|
||||
|
@ -162,6 +184,20 @@ class Interface extends ApiItem {
|
|||
}
|
||||
}
|
||||
|
||||
List<String> _getSpecialBaseClasses(String name) {
|
||||
const fileOperationTypes = [
|
||||
'TextDocumentEdit',
|
||||
'CreateFile',
|
||||
'RenameFile',
|
||||
'DeleteFile'
|
||||
];
|
||||
if (fileOperationTypes.contains(name)) {
|
||||
return ['FileOperation'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// A Field or Constant parsed from the LSP type.
|
||||
abstract class Member extends ApiItem {
|
||||
Member(String name, String comment) : super(name, comment);
|
||||
|
|
Loading…
Reference in a new issue