Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart

Issue 2664213003: Add the generator and the generated files (Closed)
Patch Set: add missed files Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:collection';
6 import 'dart:convert' hide JsonDecoder;
7
8 import 'package:analyzer_plugin/protocol/generated_protocol.dart';
9 import 'package:analyzer_plugin/protocol/protocol.dart';
10
11 final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS =
12 new HashMap<String, RefactoringKind>();
13
14 /**
15 * Adds the given [sourceEdits] to the list in [sourceFileEdit].
16 */
17 void addAllEditsForSource(
18 SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits) {
19 edits.forEach(sourceFileEdit.add);
20 }
21
22 /**
23 * Adds the given [sourceEdit] to the list in [sourceFileEdit].
24 */
25 void addEditForSource(SourceFileEdit sourceFileEdit, SourceEdit sourceEdit) {
26 List<SourceEdit> edits = sourceFileEdit.edits;
27 int index = 0;
28 while (index < edits.length && edits[index].offset > sourceEdit.offset) {
29 index++;
30 }
31 edits.insert(index, sourceEdit);
32 }
33
34 /**
35 * Adds [edit] to the [FileEdit] for the given [file].
36 */
37 void addEditToSourceChange(
38 SourceChange change, String file, int fileStamp, SourceEdit edit) {
39 SourceFileEdit fileEdit = change.getFileEdit(file);
40 if (fileEdit == null) {
41 fileEdit = new SourceFileEdit(file, fileStamp);
42 change.addFileEdit(fileEdit);
43 }
44 fileEdit.add(edit);
45 }
46
47 /**
48 * Get the result of applying the edit to the given [code]. Access via
49 * SourceEdit.apply().
50 */
51 String applyEdit(String code, SourceEdit edit) {
52 if (edit.length < 0) {
53 throw new RangeError('length is negative');
54 }
55 return code.replaceRange(edit.offset, edit.end, edit.replacement);
56 }
57
58 /**
59 * Get the result of applying a set of [edits] to the given [code]. Edits
60 * are applied in the order they appear in [edits]. Access via
61 * SourceEdit.applySequence().
62 */
63 String applySequenceOfEdits(String code, Iterable<SourceEdit> edits) {
64 edits.forEach((SourceEdit edit) {
65 code = edit.apply(code);
66 });
67 return code;
68 }
69
70 /**
71 * Returns the [FileEdit] for the given [file], maybe `null`.
72 */
73 SourceFileEdit getChangeFileEdit(SourceChange change, String file) {
74 for (SourceFileEdit fileEdit in change.edits) {
75 if (fileEdit.file == file) {
76 return fileEdit;
77 }
78 }
79 return null;
80 }
81
82 /**
83 * Compare the lists [listA] and [listB], using [itemEqual] to compare
84 * list elements.
85 */
86 bool listEqual(List listA, List listB, bool itemEqual(a, b)) {
87 if (listA == null) {
88 return listB == null;
89 }
90 if (listB == null) {
91 return false;
92 }
93 if (listA.length != listB.length) {
94 return false;
95 }
96 for (int i = 0; i < listA.length; i++) {
97 if (!itemEqual(listA[i], listB[i])) {
98 return false;
99 }
100 }
101 return true;
102 }
103
104 /**
105 * Compare the maps [mapA] and [mapB], using [valueEqual] to compare map
106 * values.
107 */
108 bool mapEqual(Map mapA, Map mapB, bool valueEqual(a, b)) {
109 if (mapA == null) {
110 return mapB == null;
111 }
112 if (mapB == null) {
113 return false;
114 }
115 if (mapA.length != mapB.length) {
116 return false;
117 }
118 for (var key in mapA.keys) {
119 if (!mapB.containsKey(key)) {
120 return false;
121 }
122 if (!valueEqual(mapA[key], mapB[key])) {
123 return false;
124 }
125 }
126 return true;
127 }
128
129 /**
130 * Translate the input [map], applying [keyCallback] to all its keys, and
131 * [valueCallback] to all its values.
132 */
133 Map/*<KR, VR>*/ mapMap/*<KP, VP, KR, VR>*/(Map/*<KP, VP>*/ map,
134 {dynamic/*=KR*/ keyCallback(/*<KP>*/ key),
135 dynamic/*=VR*/ valueCallback(/*<VP>*/ value)}) {
136 Map/*<KR, VR>*/ result = new HashMap/*<KR, VR>*/();
137 map.forEach((key, value) {
138 Object/*=KR*/ resultKey;
139 Object/*=VR*/ resultValue;
140 if (keyCallback != null) {
141 resultKey = keyCallback(key);
142 } else {
143 resultKey = key as Object/*=KR*/;
144 }
145 if (valueCallback != null) {
146 resultValue = valueCallback(value);
147 } else {
148 resultValue = value as Object/*=VR*/;
149 }
150 result[resultKey] = resultValue;
151 });
152 return result;
153 }
154
155 RefactoringProblemSeverity maxRefactoringProblemSeverity(
156 RefactoringProblemSeverity a, RefactoringProblemSeverity b) {
157 if (b == null) {
158 return a;
159 }
160 if (a == null) {
161 return b;
162 } else if (a == RefactoringProblemSeverity.INFO) {
163 return b;
164 } else if (a == RefactoringProblemSeverity.WARNING) {
165 if (b == RefactoringProblemSeverity.ERROR ||
166 b == RefactoringProblemSeverity.FATAL) {
167 return b;
168 }
169 } else if (a == RefactoringProblemSeverity.ERROR) {
170 if (b == RefactoringProblemSeverity.FATAL) {
171 return b;
172 }
173 }
174 return a;
175 }
176
177 /**
178 * Create a [RefactoringFeedback] corresponding the given [kind].
179 */
180 RefactoringFeedback refactoringFeedbackFromJson(
181 JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
182 RefactoringKind kind = jsonDecoder.refactoringKind;
183 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
184 return new ExtractLocalVariableFeedback.fromJson(
185 jsonDecoder, jsonPath, json);
186 }
187 if (kind == RefactoringKind.EXTRACT_METHOD) {
188 return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
189 }
190 if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
191 return new InlineLocalVariableFeedback.fromJson(
192 jsonDecoder, jsonPath, json);
193 }
194 if (kind == RefactoringKind.INLINE_METHOD) {
195 return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
196 }
197 if (kind == RefactoringKind.RENAME) {
198 return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json);
199 }
200 return null;
201 }
202
203 /**
204 * Create a [RefactoringOptions] corresponding the given [kind].
205 */
206 RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
207 String jsonPath, Object json, RefactoringKind kind) {
208 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
209 return new ExtractLocalVariableOptions.fromJson(
210 jsonDecoder, jsonPath, json);
211 }
212 if (kind == RefactoringKind.EXTRACT_METHOD) {
213 return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
214 }
215 if (kind == RefactoringKind.INLINE_METHOD) {
216 return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
217 }
218 if (kind == RefactoringKind.MOVE_FILE) {
219 return new MoveFileOptions.fromJson(jsonDecoder, jsonPath, json);
220 }
221 if (kind == RefactoringKind.RENAME) {
222 return new RenameOptions.fromJson(jsonDecoder, jsonPath, json);
223 }
224 return null;
225 }
226
227 ///**
228 // * Create a [RefactoringFeedback] corresponding the given [kind].
229 // */
230 //RefactoringFeedback refactoringFeedbackFromJson(
231 // JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
232 // RefactoringKind kind = jsonDecoder.refactoringKind;
233 // if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
234 // return new ExtractLocalVariableFeedback.fromJson(
235 // jsonDecoder, jsonPath, json);
236 // }
237 // if (kind == RefactoringKind.EXTRACT_METHOD) {
238 // return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
239 // }
240 // if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
241 // return new InlineLocalVariableFeedback.fromJson(
242 // jsonDecoder, jsonPath, json);
243 // }
244 // if (kind == RefactoringKind.INLINE_METHOD) {
245 // return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
246 // }
247 // if (kind == RefactoringKind.RENAME) {
248 // return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json);
249 // }
250 // return null;
251 //}
252 //
253 ///**
254 // * Create a [RefactoringOptions] corresponding the given [kind].
255 // */
256 //RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
257 // String jsonPath, Object json, RefactoringKind kind) {
258 // if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
259 // return new ExtractLocalVariableOptions.fromJson(
260 // jsonDecoder, jsonPath, json);
261 // }
262 // if (kind == RefactoringKind.EXTRACT_METHOD) {
263 // return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
264 // }
265 // if (kind == RefactoringKind.INLINE_METHOD) {
266 // return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
267 // }
268 // if (kind == RefactoringKind.MOVE_FILE) {
269 // return new MoveFileOptions.fromJson(jsonDecoder, jsonPath, json);
270 // }
271 // if (kind == RefactoringKind.RENAME) {
272 // return new RenameOptions.fromJson(jsonDecoder, jsonPath, json);
273 // }
274 // return null;
275 //}
276
277 /**
278 * Type of callbacks used to decode parts of JSON objects. [jsonPath] is a
279 * string describing the part of the JSON object being decoded, and [value] is
280 * the part to decode.
281 */
282 typedef E JsonDecoderCallback<E>(String jsonPath, Object value);
283
284 /**
285 * Instances of the class [HasToJson] implement [toJson] method that returns
286 * a JSON presentation.
287 */
288 abstract class HasToJson {
289 /**
290 * Returns a JSON presentation of the object.
291 */
292 Map<String, Object> toJson();
293 }
294
295 /**
296 * Base class for decoding JSON objects. The derived class must implement
297 * error reporting logic.
298 */
299 abstract class JsonDecoder {
300 /**
301 * Retrieve the RefactoringKind that should be assumed when decoding
302 * refactoring feedback objects, or null if no refactoring feedback object is
303 * expected to be encountered.
304 */
305 RefactoringKind get refactoringKind;
306
307 /**
308 * Decode a JSON object that is expected to be a boolean. The strings "true"
309 * and "false" are also accepted.
310 */
311 bool decodeBool(String jsonPath, Object json) {
312 if (json is bool) {
313 return json;
314 } else if (json == 'true') {
315 return true;
316 } else if (json == 'false') {
317 return false;
318 }
319 throw mismatch(jsonPath, 'bool', json);
320 }
321
322 /**
323 * Decode a JSON object that is expected to be an integer. A string
324 * representation of an integer is also accepted.
325 */
326 int decodeInt(String jsonPath, Object json) {
327 if (json is int) {
328 return json;
329 } else if (json is String) {
330 return int.parse(json, onError: (String value) {
331 throw mismatch(jsonPath, 'int', json);
332 });
333 }
334 throw mismatch(jsonPath, 'int', json);
335 }
336
337 /**
338 * Decode a JSON object that is expected to be a List. The [decoder] is used
339 * to decode the items in the list.
340 *
341 * The type parameter [E] is the expected type of the elements in the list.
342 */
343 List/*<E>*/ decodeList/*<E>*/(String jsonPath, Object json,
344 [JsonDecoderCallback/*<E>*/ decoder]) {
345 if (json == null) {
346 return/*<E>*/ [];
347 } else if (json is List) {
348 List/*<E>*/ result = /*<E>*/ [];
349 for (int i = 0; i < json.length; i++) {
350 result.add(decoder('$jsonPath[$i]', json[i]));
351 }
352 return result;
353 } else {
354 throw mismatch(jsonPath, 'List', json);
355 }
356 }
357
358 /**
359 * Decode a JSON object that is expected to be a Map. [keyDecoder] is used
360 * to decode the keys, and [valueDecoder] is used to decode the values.
361 */
362 Map/*<K, V>*/ decodeMap/*<K, V>*/(String jsonPath, Object json,
363 {JsonDecoderCallback/*<K>*/ keyDecoder,
364 JsonDecoderCallback/*<V>*/ valueDecoder}) {
365 if (json == null) {
366 return {};
367 } else if (json is Map) {
368 Map/*<K, V>*/ result = /*<K, V>*/ {};
369 json.forEach((String key, value) {
370 Object/*=K*/ decodedKey;
371 if (keyDecoder != null) {
372 decodedKey = keyDecoder('$jsonPath.key', key);
373 } else {
374 decodedKey = key as Object/*=K*/;
375 }
376 if (valueDecoder != null) {
377 value = valueDecoder('$jsonPath[${JSON.encode(key)}]', value);
378 }
379 result[decodedKey] = value as Object/*=V*/;
380 });
381 return result;
382 } else {
383 throw mismatch(jsonPath, 'Map', json);
384 }
385 }
386
387 /**
388 * Decode a JSON object that is expected to be a string.
389 */
390 String decodeString(String jsonPath, Object json) {
391 if (json is String) {
392 return json;
393 } else {
394 throw mismatch(jsonPath, 'String', json);
395 }
396 }
397
398 /**
399 * Decode a JSON object that is expected to be one of several choices,
400 * where the choices are disambiguated by the contents of the field [field].
401 * [decoders] is a map from each possible string in the field to the decoder
402 * that should be used to decode the JSON object.
403 */
404 Object decodeUnion(String jsonPath, Map json, String field,
405 Map<String, JsonDecoderCallback> decoders) {
406 if (json is Map) {
407 if (!json.containsKey(field)) {
408 throw missingKey(jsonPath, field);
409 }
410 var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]';
411 String disambiguator = decodeString(disambiguatorPath, json[field]);
412 if (!decoders.containsKey(disambiguator)) {
413 throw mismatch(
414 disambiguatorPath, 'One of: ${decoders.keys.toList()}', json);
415 }
416 return decoders[disambiguator](jsonPath, json);
417 } else {
418 throw mismatch(jsonPath, 'Map', json);
419 }
420 }
421
422 /**
423 * Create an exception to throw if the JSON object at [jsonPath] fails to
424 * match the API definition of [expected].
425 */
426 dynamic mismatch(String jsonPath, String expected, [Object actual]);
427
428 /**
429 * Create an exception to throw if the JSON object at [jsonPath] is missing
430 * the key [key].
431 */
432 dynamic missingKey(String jsonPath, String key);
433 }
434
435 /**
436 * JsonDecoder for decoding requests. Errors are reporting by throwing a
437 * [RequestFailure].
438 */
439 class RequestDecoder extends JsonDecoder {
440 /**
441 * The request being deserialized.
442 */
443 final Request _request;
444
445 RequestDecoder(this._request);
446
447 @override
448 RefactoringKind get refactoringKind {
449 // Refactoring feedback objects should never appear in requests.
450 return null;
451 }
452
453 @override
454 dynamic mismatch(String jsonPath, String expected, [Object actual]) {
455 StringBuffer buffer = new StringBuffer();
456 buffer.write('Expected to be ');
457 buffer.write(expected);
458 if (actual != null) {
459 buffer.write('; found "');
460 buffer.write(JSON.encode(actual));
461 buffer.write('"');
462 }
463 return new RequestFailure(RequestErrorFactory.invalidParameter(
464 _request, jsonPath, buffer.toString()));
465 }
466
467 @override
468 dynamic missingKey(String jsonPath, String key) {
469 return new RequestFailure(RequestErrorFactory.invalidParameter(
470 _request, jsonPath, 'Expected to contain key ${JSON.encode(key)}'));
471 }
472 }
473
474 /**
475 * JsonDecoder for decoding responses from the server. This is intended to be
476 * used only for testing. Errors are reported using bare [Exception] objects.
477 */
478 class ResponseDecoder extends JsonDecoder {
479 @override
480 final RefactoringKind refactoringKind;
481
482 ResponseDecoder(this.refactoringKind);
483
484 @override
485 dynamic mismatch(String jsonPath, String expected, [Object actual]) {
486 StringBuffer buffer = new StringBuffer();
487 buffer.write('Expected ');
488 buffer.write(expected);
489 if (actual != null) {
490 buffer.write(' found "');
491 buffer.write(JSON.encode(actual));
492 buffer.write('"');
493 }
494 buffer.write(' at ');
495 buffer.write(jsonPath);
496 return new Exception(buffer.toString());
497 }
498
499 @override
500 dynamic missingKey(String jsonPath, String key) {
501 return new Exception('Missing key $key at $jsonPath');
502 }
503 }
504
505 /**
506 * The result data associated with a response.
507 */
508 abstract class ResponseResult implements HasToJson {
509 /**
510 * Return a response whose result data is this object for the request with the
511 * given [id].
512 */
513 Response toResponse(String id);
514 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698