OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analysis_server.src.protocol.protocol_internal; | |
6 | |
7 import 'dart:collection'; | 5 import 'dart:collection'; |
8 import 'dart:convert' hide JsonDecoder; | 6 import 'dart:convert' hide JsonDecoder; |
9 | 7 |
10 import 'package:analysis_server/protocol/protocol.dart'; | 8 import 'package:analysis_server/protocol/protocol.dart'; |
11 import 'package:analysis_server/protocol/protocol_generated.dart'; | 9 import 'package:analysis_server/protocol/protocol_generated.dart'; |
| 10 import 'package:analyzer_plugin/protocol/protocol_common.dart'; |
| 11 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' |
| 12 show JsonDecoder; |
| 13 |
| 14 export 'package:analyzer_plugin/src/protocol/protocol_internal.dart' |
| 15 show JsonDecoder; |
12 | 16 |
13 final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS = | 17 final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS = |
14 new HashMap<String, RefactoringKind>(); | 18 new HashMap<String, RefactoringKind>(); |
15 | 19 |
16 /** | 20 /** |
17 * Adds the given [sourceEdits] to the list in [sourceFileEdit]. | 21 * Adds the given [sourceEdits] to the list in [sourceFileEdit]. |
18 */ | 22 */ |
19 void addAllEditsForSource( | 23 void addAllEditsForSource( |
20 SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits) { | 24 SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits) { |
21 edits.forEach(sourceFileEdit.add); | 25 edits.forEach(sourceFileEdit.add); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 * a JSON presentation. | 242 * a JSON presentation. |
239 */ | 243 */ |
240 abstract class HasToJson { | 244 abstract class HasToJson { |
241 /** | 245 /** |
242 * Returns a JSON presentation of the object. | 246 * Returns a JSON presentation of the object. |
243 */ | 247 */ |
244 Map<String, Object> toJson(); | 248 Map<String, Object> toJson(); |
245 } | 249 } |
246 | 250 |
247 /** | 251 /** |
248 * Base class for decoding JSON objects. The derived class must implement | |
249 * error reporting logic. | |
250 */ | |
251 abstract class JsonDecoder { | |
252 /** | |
253 * Retrieve the RefactoringKind that should be assumed when decoding | |
254 * refactoring feedback objects, or null if no refactoring feedback object is | |
255 * expected to be encountered. | |
256 */ | |
257 RefactoringKind get refactoringKind; | |
258 | |
259 /** | |
260 * Decode a JSON object that is expected to be a boolean. The strings "true" | |
261 * and "false" are also accepted. | |
262 */ | |
263 bool decodeBool(String jsonPath, Object json) { | |
264 if (json is bool) { | |
265 return json; | |
266 } else if (json == 'true') { | |
267 return true; | |
268 } else if (json == 'false') { | |
269 return false; | |
270 } | |
271 throw mismatch(jsonPath, 'bool', json); | |
272 } | |
273 | |
274 /** | |
275 * Decode a JSON object that is expected to be an integer. A string | |
276 * representation of an integer is also accepted. | |
277 */ | |
278 int decodeInt(String jsonPath, Object json) { | |
279 if (json is int) { | |
280 return json; | |
281 } else if (json is String) { | |
282 return int.parse(json, onError: (String value) { | |
283 throw mismatch(jsonPath, 'int', json); | |
284 }); | |
285 } | |
286 throw mismatch(jsonPath, 'int', json); | |
287 } | |
288 | |
289 /** | |
290 * Decode a JSON object that is expected to be a List. The [decoder] is used | |
291 * to decode the items in the list. | |
292 * | |
293 * The type parameter [E] is the expected type of the elements in the list. | |
294 */ | |
295 List/*<E>*/ decodeList/*<E>*/(String jsonPath, Object json, | |
296 [JsonDecoderCallback/*<E>*/ decoder]) { | |
297 if (json == null) { | |
298 return/*<E>*/ []; | |
299 } else if (json is List) { | |
300 List/*<E>*/ result = /*<E>*/ []; | |
301 for (int i = 0; i < json.length; i++) { | |
302 result.add(decoder('$jsonPath[$i]', json[i])); | |
303 } | |
304 return result; | |
305 } else { | |
306 throw mismatch(jsonPath, 'List', json); | |
307 } | |
308 } | |
309 | |
310 /** | |
311 * Decode a JSON object that is expected to be a Map. [keyDecoder] is used | |
312 * to decode the keys, and [valueDecoder] is used to decode the values. | |
313 */ | |
314 Map/*<K, V>*/ decodeMap/*<K, V>*/(String jsonPath, Object json, | |
315 {JsonDecoderCallback/*<K>*/ keyDecoder, | |
316 JsonDecoderCallback/*<V>*/ valueDecoder}) { | |
317 if (json == null) { | |
318 return {}; | |
319 } else if (json is Map) { | |
320 Map/*<K, V>*/ result = /*<K, V>*/ {}; | |
321 json.forEach((String key, value) { | |
322 Object/*=K*/ decodedKey; | |
323 if (keyDecoder != null) { | |
324 decodedKey = keyDecoder('$jsonPath.key', key); | |
325 } else { | |
326 decodedKey = key as Object/*=K*/; | |
327 } | |
328 if (valueDecoder != null) { | |
329 value = valueDecoder('$jsonPath[${JSON.encode(key)}]', value); | |
330 } | |
331 result[decodedKey] = value as Object/*=V*/; | |
332 }); | |
333 return result; | |
334 } else { | |
335 throw mismatch(jsonPath, 'Map', json); | |
336 } | |
337 } | |
338 | |
339 /** | |
340 * Decode a JSON object that is expected to be a string. | |
341 */ | |
342 String decodeString(String jsonPath, Object json) { | |
343 if (json is String) { | |
344 return json; | |
345 } else { | |
346 throw mismatch(jsonPath, 'String', json); | |
347 } | |
348 } | |
349 | |
350 /** | |
351 * Decode a JSON object that is expected to be one of several choices, | |
352 * where the choices are disambiguated by the contents of the field [field]. | |
353 * [decoders] is a map from each possible string in the field to the decoder | |
354 * that should be used to decode the JSON object. | |
355 */ | |
356 Object decodeUnion(String jsonPath, Map json, String field, | |
357 Map<String, JsonDecoderCallback> decoders) { | |
358 if (json is Map) { | |
359 if (!json.containsKey(field)) { | |
360 throw missingKey(jsonPath, field); | |
361 } | |
362 var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]'; | |
363 String disambiguator = decodeString(disambiguatorPath, json[field]); | |
364 if (!decoders.containsKey(disambiguator)) { | |
365 throw mismatch( | |
366 disambiguatorPath, 'One of: ${decoders.keys.toList()}', json); | |
367 } | |
368 return decoders[disambiguator](jsonPath, json); | |
369 } else { | |
370 throw mismatch(jsonPath, 'Map', json); | |
371 } | |
372 } | |
373 | |
374 /** | |
375 * Create an exception to throw if the JSON object at [jsonPath] fails to | |
376 * match the API definition of [expected]. | |
377 */ | |
378 dynamic mismatch(String jsonPath, String expected, [Object actual]); | |
379 | |
380 /** | |
381 * Create an exception to throw if the JSON object at [jsonPath] is missing | |
382 * the key [key]. | |
383 */ | |
384 dynamic missingKey(String jsonPath, String key); | |
385 } | |
386 | |
387 /** | |
388 * JsonDecoder for decoding requests. Errors are reporting by throwing a | 252 * JsonDecoder for decoding requests. Errors are reporting by throwing a |
389 * [RequestFailure]. | 253 * [RequestFailure]. |
390 */ | 254 */ |
391 class RequestDecoder extends JsonDecoder { | 255 class RequestDecoder extends JsonDecoder { |
392 /** | 256 /** |
393 * The request being deserialized. | 257 * The request being deserialized. |
394 */ | 258 */ |
395 final Request _request; | 259 final Request _request; |
396 | 260 |
397 RequestDecoder(this._request); | 261 RequestDecoder(this._request); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 /** | 327 /** |
464 * The result data associated with a response. | 328 * The result data associated with a response. |
465 */ | 329 */ |
466 abstract class ResponseResult implements HasToJson { | 330 abstract class ResponseResult implements HasToJson { |
467 /** | 331 /** |
468 * Return a response whose result data is this object for the request with the | 332 * Return a response whose result data is this object for the request with the |
469 * given [id]. | 333 * given [id]. |
470 */ | 334 */ |
471 Response toResponse(String id); | 335 Response toResponse(String id); |
472 } | 336 } |
OLD | NEW |