From ff61ff7d33a93270a6ca82cc121684f4c1a927f8 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Tue, 2 Mar 2021 15:24:38 +0000 Subject: [PATCH] [analyzer] Call toJson() on items in Lists when generating LSP json Change-Id: I9f5876dc577499ae609079eaecae6a3eb47535d7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188288 Reviewed-by: Brian Wilkerson Commit-Queue: Brian Wilkerson --- .../protocol_custom_generated.dart | 9 +- .../lib/lsp_protocol/protocol_generated.dart | 155 ++++++++++-------- .../test/tool/lsp_spec/json_test.dart | 13 ++ .../tool/lsp_spec/codegen_dart.dart | 18 +- 4 files changed, 124 insertions(+), 71 deletions(-) diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart index 6a1ba57e9dd..e4b17e6e4c8 100644 --- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart +++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart @@ -838,7 +838,7 @@ class FlutterOutline implements ToJsonable { __result['variableName'] = variableName; } if (attributes != null) { - __result['attributes'] = attributes; + __result['attributes'] = attributes.map((item) => item.toJson()).toList(); } if (dartElement != null) { __result['dartElement'] = dartElement.toJson(); @@ -848,7 +848,7 @@ class FlutterOutline implements ToJsonable { __result['codeRange'] = codeRange?.toJson() ?? (throw 'codeRange is required but was not set'); if (children != null) { - __result['children'] = children; + __result['children'] = children.map((item) => item.toJson()).toList(); } return __result; } @@ -1178,7 +1178,7 @@ class Outline implements ToJsonable { __result['codeRange'] = codeRange?.toJson() ?? (throw 'codeRange is required but was not set'); if (children != null) { - __result['children'] = children; + __result['children'] = children.map((item) => item.toJson()).toList(); } return __result; } @@ -1309,7 +1309,8 @@ class PublishClosingLabelsParams implements ToJsonable { Map toJson() { var __result = {}; __result['uri'] = uri ?? (throw 'uri is required but was not set'); - __result['labels'] = labels ?? (throw 'labels is required but was not set'); + __result['labels'] = labels?.map((item) => item.toJson())?.toList() ?? + (throw 'labels is required but was not set'); return __result; } diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart index 3438d4b3ae9..4af958b56b3 100644 --- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart +++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart @@ -463,7 +463,8 @@ class CallHierarchyIncomingCall implements ToJsonable { __result['from'] = from?.toJson() ?? (throw 'from is required but was not set'); __result['fromRanges'] = - fromRanges ?? (throw 'fromRanges is required but was not set'); + fromRanges?.map((item) => item.toJson())?.toList() ?? + (throw 'fromRanges is required but was not set'); return __result; } @@ -755,7 +756,7 @@ class CallHierarchyItem implements ToJsonable { __result['kind'] = kind?.toJson() ?? (throw 'kind is required but was not set'); if (tags != null) { - __result['tags'] = tags; + __result['tags'] = tags.map((item) => item.toJson()).toList(); } if (detail != null) { __result['detail'] = detail; @@ -1024,7 +1025,8 @@ class CallHierarchyOutgoingCall implements ToJsonable { var __result = {}; __result['to'] = to?.toJson() ?? (throw 'to is required but was not set'); __result['fromRanges'] = - fromRanges ?? (throw 'fromRanges is required but was not set'); + fromRanges?.map((item) => item.toJson())?.toList() ?? + (throw 'fromRanges is required but was not set'); return __result; } @@ -2637,7 +2639,8 @@ class CodeAction implements ToJsonable { __result['kind'] = kind.toJson(); } if (diagnostics != null) { - __result['diagnostics'] = diagnostics; + __result['diagnostics'] = + diagnostics.map((item) => item.toJson()).toList(); } if (isPreferred != null) { __result['isPreferred'] = isPreferred; @@ -3026,8 +3029,8 @@ class CodeActionClientCapabilitiesCodeActionKind implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } @@ -3281,9 +3284,10 @@ class CodeActionContext implements ToJsonable { Map toJson() { var __result = {}; __result['diagnostics'] = - diagnostics ?? (throw 'diagnostics is required but was not set'); + diagnostics?.map((item) => item.toJson())?.toList() ?? + (throw 'diagnostics is required but was not set'); if (only != null) { - __result['only'] = only; + __result['only'] = only.map((item) => item.toJson()).toList(); } return __result; } @@ -3532,7 +3536,8 @@ class CodeActionOptions implements WorkDoneProgressOptions, ToJsonable { Map toJson() { var __result = {}; if (codeActionKinds != null) { - __result['codeActionKinds'] = codeActionKinds; + __result['codeActionKinds'] = + codeActionKinds.map((item) => item.toJson()).toList(); } if (resolveProvider != null) { __result['resolveProvider'] = resolveProvider; @@ -3853,7 +3858,8 @@ class CodeActionRegistrationOptions var __result = {}; __result['documentSelector'] = documentSelector; if (codeActionKinds != null) { - __result['codeActionKinds'] = codeActionKinds; + __result['codeActionKinds'] = + codeActionKinds.map((item) => item.toJson()).toList(); } if (resolveProvider != null) { __result['resolveProvider'] = resolveProvider; @@ -4885,7 +4891,8 @@ class ColorPresentation implements ToJsonable { __result['textEdit'] = textEdit.toJson(); } if (additionalTextEdits != null) { - __result['additionalTextEdits'] = additionalTextEdits; + __result['additionalTextEdits'] = + additionalTextEdits.map((item) => item.toJson()).toList(); } return __result; } @@ -5512,7 +5519,8 @@ class CompletionClientCapabilitiesCompletionItem implements ToJsonable { __result['commitCharactersSupport'] = commitCharactersSupport; } if (documentationFormat != null) { - __result['documentationFormat'] = documentationFormat; + __result['documentationFormat'] = + documentationFormat.map((item) => item.toJson()).toList(); } if (deprecatedSupport != null) { __result['deprecatedSupport'] = deprecatedSupport; @@ -5707,7 +5715,7 @@ class CompletionClientCapabilitiesCompletionItemKind implements ToJsonable { Map toJson() { var __result = {}; if (valueSet != null) { - __result['valueSet'] = valueSet; + __result['valueSet'] = valueSet.map((item) => item.toJson()).toList(); } return __result; } @@ -5780,8 +5788,8 @@ class CompletionClientCapabilitiesInsertTextModeSupport implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } @@ -5938,8 +5946,8 @@ class CompletionClientCapabilitiesTagSupport implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } @@ -6300,7 +6308,7 @@ class CompletionItem implements ToJsonable { __result['kind'] = kind.toJson(); } if (tags != null) { - __result['tags'] = tags; + __result['tags'] = tags.map((item) => item.toJson()).toList(); } if (detail != null) { __result['detail'] = detail; @@ -6333,7 +6341,8 @@ class CompletionItem implements ToJsonable { __result['textEdit'] = textEdit; } if (additionalTextEdits != null) { - __result['additionalTextEdits'] = additionalTextEdits; + __result['additionalTextEdits'] = + additionalTextEdits.map((item) => item.toJson()).toList(); } if (commitCharacters != null) { __result['commitCharacters'] = commitCharacters; @@ -6700,7 +6709,8 @@ class CompletionList implements ToJsonable { var __result = {}; __result['isIncomplete'] = isIncomplete ?? (throw 'isIncomplete is required but was not set'); - __result['items'] = items ?? (throw 'items is required but was not set'); + __result['items'] = items?.map((item) => item.toJson())?.toList() ?? + (throw 'items is required but was not set'); return __result; } @@ -7438,7 +7448,8 @@ class ConfigurationParams implements ToJsonable { Map toJson() { var __result = {}; - __result['items'] = items ?? (throw 'items is required but was not set'); + __result['items'] = items?.map((item) => item.toJson())?.toList() ?? + (throw 'items is required but was not set'); return __result; } @@ -7738,7 +7749,8 @@ class CreateFilesParams implements ToJsonable { Map toJson() { var __result = {}; - __result['files'] = files ?? (throw 'files is required but was not set'); + __result['files'] = files?.map((item) => item.toJson())?.toList() ?? + (throw 'files is required but was not set'); return __result; } @@ -8866,7 +8878,8 @@ class DeleteFilesParams implements ToJsonable { Map toJson() { var __result = {}; - __result['files'] = files ?? (throw 'files is required but was not set'); + __result['files'] = files?.map((item) => item.toJson())?.toList() ?? + (throw 'files is required but was not set'); return __result; } @@ -9027,10 +9040,11 @@ class Diagnostic implements ToJsonable { __result['message'] = message ?? (throw 'message is required but was not set'); if (tags != null) { - __result['tags'] = tags; + __result['tags'] = tags.map((item) => item.toJson()).toList(); } if (relatedInformation != null) { - __result['relatedInformation'] = relatedInformation; + __result['relatedInformation'] = + relatedInformation.map((item) => item.toJson()).toList(); } if (data != null) { __result['data'] = data; @@ -9730,8 +9744,8 @@ class DidChangeWatchedFilesParams implements ToJsonable { Map toJson() { var __result = {}; - __result['changes'] = - changes ?? (throw 'changes is required but was not set'); + __result['changes'] = changes?.map((item) => item.toJson())?.toList() ?? + (throw 'changes is required but was not set'); return __result; } @@ -9810,8 +9824,8 @@ class DidChangeWatchedFilesRegistrationOptions implements ToJsonable { Map toJson() { var __result = {}; - __result['watchers'] = - watchers ?? (throw 'watchers is required but was not set'); + __result['watchers'] = watchers?.map((item) => item.toJson())?.toList() ?? + (throw 'watchers is required but was not set'); return __result; } @@ -13040,7 +13054,7 @@ class DocumentSymbol implements ToJsonable { __result['kind'] = kind?.toJson() ?? (throw 'kind is required but was not set'); if (tags != null) { - __result['tags'] = tags; + __result['tags'] = tags.map((item) => item.toJson()).toList(); } if (deprecated != null) { __result['deprecated'] = deprecated; @@ -13050,7 +13064,7 @@ class DocumentSymbol implements ToJsonable { __result['selectionRange'] = selectionRange?.toJson() ?? (throw 'selectionRange is required but was not set'); if (children != null) { - __result['children'] = children; + __result['children'] = children.map((item) => item.toJson()).toList(); } return __result; } @@ -13402,7 +13416,7 @@ class DocumentSymbolClientCapabilitiesSymbolKind implements ToJsonable { Map toJson() { var __result = {}; if (valueSet != null) { - __result['valueSet'] = valueSet; + __result['valueSet'] = valueSet.map((item) => item.toJson()).toList(); } return __result; } @@ -13475,8 +13489,8 @@ class DocumentSymbolClientCapabilitiesTagSupport implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } @@ -14940,8 +14954,8 @@ class FileOperationRegistrationOptions implements ToJsonable { Map toJson() { var __result = {}; - __result['filters'] = - filters ?? (throw 'filters is required but was not set'); + __result['filters'] = filters?.map((item) => item.toJson())?.toList() ?? + (throw 'filters is required but was not set'); return __result; } @@ -16112,7 +16126,8 @@ class HoverClientCapabilities implements ToJsonable { __result['dynamicRegistration'] = dynamicRegistration; } if (contentFormat != null) { - __result['contentFormat'] = contentFormat; + __result['contentFormat'] = + contentFormat.map((item) => item.toJson()).toList(); } return __result; } @@ -17014,7 +17029,8 @@ class InitializeParams implements WorkDoneProgressParams, ToJsonable { __result['trace'] = trace; } if (workspaceFolders != null) { - __result['workspaceFolders'] = workspaceFolders; + __result['workspaceFolders'] = + workspaceFolders.map((item) => item.toJson()).toList(); } if (workDoneToken != null) { __result['workDoneToken'] = workDoneToken; @@ -18114,7 +18130,8 @@ class LinkedEditingRanges implements ToJsonable { Map toJson() { var __result = {}; - __result['ranges'] = ranges ?? (throw 'ranges is required but was not set'); + __result['ranges'] = ranges?.map((item) => item.toJson())?.toList() ?? + (throw 'ranges is required but was not set'); if (wordPattern != null) { __result['wordPattern'] = wordPattern; } @@ -20855,8 +20872,8 @@ class PublishDiagnosticsClientCapabilitiesTagSupport implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } @@ -20953,7 +20970,8 @@ class PublishDiagnosticsParams implements ToJsonable { __result['version'] = version; } __result['diagnostics'] = - diagnostics ?? (throw 'diagnostics is required but was not set'); + diagnostics?.map((item) => item.toJson())?.toList() ?? + (throw 'diagnostics is required but was not set'); return __result; } @@ -21847,7 +21865,8 @@ class RegistrationParams implements ToJsonable { Map toJson() { var __result = {}; __result['registrations'] = - registrations ?? (throw 'registrations is required but was not set'); + registrations?.map((item) => item.toJson())?.toList() ?? + (throw 'registrations is required but was not set'); return __result; } @@ -22413,7 +22432,8 @@ class RenameFilesParams implements ToJsonable { Map toJson() { var __result = {}; - __result['files'] = files ?? (throw 'files is required but was not set'); + __result['files'] = files?.map((item) => item.toJson())?.toList() ?? + (throw 'files is required but was not set'); return __result; } @@ -23601,8 +23621,8 @@ class SelectionRangeParams var __result = {}; __result['textDocument'] = textDocument?.toJson() ?? (throw 'textDocument is required but was not set'); - __result['positions'] = - positions ?? (throw 'positions is required but was not set'); + __result['positions'] = positions?.map((item) => item.toJson())?.toList() ?? + (throw 'positions is required but was not set'); if (workDoneToken != null) { __result['workDoneToken'] = workDoneToken; } @@ -24087,8 +24107,8 @@ class SemanticTokensClientCapabilities implements ToJsonable { tokenTypes ?? (throw 'tokenTypes is required but was not set'); __result['tokenModifiers'] = tokenModifiers ?? (throw 'tokenModifiers is required but was not set'); - __result['formats'] = - formats ?? (throw 'formats is required but was not set'); + __result['formats'] = formats?.map((item) => item.toJson())?.toList() ?? + (throw 'formats is required but was not set'); if (overlappingTokenSupport != null) { __result['overlappingTokenSupport'] = overlappingTokenSupport; } @@ -24492,7 +24512,8 @@ class SemanticTokensDelta implements ToJsonable { if (resultId != null) { __result['resultId'] = resultId; } - __result['edits'] = edits ?? (throw 'edits is required but was not set'); + __result['edits'] = edits?.map((item) => item.toJson())?.toList() ?? + (throw 'edits is required but was not set'); return __result; } @@ -24743,7 +24764,8 @@ class SemanticTokensDeltaPartialResult implements ToJsonable { Map toJson() { var __result = {}; - __result['edits'] = edits ?? (throw 'edits is required but was not set'); + __result['edits'] = edits?.map((item) => item.toJson())?.toList() ?? + (throw 'edits is required but was not set'); return __result; } @@ -27928,7 +27950,7 @@ class ShowMessageRequestParams implements ToJsonable { __result['message'] = message ?? (throw 'message is required but was not set'); if (actions != null) { - __result['actions'] = actions; + __result['actions'] = actions.map((item) => item.toJson()).toList(); } return __result; } @@ -28066,7 +28088,8 @@ class SignatureHelp implements ToJsonable { Map toJson() { var __result = {}; __result['signatures'] = - signatures ?? (throw 'signatures is required but was not set'); + signatures?.map((item) => item.toJson())?.toList() ?? + (throw 'signatures is required but was not set'); if (activeSignature != null) { __result['activeSignature'] = activeSignature; } @@ -28377,7 +28400,8 @@ class SignatureHelpClientCapabilitiesSignatureInformation Map toJson() { var __result = {}; if (documentationFormat != null) { - __result['documentationFormat'] = documentationFormat; + __result['documentationFormat'] = + documentationFormat.map((item) => item.toJson()).toList(); } if (parameterInformation != null) { __result['parameterInformation'] = parameterInformation.toJson(); @@ -29153,7 +29177,7 @@ class SignatureInformation implements ToJsonable { __result['documentation'] = documentation; } if (parameters != null) { - __result['parameters'] = parameters; + __result['parameters'] = parameters.map((item) => item.toJson()).toList(); } if (activeParameter != null) { __result['activeParameter'] = activeParameter; @@ -29419,7 +29443,7 @@ class SymbolInformation implements ToJsonable { __result['kind'] = kind?.toJson() ?? (throw 'kind is required but was not set'); if (tags != null) { - __result['tags'] = tags; + __result['tags'] = tags.map((item) => item.toJson()).toList(); } if (deprecated != null) { __result['deprecated'] = deprecated; @@ -32447,8 +32471,9 @@ class UnregistrationParams implements ToJsonable { Map toJson() { var __result = {}; - __result['unregisterations'] = unregisterations ?? - (throw 'unregisterations is required but was not set'); + __result['unregisterations'] = + unregisterations?.map((item) => item.toJson())?.toList() ?? + (throw 'unregisterations is required but was not set'); return __result; } @@ -33817,7 +33842,8 @@ class WorkspaceEditClientCapabilities implements ToJsonable { __result['documentChanges'] = documentChanges; } if (resourceOperations != null) { - __result['resourceOperations'] = resourceOperations; + __result['resourceOperations'] = + resourceOperations.map((item) => item.toJson()).toList(); } if (failureHandling != null) { __result['failureHandling'] = failureHandling.toJson(); @@ -34120,9 +34146,10 @@ class WorkspaceFoldersChangeEvent implements ToJsonable { Map toJson() { var __result = {}; - __result['added'] = added ?? (throw 'added is required but was not set'); - __result['removed'] = - removed ?? (throw 'removed is required but was not set'); + __result['added'] = added?.map((item) => item.toJson())?.toList() ?? + (throw 'added is required but was not set'); + __result['removed'] = removed?.map((item) => item.toJson())?.toList() ?? + (throw 'removed is required but was not set'); return __result; } @@ -34437,7 +34464,7 @@ class WorkspaceSymbolClientCapabilitiesSymbolKind implements ToJsonable { Map toJson() { var __result = {}; if (valueSet != null) { - __result['valueSet'] = valueSet; + __result['valueSet'] = valueSet.map((item) => item.toJson()).toList(); } return __result; } @@ -34510,8 +34537,8 @@ class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable { Map toJson() { var __result = {}; - __result['valueSet'] = - valueSet ?? (throw 'valueSet is required but was not set'); + __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ?? + (throw 'valueSet is required but was not set'); return __result; } diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart index 915c417bdaa..4e32945a5ef 100644 --- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart +++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart @@ -80,6 +80,19 @@ void main() { expect(output, equals(expected)); }); + test('toJson() converts lists of enums to their underlying values', () { + final kind = CompletionClientCapabilitiesCompletionItemKind( + valueSet: [CompletionItemKind.Color], + ); + final json = kind.toJson(); + expect( + json['valueSet'], + // The list should contain the toJson (string/int) representation of + // the color, and not the CompletionItemKind itself. + equals([CompletionItemKind.Color.toJson()]), + ); + }); + test('serialises enums to their underlying values', () { final foldingRange = FoldingRange( startLine: 1, diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart index 3c8a5a2a6b7..1e17989c0f6 100644 --- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart +++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart @@ -668,9 +668,8 @@ void _writeJsonMapAssignment( } // Suppress the ? operator if we've output a null check already. final nullOp = shouldBeOmittedIfNoValue ? '' : '?'; - final valueCode = - _isSpecType(field.type) ? '${field.name}$nullOp.toJson()' : field.name; - buffer.writeIndented('''$mapName['${field.name}'] = $valueCode'''); + buffer.writeIndented('''$mapName['${field.name}'] = '''); + _writeToJsonCode(buffer, field.type, field.name, nullOp); if (!field.allowsUndefined && !field.allowsNull) { buffer.write(''' ?? (throw '${field.name} is required but was not set')'''); } @@ -696,6 +695,19 @@ void _writeMembers(IndentableStringBuffer buffer, List members) { _getSortedUnique(members).forEach((m) => _writeMember(buffer, m)); } +void _writeToJsonCode(IndentableStringBuffer buffer, TypeBase type, + String valueCode, String nullOp) { + if (_isSpecType(type)) { + buffer.write('$valueCode$nullOp.toJson()'); + } else if (type is ArrayType && _isSpecType(type.elementType)) { + buffer.write('$valueCode$nullOp.map((item) => '); + _writeToJsonCode(buffer, type.elementType, 'item', ''); + buffer.write(')$nullOp.toList()'); + } else { + buffer.write(valueCode); + } +} + void _writeToJsonFieldsForResponseMessage( IndentableStringBuffer buffer, Interface interface) { const mapName = '__result';