diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart index 3f2fada1000..82197fa8562 100644 --- a/pkg/analysis_server/lib/protocol/protocol_generated.dart +++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart @@ -10,6 +10,8 @@ import 'dart:convert' hide JsonDecoder; import 'package:analysis_server/protocol/protocol.dart'; import 'package:analysis_server/src/protocol/protocol_internal.dart'; +import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' + show clientUriConverter; import 'package:analyzer_plugin/protocol/protocol_common.dart'; /// analysis.analyzedFiles params @@ -31,8 +33,11 @@ class AnalysisAnalyzedFilesParams implements HasToJson { if (json is Map) { List directories; if (json.containsKey('directories')) { - directories = jsonDecoder.decodeList('$jsonPath.directories', - json['directories'], jsonDecoder.decodeString); + directories = jsonDecoder.decodeList( + '$jsonPath.directories', + json['directories'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'directories'); } @@ -52,7 +57,9 @@ class AnalysisAnalyzedFilesParams implements HasToJson { @override Map toJson() { var result = {}; - result['directories'] = directories; + result['directories'] = directories + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -105,7 +112,8 @@ class AnalysisClosingLabelsParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -135,7 +143,7 @@ class AnalysisClosingLabelsParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['labels'] = labels.map((ClosingLabel value) => value.toJson()).toList(); return result; @@ -262,7 +270,8 @@ class AnalysisErrorsParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -290,7 +299,7 @@ class AnalysisErrorsParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['errors'] = errors.map((AnalysisError value) => value.toJson()).toList(); return result; @@ -340,7 +349,10 @@ class AnalysisFlushResultsParams implements HasToJson { List files; if (json.containsKey('files')) { files = jsonDecoder.decodeList( - '$jsonPath.files', json['files'], jsonDecoder.decodeString); + '$jsonPath.files', + json['files'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'files'); } @@ -360,7 +372,9 @@ class AnalysisFlushResultsParams implements HasToJson { @override Map toJson() { var result = {}; - result['files'] = files; + result['files'] = files + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -406,7 +420,8 @@ class AnalysisFoldingParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -434,7 +449,7 @@ class AnalysisFoldingParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['regions'] = regions.map((FoldingRegion value) => value.toJson()).toList(); return result; @@ -483,7 +498,8 @@ class AnalysisGetErrorsParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -501,7 +517,7 @@ class AnalysisGetErrorsParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); return result; } @@ -617,7 +633,8 @@ class AnalysisGetHoverParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -641,7 +658,7 @@ class AnalysisGetHoverParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -769,7 +786,8 @@ class AnalysisGetImportedElementsParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -800,7 +818,7 @@ class AnalysisGetImportedElementsParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; return result; @@ -949,7 +967,10 @@ class AnalysisGetLibraryDependenciesResult implements ResponseResult { List libraries; if (json.containsKey('libraries')) { libraries = jsonDecoder.decodeList( - '$jsonPath.libraries', json['libraries'], jsonDecoder.decodeString); + '$jsonPath.libraries', + json['libraries'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'libraries'); } @@ -959,8 +980,14 @@ class AnalysisGetLibraryDependenciesResult implements ResponseResult { '$jsonPath.packageMap', json['packageMap'], valueDecoder: (String jsonPath, Object? json) => jsonDecoder.decodeMap(jsonPath, json, - valueDecoder: (String jsonPath, Object? json) => jsonDecoder - .decodeList(jsonPath, json, jsonDecoder.decodeString))); + valueDecoder: (String jsonPath, Object? json) => + jsonDecoder.decodeList( + jsonPath, + json, + (String jsonPath, Object? json) => + clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString( + jsonPath, json))))); } else { throw jsonDecoder.mismatch(jsonPath, 'packageMap'); } @@ -981,8 +1008,15 @@ class AnalysisGetLibraryDependenciesResult implements ResponseResult { @override Map toJson() { var result = {}; - result['libraries'] = libraries; - result['packageMap'] = packageMap; + result['libraries'] = libraries + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); + result['packageMap'] = mapMap(packageMap, + valueCallback: (Map> value) => mapMap(value, + valueCallback: (List value) => value + .map((String value) => + clientUriConverter.toClientFilePath(value)) + .toList())); return result; } @@ -1048,7 +1082,8 @@ class AnalysisGetNavigationParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1079,7 +1114,7 @@ class AnalysisGetNavigationParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; return result; @@ -1141,7 +1176,10 @@ class AnalysisGetNavigationResult implements ResponseResult { List files; if (json.containsKey('files')) { files = jsonDecoder.decodeList( - '$jsonPath.files', json['files'], jsonDecoder.decodeString); + '$jsonPath.files', + json['files'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'files'); } @@ -1182,7 +1220,9 @@ class AnalysisGetNavigationResult implements ResponseResult { @override Map toJson() { var result = {}; - result['files'] = files; + result['files'] = files + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); result['targets'] = targets.map((NavigationTarget value) => value.toJson()).toList(); result['regions'] = @@ -1237,7 +1277,8 @@ class AnalysisGetReachableSourcesParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1256,7 +1297,7 @@ class AnalysisGetReachableSourcesParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); return result; } @@ -1379,7 +1420,8 @@ class AnalysisGetSignatureParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1404,7 +1446,7 @@ class AnalysisGetSignatureParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -1564,7 +1606,8 @@ class AnalysisHighlightsParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1592,7 +1635,7 @@ class AnalysisHighlightsParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['regions'] = regions.map((HighlightRegion value) => value.toJson()).toList(); return result; @@ -1649,7 +1692,8 @@ class AnalysisImplementedParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1688,7 +1732,7 @@ class AnalysisImplementedParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['classes'] = classes.map((ImplementedClass value) => value.toJson()).toList(); result['members'] = @@ -1756,7 +1800,8 @@ class AnalysisInvalidateParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1792,7 +1837,7 @@ class AnalysisInvalidateParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; result['delta'] = delta; @@ -1865,7 +1910,8 @@ class AnalysisNavigationParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -1892,7 +1938,10 @@ class AnalysisNavigationParams implements HasToJson { List files; if (json.containsKey('files')) { files = jsonDecoder.decodeList( - '$jsonPath.files', json['files'], jsonDecoder.decodeString); + '$jsonPath.files', + json['files'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'files'); } @@ -1910,12 +1959,14 @@ class AnalysisNavigationParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['regions'] = regions.map((NavigationRegion value) => value.toJson()).toList(); result['targets'] = targets.map((NavigationTarget value) => value.toJson()).toList(); - result['files'] = files; + result['files'] = files + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -1971,7 +2022,8 @@ class AnalysisOccurrencesParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -2000,7 +2052,7 @@ class AnalysisOccurrencesParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['occurrences'] = occurrences.map((Occurrences value) => value.toJson()).toList(); return result; @@ -2239,7 +2291,8 @@ class AnalysisOutlineParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -2276,7 +2329,7 @@ class AnalysisOutlineParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['kind'] = kind.toJson(); var libraryName = this.libraryName; if (libraryName != null) { @@ -2336,7 +2389,8 @@ class AnalysisOverridesParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -2364,7 +2418,7 @@ class AnalysisOverridesParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['overrides'] = overrides.map((Override value) => value.toJson()).toList(); return result; @@ -2570,14 +2624,20 @@ class AnalysisSetAnalysisRootsParams implements RequestParams { List included; if (json.containsKey('included')) { included = jsonDecoder.decodeList( - '$jsonPath.included', json['included'], jsonDecoder.decodeString); + '$jsonPath.included', + json['included'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'included'); } List excluded; if (json.containsKey('excluded')) { excluded = jsonDecoder.decodeList( - '$jsonPath.excluded', json['excluded'], jsonDecoder.decodeString); + '$jsonPath.excluded', + json['excluded'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'excluded'); } @@ -2585,7 +2645,10 @@ class AnalysisSetAnalysisRootsParams implements RequestParams { if (json.containsKey('packageRoots')) { packageRoots = jsonDecoder.decodeMap( '$jsonPath.packageRoots', json['packageRoots'], - valueDecoder: jsonDecoder.decodeString); + keyDecoder: (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json)), + valueDecoder: (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } return AnalysisSetAnalysisRootsParams(included, excluded, packageRoots: packageRoots); @@ -2603,11 +2666,19 @@ class AnalysisSetAnalysisRootsParams implements RequestParams { @override Map toJson() { var result = {}; - result['included'] = included; - result['excluded'] = excluded; + result['included'] = included + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); + result['excluded'] = excluded + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); var packageRoots = this.packageRoots; if (packageRoots != null) { - result['packageRoots'] = packageRoots; + result['packageRoots'] = mapMap(packageRoots, + keyCallback: (String value) => + clientUriConverter.toClientFilePath(value), + valueCallback: (String value) => + clientUriConverter.toClientFilePath(value)); } return result; } @@ -2767,7 +2838,10 @@ class AnalysisSetPriorityFilesParams implements RequestParams { List files; if (json.containsKey('files')) { files = jsonDecoder.decodeList( - '$jsonPath.files', json['files'], jsonDecoder.decodeString); + '$jsonPath.files', + json['files'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'files'); } @@ -2786,7 +2860,9 @@ class AnalysisSetPriorityFilesParams implements RequestParams { @override Map toJson() { var result = {}; - result['files'] = files; + result['files'] = files + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -2853,8 +2929,13 @@ class AnalysisSetSubscriptionsParams implements RequestParams { '$jsonPath.subscriptions', json['subscriptions'], keyDecoder: (String jsonPath, Object? json) => AnalysisService.fromJson(jsonDecoder, jsonPath, json), - valueDecoder: (String jsonPath, Object? json) => jsonDecoder - .decodeList(jsonPath, json, jsonDecoder.decodeString)); + valueDecoder: (String jsonPath, Object? json) => + jsonDecoder.decodeList( + jsonPath, + json, + (String jsonPath, Object? json) => + clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString(jsonPath, json)))); } else { throw jsonDecoder.mismatch(jsonPath, 'subscriptions'); } @@ -2874,7 +2955,10 @@ class AnalysisSetSubscriptionsParams implements RequestParams { Map toJson() { var result = {}; result['subscriptions'] = mapMap(subscriptions, - keyCallback: (AnalysisService value) => value.toJson()); + keyCallback: (AnalysisService value) => value.toJson(), + valueCallback: (List value) => value + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList()); return result; } @@ -3013,6 +3097,8 @@ class AnalysisUpdateContentParams implements RequestParams { Map files; if (json.containsKey('files')) { files = jsonDecoder.decodeMap('$jsonPath.files', json['files'], + keyDecoder: (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json)), valueDecoder: (String jsonPath, Object? json) => jsonDecoder.decodeUnion(jsonPath, json, 'type', { 'add': (String jsonPath, Object? json) => @@ -3042,6 +3128,8 @@ class AnalysisUpdateContentParams implements RequestParams { Map toJson() { var result = {}; result['files'] = mapMap(files, + keyCallback: (String value) => + clientUriConverter.toClientFilePath(value), valueCallback: (Object value) => (value as dynamic).toJson()); return result; } @@ -3560,7 +3648,8 @@ class BulkFix implements HasToJson { if (json is Map) { String path; if (json.containsKey('path')) { - path = jsonDecoder.decodeString('$jsonPath.path', json['path']); + path = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.path', json['path'])); } else { throw jsonDecoder.mismatch(jsonPath, 'path'); } @@ -3583,7 +3672,7 @@ class BulkFix implements HasToJson { @override Map toJson() { var result = {}; - result['path'] = path; + result['path'] = clientUriConverter.toClientFilePath(path); result['fixes'] = fixes.map((BulkFixDetail value) => value.toJson()).toList(); return result; @@ -3841,7 +3930,8 @@ class CompletionExistingImportsParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -3868,7 +3958,7 @@ class CompletionExistingImportsParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['imports'] = imports.toJson(); return result; } @@ -3931,7 +4021,8 @@ class CompletionGetSuggestionDetails2Params implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -3971,7 +4062,7 @@ class CompletionGetSuggestionDetails2Params implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['completion'] = completion; result['libraryUri'] = libraryUri; @@ -4144,7 +4235,8 @@ class CompletionGetSuggestions2Params implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -4201,7 +4293,7 @@ class CompletionGetSuggestions2Params implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['maxResults'] = maxResults; var completionCaseMatchingMode = this.completionCaseMatchingMode; @@ -4918,7 +5010,10 @@ class EditBulkFixesParams implements RequestParams { List included; if (json.containsKey('included')) { included = jsonDecoder.decodeList( - '$jsonPath.included', json['included'], jsonDecoder.decodeString); + '$jsonPath.included', + json['included'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'included'); } @@ -4952,7 +5047,9 @@ class EditBulkFixesParams implements RequestParams { @override Map toJson() { var result = {}; - result['included'] = included; + result['included'] = included + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); var inTestMode = this.inTestMode; if (inTestMode != null) { result['inTestMode'] = inTestMode; @@ -5118,8 +5215,11 @@ class EditFormatIfEnabledParams implements RequestParams { if (json is Map) { List directories; if (json.containsKey('directories')) { - directories = jsonDecoder.decodeList('$jsonPath.directories', - json['directories'], jsonDecoder.decodeString); + directories = jsonDecoder.decodeList( + '$jsonPath.directories', + json['directories'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'directories'); } @@ -5137,7 +5237,9 @@ class EditFormatIfEnabledParams implements RequestParams { @override Map toJson() { var result = {}; - result['directories'] = directories; + result['directories'] = directories + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -5265,7 +5367,8 @@ class EditFormatParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -5303,7 +5406,7 @@ class EditFormatParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['selectionOffset'] = selectionOffset; result['selectionLength'] = selectionLength; var lineLength = this.lineLength; @@ -5467,7 +5570,8 @@ class EditGetAssistsParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -5497,7 +5601,7 @@ class EditGetAssistsParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; return result; @@ -5625,7 +5729,8 @@ class EditGetAvailableRefactoringsParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -5656,7 +5761,7 @@ class EditGetAvailableRefactoringsParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; return result; @@ -5781,7 +5886,8 @@ class EditGetFixesParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -5805,7 +5911,7 @@ class EditGetFixesParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -5930,7 +6036,8 @@ class EditGetPostfixCompletionParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -5961,7 +6068,7 @@ class EditGetPostfixCompletionParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['key'] = key; result['offset'] = offset; return result; @@ -6109,7 +6216,8 @@ class EditGetRefactoringParams implements RequestParams { } String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -6155,7 +6263,7 @@ class EditGetRefactoringParams implements RequestParams { Map toJson() { var result = {}; result['kind'] = kind.toJson(); - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; result['validateOnly'] = validateOnly; @@ -6401,7 +6509,8 @@ class EditGetStatementCompletionParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -6426,7 +6535,7 @@ class EditGetStatementCompletionParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -6565,7 +6674,8 @@ class EditImportElementsParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -6597,7 +6707,7 @@ class EditImportElementsParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['elements'] = elements.map((ImportedElements value) => value.toJson()).toList(); var offset = this.offset; @@ -6732,7 +6842,8 @@ class EditIsPostfixCompletionApplicableParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -6763,7 +6874,7 @@ class EditIsPostfixCompletionApplicableParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['key'] = key; result['offset'] = offset; return result; @@ -6969,7 +7080,8 @@ class EditOrganizeDirectivesParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -6988,7 +7100,7 @@ class EditOrganizeDirectivesParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); return result; } @@ -7097,7 +7209,8 @@ class EditSortMembersParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -7115,7 +7228,7 @@ class EditSortMembersParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); return result; } @@ -7431,7 +7544,8 @@ class ExecutableFile implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -7451,7 +7565,7 @@ class ExecutableFile implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['kind'] = kind.toJson(); return result; } @@ -7559,8 +7673,8 @@ class ExecutionCreateContextParams implements RequestParams { if (json is Map) { String contextRoot; if (json.containsKey('contextRoot')) { - contextRoot = jsonDecoder.decodeString( - '$jsonPath.contextRoot', json['contextRoot']); + contextRoot = clientUriConverter.fromClientFilePath(jsonDecoder + .decodeString('$jsonPath.contextRoot', json['contextRoot'])); } else { throw jsonDecoder.mismatch(jsonPath, 'contextRoot'); } @@ -7579,7 +7693,7 @@ class ExecutionCreateContextParams implements RequestParams { @override Map toJson() { var result = {}; - result['contextRoot'] = contextRoot; + result['contextRoot'] = clientUriConverter.toClientFilePath(contextRoot); return result; } @@ -7814,8 +7928,8 @@ class ExecutionGetSuggestionsParams implements RequestParams { } String contextFile; if (json.containsKey('contextFile')) { - contextFile = jsonDecoder.decodeString( - '$jsonPath.contextFile', json['contextFile']); + contextFile = clientUriConverter.fromClientFilePath(jsonDecoder + .decodeString('$jsonPath.contextFile', json['contextFile'])); } else { throw jsonDecoder.mismatch(jsonPath, 'contextFile'); } @@ -7865,7 +7979,7 @@ class ExecutionGetSuggestionsParams implements RequestParams { var result = {}; result['code'] = code; result['offset'] = offset; - result['contextFile'] = contextFile; + result['contextFile'] = clientUriConverter.toClientFilePath(contextFile); result['contextOffset'] = contextOffset; result['variables'] = variables .map((RuntimeCompletionVariable value) => value.toJson()) @@ -8059,7 +8173,8 @@ class ExecutionLaunchDataParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -8070,8 +8185,11 @@ class ExecutionLaunchDataParams implements HasToJson { } List? referencedFiles; if (json.containsKey('referencedFiles')) { - referencedFiles = jsonDecoder.decodeList('$jsonPath.referencedFiles', - json['referencedFiles'], jsonDecoder.decodeString); + referencedFiles = jsonDecoder.decodeList( + '$jsonPath.referencedFiles', + json['referencedFiles'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } return ExecutionLaunchDataParams(file, kind: kind, referencedFiles: referencedFiles); @@ -8089,14 +8207,16 @@ class ExecutionLaunchDataParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); var kind = this.kind; if (kind != null) { result['kind'] = kind.toJson(); } var referencedFiles = this.referencedFiles; if (referencedFiles != null) { - result['referencedFiles'] = referencedFiles; + result['referencedFiles'] = referencedFiles + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); } return result; } @@ -8160,7 +8280,8 @@ class ExecutionMapUriParams implements RequestParams { } String? file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } String? uri; if (json.containsKey('uri')) { @@ -8183,7 +8304,7 @@ class ExecutionMapUriParams implements RequestParams { result['id'] = id; var file = this.file; if (file != null) { - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); } var uri = this.uri; if (uri != null) { @@ -8241,7 +8362,8 @@ class ExecutionMapUriResult implements ResponseResult { if (json is Map) { String? file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } String? uri; if (json.containsKey('uri')) { @@ -8265,7 +8387,7 @@ class ExecutionMapUriResult implements ResponseResult { var result = {}; var file = this.file; if (file != null) { - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); } var uri = this.uri; if (uri != null) { @@ -9250,7 +9372,8 @@ class FlutterGetWidgetDescriptionParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -9275,7 +9398,7 @@ class FlutterGetWidgetDescriptionParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -9899,7 +10022,8 @@ class FlutterOutlineParams implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -9924,7 +10048,7 @@ class FlutterOutlineParams implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['outline'] = outline.toJson(); return result; } @@ -10019,8 +10143,13 @@ class FlutterSetSubscriptionsParams implements RequestParams { '$jsonPath.subscriptions', json['subscriptions'], keyDecoder: (String jsonPath, Object? json) => FlutterService.fromJson(jsonDecoder, jsonPath, json), - valueDecoder: (String jsonPath, Object? json) => jsonDecoder - .decodeList(jsonPath, json, jsonDecoder.decodeString)); + valueDecoder: (String jsonPath, Object? json) => + jsonDecoder.decodeList( + jsonPath, + json, + (String jsonPath, Object? json) => + clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString(jsonPath, json)))); } else { throw jsonDecoder.mismatch(jsonPath, 'subscriptions'); } @@ -10040,7 +10169,10 @@ class FlutterSetSubscriptionsParams implements RequestParams { Map toJson() { var result = {}; result['subscriptions'] = mapMap(subscriptions, - keyCallback: (FlutterService value) => value.toJson()); + keyCallback: (FlutterService value) => value.toJson(), + valueCallback: (List value) => value + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList()); return result; } @@ -11401,7 +11533,8 @@ class ImportedElements implements HasToJson { if (json is Map) { String path; if (json.containsKey('path')) { - path = jsonDecoder.decodeString('$jsonPath.path', json['path']); + path = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.path', json['path'])); } else { throw jsonDecoder.mismatch(jsonPath, 'path'); } @@ -11427,7 +11560,7 @@ class ImportedElements implements HasToJson { @override Map toJson() { var result = {}; - result['path'] = path; + result['path'] = clientUriConverter.toClientFilePath(path); result['prefix'] = prefix; result['elements'] = elements; return result; @@ -11720,14 +11853,18 @@ class LibraryPathSet implements HasToJson { if (json is Map) { String scope; if (json.containsKey('scope')) { - scope = jsonDecoder.decodeString('$jsonPath.scope', json['scope']); + scope = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.scope', json['scope'])); } else { throw jsonDecoder.mismatch(jsonPath, 'scope'); } List libraryPaths; if (json.containsKey('libraryPaths')) { - libraryPaths = jsonDecoder.decodeList('$jsonPath.libraryPaths', - json['libraryPaths'], jsonDecoder.decodeString); + libraryPaths = jsonDecoder.decodeList( + '$jsonPath.libraryPaths', + json['libraryPaths'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'libraryPaths'); } @@ -11740,8 +11877,10 @@ class LibraryPathSet implements HasToJson { @override Map toJson() { var result = {}; - result['scope'] = scope; - result['libraryPaths'] = libraryPaths; + result['scope'] = clientUriConverter.toClientFilePath(scope); + result['libraryPaths'] = libraryPaths + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -12039,8 +12178,8 @@ class MoveFileOptions extends RefactoringOptions { if (json is Map) { String newFile; if (json.containsKey('newFile')) { - newFile = - jsonDecoder.decodeString('$jsonPath.newFile', json['newFile']); + newFile = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.newFile', json['newFile'])); } else { throw jsonDecoder.mismatch(jsonPath, 'newFile'); } @@ -12059,7 +12198,7 @@ class MoveFileOptions extends RefactoringOptions { @override Map toJson() { var result = {}; - result['newFile'] = newFile; + result['newFile'] = clientUriConverter.toClientFilePath(newFile); return result; } @@ -13176,8 +13315,8 @@ class RuntimeCompletionExpressionType implements HasToJson { if (json is Map) { String? libraryPath; if (json.containsKey('libraryPath')) { - libraryPath = jsonDecoder.decodeString( - '$jsonPath.libraryPath', json['libraryPath']); + libraryPath = clientUriConverter.fromClientFilePath(jsonDecoder + .decodeString('$jsonPath.libraryPath', json['libraryPath'])); } RuntimeCompletionExpressionTypeKind kind; if (json.containsKey('kind')) { @@ -13236,7 +13375,7 @@ class RuntimeCompletionExpressionType implements HasToJson { var result = {}; var libraryPath = this.libraryPath; if (libraryPath != null) { - result['libraryPath'] = libraryPath; + result['libraryPath'] = clientUriConverter.toClientFilePath(libraryPath); } result['kind'] = kind.toJson(); var name = this.name; @@ -13463,7 +13602,8 @@ class SearchFindElementReferencesParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -13495,7 +13635,7 @@ class SearchFindElementReferencesParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['includePotential'] = includePotential; return result; @@ -14025,7 +14165,8 @@ class SearchGetElementDeclarationsParams implements RequestParams { if (json is Map) { String? file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } String? pattern; if (json.containsKey('pattern')) { @@ -14055,7 +14196,7 @@ class SearchGetElementDeclarationsParams implements RequestParams { var result = {}; var file = this.file; if (file != null) { - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); } var pattern = this.pattern; if (pattern != null) { @@ -14128,7 +14269,10 @@ class SearchGetElementDeclarationsResult implements ResponseResult { List files; if (json.containsKey('files')) { files = jsonDecoder.decodeList( - '$jsonPath.files', json['files'], jsonDecoder.decodeString); + '$jsonPath.files', + json['files'], + (String jsonPath, Object? json) => clientUriConverter + .fromClientFilePath(jsonDecoder.decodeString(jsonPath, json))); } else { throw jsonDecoder.mismatch(jsonPath, 'files'); } @@ -14151,7 +14295,9 @@ class SearchGetElementDeclarationsResult implements ResponseResult { var result = {}; result['declarations'] = declarations.map((ElementDeclaration value) => value.toJson()).toList(); - result['files'] = files; + result['files'] = files + .map((String value) => clientUriConverter.toClientFilePath(value)) + .toList(); return result; } @@ -14209,7 +14355,8 @@ class SearchGetTypeHierarchyParams implements RequestParams { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -14239,7 +14386,7 @@ class SearchGetTypeHierarchyParams implements RequestParams { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; var superOnly = this.superOnly; if (superOnly != null) { diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart index fc7fc0ba8c5..df80ceca931 100644 --- a/pkg/analysis_server/lib/src/analysis_server.dart +++ b/pkg/analysis_server/lib/src/analysis_server.dart @@ -38,7 +38,6 @@ import 'package:analysis_server/src/services/search/search_engine_internal.dart' import 'package:analysis_server/src/services/user_prompts/dart_fix_prompt_manager.dart'; import 'package:analysis_server/src/services/user_prompts/survey_manager.dart'; import 'package:analysis_server/src/services/user_prompts/user_prompts.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analysis_server/src/utilities/file_string_sink.dart'; import 'package:analysis_server/src/utilities/null_string_sink.dart'; import 'package:analysis_server/src/utilities/process.dart'; @@ -76,6 +75,7 @@ import 'package:analyzer/src/util/performance/operation_performance.dart'; import 'package:analyzer/src/utilities/extensions/analysis_session.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/src/protocol/protocol_internal.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:collection/collection.dart'; import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart index 8ba3931d5e8..93807171997 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart @@ -12,13 +12,13 @@ import 'package:analysis_server/src/lsp/handlers/handler_reject.dart'; import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; import 'package:analysis_server/src/lsp/progress.dart'; import 'package:analysis_server/src/request_handler_mixin.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/source/line_info.dart'; import 'package:analyzer/src/util/performance/operation_performance.dart'; import 'package:analyzer/src/utilities/cancellation.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/src/protocol/protocol_internal.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:language_server_protocol/json_parsing.dart'; import 'package:path/path.dart' as path; diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart index fb9fe14cabb..15d673baab9 100644 --- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart +++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart @@ -29,7 +29,6 @@ import 'package:analysis_server/src/server/diagnostic_server.dart'; import 'package:analysis_server/src/server/error_notifier.dart'; import 'package:analysis_server/src/server/performance.dart'; import 'package:analysis_server/src/services/user_prompts/dart_fix_prompt_manager.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analysis_server/src/utilities/flutter.dart'; import 'package:analysis_server/src/utilities/process.dart'; import 'package:analyzer/dart/analysis/context_locator.dart'; @@ -46,6 +45,7 @@ import 'package:analyzer/src/util/performance/operation_performance.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin; import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:collection/collection.dart'; import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart index 8d5ae9d60fc..d903aadde5d 100644 --- a/pkg/analysis_server/lib/src/lsp/mapping.dart +++ b/pkg/analysis_server/lib/src/lsp/mapping.dart @@ -18,7 +18,6 @@ import 'package:analysis_server/src/protocol_server.dart' as server hide AnalysisError; import 'package:analysis_server/src/services/completion/dart/feature_computer.dart'; import 'package:analysis_server/src/services/snippets/snippet.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analysis_server/src/utilities/extensions/string.dart'; import 'package:analyzer/dart/analysis/results.dart' as server; import 'package:analyzer/error/error.dart' as server; @@ -30,6 +29,7 @@ import 'package:analyzer/src/dart/analysis/search.dart' as server import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/utilities/extensions/collection.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:collection/collection.dart'; const languageSourceName = 'dart'; diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart index 51407e67854..3bd06e35a3a 100644 --- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart +++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart @@ -316,7 +316,13 @@ class ServerCapabilitiesComputer { clientCapabilities: _server.lspClientCapabilities!, clientConfiguration: _server.lspClientConfiguration, customDartSchemes: _server.uriConverter.supportedNonFileSchemes, - dartFilters: _server.uriConverter.filters, + dartFilters: [ + for (var scheme in { + 'file', + ..._server.uriConverter.supportedNonFileSchemes + }) + TextDocumentFilterWithScheme(language: 'dart', scheme: scheme) + ], pluginTypes: pluginTypes, ); } diff --git a/pkg/analysis_server/test/lsp/dart_text_document_content_provider_test.dart b/pkg/analysis_server/test/lsp/dart_text_document_content_provider_test.dart index d42dbbf73ea..0d9f87b1cb5 100644 --- a/pkg/analysis_server/test/lsp/dart_text_document_content_provider_test.dart +++ b/pkg/analysis_server/test/lsp/dart_text_document_content_provider_test.dart @@ -4,8 +4,8 @@ import 'package:analysis_server/src/legacy_analysis_server.dart'; import 'package:analysis_server/src/lsp/test_macros.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analyzer/src/dart/analysis/experiments.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:language_server_protocol/protocol_generated.dart'; import 'package:test/expect.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; diff --git a/pkg/analysis_server/test/lsp/request_helpers_mixin.dart b/pkg/analysis_server/test/lsp/request_helpers_mixin.dart index e5a057db206..8827de670ce 100644 --- a/pkg/analysis_server/test/lsp/request_helpers_mixin.dart +++ b/pkg/analysis_server/test/lsp/request_helpers_mixin.dart @@ -8,8 +8,8 @@ import 'package:analysis_server/lsp_protocol/protocol.dart'; import 'package:analysis_server/src/lsp/constants.dart'; import 'package:analysis_server/src/lsp/mapping.dart'; import 'package:analysis_server/src/services/completion/dart/feature_computer.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analyzer/source/line_info.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:collection/collection.dart'; import 'package:language_server_protocol/json_parsing.dart'; import 'package:path/path.dart' as path; diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart index 42b0c2899a3..e4020ff8f7b 100644 --- a/pkg/analysis_server/test/lsp/server_abstract.dart +++ b/pkg/analysis_server/test/lsp/server_abstract.dart @@ -13,7 +13,6 @@ import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; import 'package:analysis_server/src/plugin/plugin_manager.dart'; import 'package:analysis_server/src/server/crash_reporting_attachments.dart'; import 'package:analysis_server/src/services/user_prompts/dart_fix_prompt_manager.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; import 'package:analysis_server/src/utilities/mocks.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; import 'package:analyzer/src/generated/sdk.dart'; @@ -23,6 +22,7 @@ import 'package:analyzer/src/test_utilities/test_code_format.dart'; import 'package:analyzer/src/util/file_paths.dart' as file_paths; import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:collection/collection.dart'; import 'package:language_server_protocol/json_parsing.dart'; import 'package:path/path.dart' as path; diff --git a/pkg/analysis_server/test/lsp_over_legacy/abstract_lsp_over_legacy.dart b/pkg/analysis_server/test/lsp_over_legacy/abstract_lsp_over_legacy.dart index d583abe3a8e..fccc0764b14 100644 --- a/pkg/analysis_server/test/lsp_over_legacy/abstract_lsp_over_legacy.dart +++ b/pkg/analysis_server/test/lsp_over_legacy/abstract_lsp_over_legacy.dart @@ -7,7 +7,7 @@ import 'dart:convert'; import 'package:analysis_server/lsp_protocol/protocol.dart'; import 'package:analysis_server/src/protocol/protocol_internal.dart'; import 'package:analysis_server/src/protocol_server.dart'; -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; diff --git a/pkg/analysis_server/test/src/computer/color_computer_test.dart b/pkg/analysis_server/test/src/computer/color_computer_test.dart index dc2436280cf..4a91634178d 100644 --- a/pkg/analysis_server/test/src/computer/color_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/color_computer_test.dart @@ -8,7 +8,6 @@ import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../../tool/codebase/failing_tests.dart'; import '../../abstract_context.dart'; void main() { diff --git a/pkg/analysis_server/test/src/utilities/json_test.dart b/pkg/analysis_server/test/src/utilities/json_test.dart new file mode 100644 index 00000000000..492f4281c46 --- /dev/null +++ b/pkg/analysis_server/test/src/utilities/json_test.dart @@ -0,0 +1,230 @@ +// Copyright (c) 2024, 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. + +import 'package:analysis_server/src/protocol/protocol_internal.dart'; +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' + show clientUriConverter; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +void main() { + defineReflectiveSuite(() { + defineReflectiveTests(JsonTest); + defineReflectiveTests(JsonWithConvertedFilePathsTest); + }); +} + +@reflectiveTest +class JsonTest { + final decoder = ResponseDecoder(null); + + void test_fromJson() { + var json = { + 'offset': 0, + 'length': 1, + 'label': 'x', + }; + var label = ClosingLabel.fromJson(decoder, '', json); + expect(label.label, 'x'); + expect(label.offset, 0); + expect(label.length, 1); + } + + void test_toJson() { + var closingLabel = ClosingLabel(0, 1, 'x'); + var json = closingLabel.toJson(); + + expect(json, { + 'offset': 0, + 'length': 1, + 'label': 'x', + }); + } +} + +@reflectiveTest +class JsonWithConvertedFilePathsTest with ResourceProviderMixin { + final decoder = ResponseDecoder(null); + + void setUp() { + // These tests use a dummy encoder that just prefixes the FilePaths with + // "Encoded" and "Decoded" to simplify testing. The real implementation will + // convert between file paths and URI strings. + clientUriConverter = _PrefixingUriConverter(); + } + + void tearDown() { + // Because this is currently global, restore after the tests. + clientUriConverter = ClientUriConverter.noop(pathContext); + } + + void test_fromJson_filePath_list() { + var json = { + 'files': ['/my/file/1', '/my/file/2'] + }; + var params = AnalysisFlushResultsParams.fromJson(decoder, '', json); + expect(params.files, ['Decoded /my/file/1', 'Decoded /my/file/2']); + } + + void test_fromJson_filePath_map_keyValue() { + var json = { + 'included': [], + 'excluded': [], + 'packageRoots': { + '/my/file/key': '/my/file/value', + } + }; + var params = AnalysisSetAnalysisRootsParams.fromJson(decoder, '', json); + expect(params.packageRoots, { + 'Decoded /my/file/key': 'Decoded /my/file/value', + }); + } + + void test_fromJson_filePath_map_value_list() { + var json = { + 'subscriptions': { + 'CLOSING_LABELS': ['/my/file/value'] + } + }; + var params = AnalysisSetSubscriptionsParams.fromJson(decoder, '', json); + expect(params.subscriptions, { + AnalysisService.CLOSING_LABELS: ['Decoded /my/file/value'], + }); + } + + void test_fromJson_filePath_nested() { + var json = { + 'fixes': [ + { + 'error': { + 'severity': 'INFO', + 'type': 'LINT', + 'location': { + 'file': '/my/file', + 'offset': 0, + 'length': 1, + 'startLine': 2, + 'startColumn': 3 + }, + 'message': 'x', + 'code': 'y' + }, + 'fixes': [] + } + ] + }; + var result = EditGetFixesResult.fromJson(decoder, '', json); + expect(result.fixes.single.error.location.file, 'Decoded /my/file'); + } + + void test_fromJson_filePath_topLevel() { + var json = {'file': '/my/file', 'labels': []}; + var params = AnalysisClosingLabelsParams.fromJson(decoder, '', json); + expect(params.file, 'Decoded /my/file'); + } + + void test_toJson_list() { + var params = AnalysisFlushResultsParams(['/my/file/1', '/my/file/2']); + var json = params.toJson(); + + expect( + json, + { + 'files': ['Encoded /my/file/1', 'Encoded /my/file/2'] + }, + ); + } + + void test_toJson_map_keyValue() { + var params = AnalysisSetAnalysisRootsParams( + [], + [], + packageRoots: { + '/my/file/key': '/my/file/value', + }, + ); + var json = params.toJson(); + expect(json, { + 'included': [], + 'excluded': [], + 'packageRoots': { + 'Encoded /my/file/key': 'Encoded /my/file/value', + } + }); + } + + void test_toJson_map_value_list() { + var params = AnalysisSetSubscriptionsParams( + { + AnalysisService.CLOSING_LABELS: ['/my/file/value'], + }, + ); + var json = params.toJson(); + expect(json, { + 'subscriptions': { + 'CLOSING_LABELS': ['Encoded /my/file/value'] + } + }); + } + + void test_toJson_nested() { + var result = EditGetFixesResult([ + AnalysisErrorFixes( + AnalysisError( + AnalysisErrorSeverity.INFO, + AnalysisErrorType.LINT, + Location('/my/file', 0, 1, 2, 3), + 'x', + 'y', + ), + ) + ]); + var json = result.toJson(); + expect(json, { + 'fixes': [ + { + 'error': { + 'severity': 'INFO', + 'type': 'LINT', + 'location': { + 'file': 'Encoded /my/file', + 'offset': 0, + 'length': 1, + 'startLine': 2, + 'startColumn': 3 + }, + 'message': 'x', + 'code': 'y' + }, + 'fixes': [] + } + ] + }); + } + + void test_toJson_topLevel() { + var closingLabelParams = AnalysisClosingLabelsParams('/my/file', []); + var json = closingLabelParams.toJson(); + + expect( + json, + {'file': 'Encoded /my/file', 'labels': []}, + ); + } +} + +/// A [ClientUriConverter] that just prefixes the input string for testing. +class _PrefixingUriConverter implements ClientUriConverter { + @override + String fromClientFilePath(String filePathOrUri) => 'Decoded $filePathOrUri'; + + @override + dynamic noSuchMethod(Invocation invocation) => throw UnimplementedError(); + + @override + String toClientFilePath(String filePath) => 'Encoded $filePath'; +} diff --git a/pkg/analysis_server/test/src/utilities/test_all.dart b/pkg/analysis_server/test/src/utilities/test_all.dart index 48acc60765a..e5063641e38 100644 --- a/pkg/analysis_server/test/src/utilities/test_all.dart +++ b/pkg/analysis_server/test/src/utilities/test_all.dart @@ -4,10 +4,10 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; -import 'client_uri_converter_test.dart' as client_uri_converter; import 'extensions/test_all.dart' as extensions; import 'flutter_test.dart' as flutter; import 'import_analyzer_test.dart' as import_analyzer; +import 'json_test.dart' as json; import 'profiling_test.dart' as profiling; import 'selection_coverage_test.dart' as selection_coverage; import 'selection_test.dart' as selection; @@ -16,9 +16,9 @@ import 'strings_test.dart' as strings; void main() { defineReflectiveSuite(() { - client_uri_converter.main(); extensions.main(); flutter.main(); + json.main(); import_analyzer.main(); profiling.main(); selection_coverage.main(); diff --git a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart index 81415aa852e..1212c8a0f02 100644 --- a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart +++ b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart @@ -25,21 +25,31 @@ const Map specialElementFlags = { 'deprecated': '0x20' }; -GeneratedFile clientTarget(bool responseRequiresRequestTime) { +GeneratedFile clientTarget( + bool responseRequiresRequestTime, bool requiresProtocolJsonMethods) { return GeneratedFile( '../analysis_server_client/lib/src/protocol/protocol_generated.dart', (String pkgPath) async { - var visitor = CodegenProtocolVisitor('analysis_server_client', - responseRequiresRequestTime, false, readApi(pkgPath)); + var visitor = CodegenProtocolVisitor( + 'analysis_server_client', + responseRequiresRequestTime, + requiresProtocolJsonMethods, + false, + readApi(pkgPath)); return visitor.collectCode(visitor.visitApi); }); } -GeneratedFile serverTarget(bool responseRequiresRequestTime) { +GeneratedFile serverTarget( + bool responseRequiresRequestTime, bool requiresProtocolJsonMethods) { return GeneratedFile('lib/protocol/protocol_generated.dart', (String pkgPath) async { - var visitor = CodegenProtocolVisitor(path.basename(pkgPath), - responseRequiresRequestTime, true, readApi(pkgPath)); + var visitor = CodegenProtocolVisitor( + path.basename(pkgPath), + responseRequiresRequestTime, + requiresProtocolJsonMethods, + true, + readApi(pkgPath)); return visitor.collectCode(visitor.visitApi); }); } @@ -75,6 +85,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { /// parameter. final bool responseRequiresRequestTime; + /// A flag indicating whether the classes should have `toProtocolJson` and + /// `fromProtocolJson` methods that can handle converting client URIs. + final bool requiresProtocolJsonMethods; + /// A flag indicating whether this generated code is for the server /// (analysis_server) or for the client (analysis_server_client). final bool isServer; @@ -88,7 +102,7 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { final Map impliedTypes; CodegenProtocolVisitor(this.packageName, this.responseRequiresRequestTime, - this.isServer, Api api) + this.requiresProtocolJsonMethods, this.isServer, Api api) : toHtmlVisitor = ToHtmlVisitor(api), impliedTypes = computeImpliedTypes(api), super(api) { @@ -383,6 +397,8 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { writeln("import 'package:$packageName/protocol/protocol.dart';"); writeln( "import 'package:$packageName/src/protocol/protocol_internal.dart';"); + writeln( + "import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' show clientUriConverter;"); for (var uri in api.types.importUris) { write("import '"); write(uri); @@ -943,6 +959,12 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { return '$typeName.fromJson(jsonDecoder, $jsonPath, $json)'; } }); + } else if (requiresProtocolJsonMethods && + referencedDefinition.name == 'FilePath') { + // TODO(dantup): Ensure if the client sends us filepaths instead of + // URIs that we generate good error responses. + return FromJsonSnippet((jsonPath, json) => + 'clientUriConverter.fromClientFilePath(jsonDecoder.decodeString($jsonPath, $json))'); } else { return fromJsonCode(referencedType); } @@ -966,7 +988,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { } } else if (type is TypeMap) { FromJsonCode keyCode; - if (dartType(type.keyType) != 'String') { + var referencedDefinition = api.types[type.keyType.typeName]; + if (dartType(type.keyType) != 'String' || + (requiresProtocolJsonMethods && + referencedDefinition?.name == 'FilePath')) { keyCode = fromJsonCode(type.keyType); } else { keyCode = FromJsonIdentity(); @@ -1060,7 +1085,14 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { /// Compute the code necessary to convert [type] to JSON. ToJsonCode toJsonCode(TypeDecl type) { var resolvedType = resolveTypeReferenceChain(type); - if (resolvedType is TypeReference) { + if (type is TypeReference && + requiresProtocolJsonMethods && + type.typeName == 'FilePath') { + return ToJsonSnippet( + dartType(type), + (String value) => 'clientUriConverter.toClientFilePath($value)', + ); + } else if (resolvedType is TypeReference) { return ToJsonIdentity(dartType(type)); } else if (resolvedType is TypeList) { var itemCode = toJsonCode(resolvedType.itemType); @@ -1072,7 +1104,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { } } else if (resolvedType is TypeMap) { ToJsonCode keyCode; - if (dartType(resolvedType.keyType) != 'String') { + var referencedDefinition = api.types[resolvedType.keyType.typeName]; + if (dartType(resolvedType.keyType) != 'String' || + (requiresProtocolJsonMethods && + referencedDefinition?.name == 'FilePath')) { keyCode = toJsonCode(resolvedType.keyType); } else { keyCode = ToJsonIdentity(dartType(resolvedType.keyType)); diff --git a/pkg/analysis_server/tool/spec/generate_all.dart b/pkg/analysis_server/tool/spec/generate_all.dart index f6f43aff6dc..f31cbfae320 100644 --- a/pkg/analysis_server/tool/spec/generate_all.dart +++ b/pkg/analysis_server/tool/spec/generate_all.dart @@ -29,8 +29,8 @@ List get allTargets { var targets = []; targets.add(codegen_analysis_server.target); targets.add(codegen_dart_notification_handler.clientTarget()); - targets.add(codegen_dart_protocol.clientTarget(false)); - targets.add(codegen_dart_protocol.serverTarget(false)); + targets.add(codegen_dart_protocol.clientTarget(false, false)); + targets.add(codegen_dart_protocol.serverTarget(false, true)); targets.add(codegen_java_types.targetDir); targets.add(codegen_inttest_methods.target); targets.add(codegen_matchers.target); diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart index 5cb698040c8..6f171bf5195 100644 --- a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart +++ b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart @@ -9,6 +9,8 @@ import 'package:analysis_server_client/src/protocol/protocol_base.dart'; import 'package:analysis_server_client/src/protocol/protocol_common.dart'; import 'package:analysis_server_client/src/protocol/protocol_generated.dart'; +final clientUriConverter = _ClientUriConverter(); + final Map REQUEST_ID_REFACTORING_KINDS = HashMap(); @@ -462,3 +464,14 @@ abstract class ResponseResult implements HasToJson { /// given [id]. Response toResponse(String id); } + +/// A dummy converter with the required API for the copy of protocol classes +/// in analysis_server_client. +class _ClientUriConverter { + // TODO(dantup): Determine whether analysis_server_client needs to support + // macro mappings. + + String fromClientFilePath(String filePath) => filePath; + + String toClientFilePath(String filePath) => filePath; +} diff --git a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart index 7d4370bb678..d21384758bc 100644 --- a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart +++ b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart @@ -24,6 +24,8 @@ mixin ResourceProviderMixin { ? MemoryResourceProvider(context: path.windows) : MemoryResourceProvider(); + path.Context get pathContext => resourceProvider.pathContext; + String convertPath(String path) => resourceProvider.convertPath(path); void deleteAnalysisOptionsYamlFile(String directoryPath) { diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart index 3f30a993220..2ce516580f8 100644 --- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart +++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart @@ -2798,7 +2798,8 @@ class Location implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -2847,7 +2848,7 @@ class Location implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; result['length'] = length; result['startLine'] = startLine; @@ -3538,7 +3539,8 @@ class Position implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -3557,7 +3559,7 @@ class Position implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['offset'] = offset; return result; } @@ -4390,7 +4392,8 @@ class SourceFileEdit implements HasToJson { if (json is Map) { String file; if (json.containsKey('file')) { - file = jsonDecoder.decodeString('$jsonPath.file', json['file']); + file = clientUriConverter.fromClientFilePath( + jsonDecoder.decodeString('$jsonPath.file', json['file'])); } else { throw jsonDecoder.mismatch(jsonPath, 'file'); } @@ -4420,7 +4423,7 @@ class SourceFileEdit implements HasToJson { @override Map toJson() { var result = {}; - result['file'] = file; + result['file'] = clientUriConverter.toClientFilePath(file); result['fileStamp'] = fileStamp; result['edits'] = edits.map((SourceEdit value) => value.toJson()).toList(); return result; diff --git a/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart index 5185ebc782e..fc01678c2a8 100644 --- a/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart +++ b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart @@ -8,7 +8,16 @@ import 'dart:convert' hide JsonDecoder; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart'; +import 'package:path/path.dart' as path; + +/// This can be set by server (or tests) to change into URI mode for all legacy +/// protocol JSON. +/// +// TODO(dantup): Consider replacing this global with encoders being passed to +// toJson/fromJson methods. +var clientUriConverter = ClientUriConverter.noop(path.context); final Map REQUEST_ID_REFACTORING_KINDS = HashMap(); diff --git a/pkg/analysis_server/lib/src/utilities/client_uri_converter.dart b/pkg/analyzer_plugin/lib/src/utilities/client_uri_converter.dart similarity index 63% rename from pkg/analysis_server/lib/src/utilities/client_uri_converter.dart rename to pkg/analyzer_plugin/lib/src/utilities/client_uri_converter.dart index 3396d230961..4260e23ff7e 100644 --- a/pkg/analysis_server/lib/src/utilities/client_uri_converter.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/client_uri_converter.dart @@ -2,7 +2,6 @@ // 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. -import 'package:analysis_server/lsp_protocol/protocol.dart'; import 'package:path/path.dart' as path; /// The file suffix used for virtual macro files in the analyzer. @@ -17,7 +16,7 @@ const macroClientUriScheme = 'dart-macro+file'; /// The simplest form of this class simple translates between file paths and /// `file://` URIs but depending on client capabilities some paths/URIs may be /// re-written to support features like virtual files for macros. -class ClientUriConverter { +abstract class ClientUriConverter { final path.Context _context; /// The URI schemes that are supported by this converter. @@ -29,27 +28,69 @@ class ClientUriConverter { /// The URI schemes that are supported by this converter except 'file'. final Set supportedNonFileSchemes; - /// A set of document filters for Dart files in the supported schemes. - final List filters; - /// Creates a converter that does nothing besides translation between file /// paths and `file://` URIs. - ClientUriConverter.noop(path.Context context) : this._(context); + factory ClientUriConverter.noop(path.Context context) => + _NoOpConverter(context); /// Creates a converter that translates paths/URIs for virtual files such as /// those created by macros. - ClientUriConverter.withVirtualFileSupport(path.Context context) - : this._(context, {macroClientUriScheme}); + factory ClientUriConverter.withVirtualFileSupport(path.Context context) => + _VirtualFileClientUriConverter(context); ClientUriConverter._(this._context, [this.supportedNonFileSchemes = const {}]) - : supportedSchemes = {'file', ...supportedNonFileSchemes}, - filters = [ - for (var scheme in {'file', ...supportedNonFileSchemes}) - TextDocumentFilterWithScheme(language: 'dart', scheme: scheme) - ]; + : supportedSchemes = {'file', ...supportedNonFileSchemes}; + + /// Converts client FilePath (which may be a URI or a file path depending on + /// client capbilities) into a file path/reference from the analyzer. + /// + /// This is the legacy protocol equiv of [fromClientUri]. + String fromClientFilePath(String filePathOrUri); /// Converts a URI provided by the client into a file path/reference that can /// be used by the analyzer. + /// + /// This is the LSP equiv of [fromClientFilePath]. + String fromClientUri(Uri uri); + + /// Converts a file path/reference from the analyzer into a client FilePath + /// (which may be a URI or a file path depending on client capbilities). + /// + /// This is the legacy protocol equiv of [toClientUri]. + String toClientFilePath(String filePath); + + /// Converts a file path/reference from the analyzer into a URI to be sent to + /// the client. + /// + /// This is the LSP equiv of [toClientFilePath]. + Uri toClientUri(String filePath); +} + +class _NoOpConverter extends ClientUriConverter { + _NoOpConverter(super.context) : super._(); + + @override + String fromClientFilePath(String filePathOrUri) => filePathOrUri; + + @override + String fromClientUri(Uri uri) => _context.fromUri(uri); + + @override + String toClientFilePath(String filePath) => filePath; + + @override + Uri toClientUri(String filePath) => _context.toUri(filePath); +} + +class _VirtualFileClientUriConverter extends ClientUriConverter { + _VirtualFileClientUriConverter(path.Context context) + : super._(context, {macroClientUriScheme}); + + @override + String fromClientFilePath(String filePathOrUri) => + fromClientUri(Uri.parse(filePathOrUri)); + + @override String fromClientUri(Uri uri) { // For URIs with no scheme, assume it was a relative path and provide a // better message than "scheme '' is not supported". @@ -81,8 +122,10 @@ class ClientUriConverter { } } - /// Converts a file path/reference from the analyzer into a URI to be sent to - /// the client. + @override + String toClientFilePath(String filePath) => toClientUri(filePath).toString(); + + @override Uri toClientUri(String filePath) { // Map '/.../x.macro.dart' onto macro scheme. if (filePath.endsWith(macroClientFileSuffix) && diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml index 54cb0410fb7..08dd5bdad91 100644 --- a/pkg/analyzer_plugin/pubspec.yaml +++ b/pkg/analyzer_plugin/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: dart_style: ^2.2.1 pub_semver: ^2.1.0 yaml: ^3.1.0 + path: ^1.9.0 # We use 'any' version constraints here as we get our package versions from # the dart-lang/sdk repo's DEPS file. Note that this is a special case; the @@ -22,6 +23,5 @@ dev_dependencies: lints: any linter: any meta: any - path: any test_reflective_loader: any test: any diff --git a/pkg/analysis_server/test/src/utilities/client_uri_converter_test.dart b/pkg/analyzer_plugin/test/src/utilities/client_uri_converter_test.dart similarity index 86% rename from pkg/analysis_server/test/src/utilities/client_uri_converter_test.dart rename to pkg/analyzer_plugin/test/src/utilities/client_uri_converter_test.dart index 3842d707fa7..14f6e525fc4 100644 --- a/pkg/analysis_server/test/src/utilities/client_uri_converter_test.dart +++ b/pkg/analyzer_plugin/test/src/utilities/client_uri_converter_test.dart @@ -2,13 +2,11 @@ // 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. -import 'package:analysis_server/src/utilities/client_uri_converter.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../../tool/codebase/failing_tests.dart'; -import '../../abstract_single_unit.dart'; - void main() { defineReflectiveSuite(() { defineReflectiveTests(ClientUriConverterTest); @@ -16,7 +14,7 @@ void main() { } @reflectiveTest -class ClientUriConverterTest extends AbstractSingleUnitTest { +class ClientUriConverterTest with ResourceProviderMixin { Future test_noop_fromUri() async { var converter = ClientUriConverter.noop(pathContext); diff --git a/pkg/analyzer_plugin/test/src/utilities/test_all.dart b/pkg/analyzer_plugin/test/src/utilities/test_all.dart index ba180de1e52..fb88ce8ae72 100644 --- a/pkg/analyzer_plugin/test/src/utilities/test_all.dart +++ b/pkg/analyzer_plugin/test/src/utilities/test_all.dart @@ -5,6 +5,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'change_builder/test_all.dart' as change_builder; +import 'client_uri_converter_test.dart' as client_uri_converter; import 'completion/test_all.dart' as completion; import 'navigation/test_all.dart' as navigation; import 'string_utilities_test.dart' as string_utilities; @@ -13,6 +14,7 @@ import 'visitors/test_all.dart' as visitors; void main() { defineReflectiveSuite(() { change_builder.main(); + client_uri_converter.main(); completion.main(); navigation.main(); string_utilities.main(); diff --git a/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart b/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart index ddaf5430a0a..68c735c45fc 100644 --- a/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart +++ b/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart @@ -25,11 +25,15 @@ const Map specialElementFlags = { 'deprecated': '0x20' }; -GeneratedFile target(bool responseRequiresRequestTime) { +GeneratedFile target( + bool responseRequiresRequestTime, bool requiresProtocolJsonMethods) { return GeneratedFile('lib/protocol/protocol_generated.dart', (String pkgPath) async { var visitor = CodegenProtocolVisitor( - path.basename(pkgPath), responseRequiresRequestTime, readApi(pkgPath)); + path.basename(pkgPath), + responseRequiresRequestTime, + requiresProtocolJsonMethods, + readApi(pkgPath)); return visitor.collectCode(visitor.visitApi); }); } @@ -65,6 +69,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { /// parameter. final bool responseRequiresRequestTime; + /// A flag indicating whether the classes should have `toProtocolJson` and + /// `fromProtocolJson` methods that can handle converting client URIs. + final bool requiresProtocolJsonMethods; + /// Visitor used to produce doc comments. final ToHtmlVisitor toHtmlVisitor; @@ -73,8 +81,8 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { /// notifications, etc. final Map impliedTypes; - CodegenProtocolVisitor( - this.packageName, this.responseRequiresRequestTime, Api api) + CodegenProtocolVisitor(this.packageName, this.responseRequiresRequestTime, + this.requiresProtocolJsonMethods, Api api) : toHtmlVisitor = ToHtmlVisitor(api), impliedTypes = computeImpliedTypes(api), super(api) { @@ -957,6 +965,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { return '$typeName.fromJson(jsonDecoder, $jsonPath, $json)'; } }); + } else if (requiresProtocolJsonMethods && + referencedDefinition.name == 'FilePath') { + return FromJsonSnippet((jsonPath, json) => + 'clientUriConverter.fromClientFilePath(jsonDecoder.decodeString($jsonPath, $json))'); } else { return fromJsonCode(referencedType); } @@ -977,7 +989,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { } } else if (type is TypeMap) { FromJsonCode keyCode; - if (dartType(type.keyType) != 'String') { + var referencedDefinition = api.types[type.keyType.typeName]; + if (dartType(type.keyType) != 'String' || + (requiresProtocolJsonMethods && + referencedDefinition?.name == 'FilePath')) { keyCode = fromJsonCode(type.keyType); } else { keyCode = FromJsonIdentity(); @@ -1071,7 +1086,14 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { /// Compute the code necessary to convert [type] to JSON. ToJsonCode toJsonCode(TypeDecl type) { var resolvedType = resolveTypeReferenceChain(type); - if (resolvedType is TypeReference) { + if (type is TypeReference && + requiresProtocolJsonMethods && + type.typeName == 'FilePath') { + return ToJsonSnippet( + dartType(type), + (String value) => 'clientUriConverter.toClientFilePath($value)', + ); + } else if (resolvedType is TypeReference) { return ToJsonIdentity(dartType(type)); } else if (resolvedType is TypeList) { var itemCode = toJsonCode(resolvedType.itemType); @@ -1083,7 +1105,10 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { } } else if (resolvedType is TypeMap) { ToJsonCode keyCode; - if (dartType(resolvedType.keyType) != 'String') { + var referencedDefinition = api.types[resolvedType.keyType.typeName]; + if (dartType(resolvedType.keyType) != 'String' || + (requiresProtocolJsonMethods && + referencedDefinition?.name == 'FilePath')) { keyCode = toJsonCode(resolvedType.keyType); } else { keyCode = ToJsonIdentity(dartType(resolvedType.keyType)); diff --git a/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart b/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart index 01389b7b7f7..78bd9817b8c 100644 --- a/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart +++ b/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart @@ -10,19 +10,28 @@ import 'codegen_dart_protocol.dart'; import 'from_html.dart'; import 'implied_types.dart'; -GeneratedFile clientTarget(bool responseRequiresRequestTime) => GeneratedFile( +GeneratedFile clientTarget( + bool responseRequiresRequestTime, bool requiresProtocolJsonMethods) => + GeneratedFile( '../analysis_server_client/lib/src/protocol/protocol_common.dart', (String pkgPath) async { var visitor = CodegenCommonVisitor( - path.basename(pkgPath), responseRequiresRequestTime, readApi(pkgPath), + path.basename(pkgPath), + responseRequiresRequestTime, + requiresProtocolJsonMethods, + readApi(pkgPath), forClient: true); return visitor.collectCode(visitor.visitApi); }); -GeneratedFile pluginTarget(bool responseRequiresRequestTime) => +GeneratedFile pluginTarget( + bool responseRequiresRequestTime, bool requiresProtocolJsonMethods) => GeneratedFile('lib/protocol/protocol_common.dart', (String pkgPath) async { - var visitor = CodegenCommonVisitor(path.basename(pkgPath), - responseRequiresRequestTime, readApi(pkgPath)); + var visitor = CodegenCommonVisitor( + path.basename(pkgPath), + responseRequiresRequestTime, + requiresProtocolJsonMethods, + readApi(pkgPath)); return visitor.collectCode(visitor.visitApi); }); @@ -34,8 +43,8 @@ class CodegenCommonVisitor extends CodegenProtocolVisitor { /// Initialize a newly created visitor to generate code in the package with /// the given [packageName] corresponding to the types in the given [api] that /// are common to multiple protocols. - CodegenCommonVisitor( - super.packageName, super.responseRequiresRequestTime, super.api, + CodegenCommonVisitor(super.packageName, super.responseRequiresRequestTime, + super.requiresProtocolJsonMethods, super.api, {this.forClient = false}); @override diff --git a/pkg/analyzer_plugin/tool/spec/generate_all.dart b/pkg/analyzer_plugin/tool/spec/generate_all.dart index 6507475c1b6..2b69df51b9c 100644 --- a/pkg/analyzer_plugin/tool/spec/generate_all.dart +++ b/pkg/analyzer_plugin/tool/spec/generate_all.dart @@ -24,11 +24,11 @@ Future main() async { /// Get a list of all generated targets. List get allTargets { var targets = []; - targets.add(codegen_dart_protocol.target(true)); + targets.add(codegen_dart_protocol.target(true, false)); targets.add(codegen_inttest_methods.target); targets.add(codegen_matchers.target); - targets.add(codegen_protocol_common.pluginTarget(true)); - targets.add(codegen_protocol_common.clientTarget(true)); + targets.add(codegen_protocol_common.pluginTarget(true, true)); + targets.add(codegen_protocol_common.clientTarget(true, false)); targets.add(codegen_protocol_constants.target); targets.add(to_html.target); return targets;