| 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 protocol; | 5 library protocol; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 part 'generated_protocol.dart'; | 10 part 'generated_protocol.dart'; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 * Retrieve the RefactoringKind that should be assumed when decoding | 274 * Retrieve the RefactoringKind that should be assumed when decoding |
| 275 * refactoring feedback objects, or null if no refactoring feedback object is | 275 * refactoring feedback objects, or null if no refactoring feedback object is |
| 276 * expected to be encountered. | 276 * expected to be encountered. |
| 277 */ | 277 */ |
| 278 RefactoringKind get refactoringKind; | 278 RefactoringKind get refactoringKind; |
| 279 | 279 |
| 280 /** | 280 /** |
| 281 * Create an exception to throw if the JSON object at [jsonPath] fails to | 281 * Create an exception to throw if the JSON object at [jsonPath] fails to |
| 282 * match the API definition of [expected]. | 282 * match the API definition of [expected]. |
| 283 */ | 283 */ |
| 284 dynamic mismatch(String jsonPath, String expected); | 284 dynamic mismatch(String jsonPath, String expected, [Object actual]); |
| 285 | 285 |
| 286 /** | 286 /** |
| 287 * Create an exception to throw if the JSON object at [jsonPath] is missing | 287 * Create an exception to throw if the JSON object at [jsonPath] is missing |
| 288 * the key [key]. | 288 * the key [key]. |
| 289 */ | 289 */ |
| 290 dynamic missingKey(String jsonPath, String key); | 290 dynamic missingKey(String jsonPath, String key); |
| 291 | 291 |
| 292 /** | 292 /** |
| 293 * Decode a JSON object that is expected to be a boolean. The strings "true" | 293 * Decode a JSON object that is expected to be a boolean. The strings "true" |
| 294 * and "false" are also accepted. | 294 * and "false" are also accepted. |
| 295 */ | 295 */ |
| 296 bool _decodeBool(String jsonPath, Object json) { | 296 bool _decodeBool(String jsonPath, Object json) { |
| 297 if (json is bool) { | 297 if (json is bool) { |
| 298 return json; | 298 return json; |
| 299 } else if (json == 'true') { | 299 } else if (json == 'true') { |
| 300 return true; | 300 return true; |
| 301 } else if (json == 'false') { | 301 } else if (json == 'false') { |
| 302 return false; | 302 return false; |
| 303 } | 303 } |
| 304 throw mismatch(jsonPath, 'bool'); | 304 throw mismatch(jsonPath, 'bool', json); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /** | 307 /** |
| 308 * Decode a JSON object that is expected to be an integer. A string | 308 * Decode a JSON object that is expected to be an integer. A string |
| 309 * representation of an integer is also accepted. | 309 * representation of an integer is also accepted. |
| 310 */ | 310 */ |
| 311 int _decodeInt(String jsonPath, Object json) { | 311 int _decodeInt(String jsonPath, Object json) { |
| 312 if (json is int) { | 312 if (json is int) { |
| 313 return json; | 313 return json; |
| 314 } else if (json is String) { | 314 } else if (json is String) { |
| 315 return int.parse(json, onError: (String value) { | 315 return int.parse(json, onError: (String value) { |
| 316 throw mismatch(jsonPath, 'int'); | 316 throw mismatch(jsonPath, 'int', json); |
| 317 }); | 317 }); |
| 318 } | 318 } |
| 319 throw mismatch(jsonPath, 'int'); | 319 throw mismatch(jsonPath, 'int', json); |
| 320 } | 320 } |
| 321 | 321 |
| 322 /** | 322 /** |
| 323 * Decode a JSON object that is expected to be a List. [decoder] is used to | 323 * Decode a JSON object that is expected to be a List. [decoder] is used to |
| 324 * decode the items in the list. | 324 * decode the items in the list. |
| 325 */ | 325 */ |
| 326 List _decodeList(String jsonPath, Object json, | 326 List _decodeList(String jsonPath, Object json, |
| 327 [JsonDecoderCallback decoder]) { | 327 [JsonDecoderCallback decoder]) { |
| 328 if (json == null) { | 328 if (json == null) { |
| 329 return []; | 329 return []; |
| 330 } else if (json is List) { | 330 } else if (json is List) { |
| 331 List result = []; | 331 List result = []; |
| 332 for (int i = 0; i < json.length; i++) { | 332 for (int i = 0; i < json.length; i++) { |
| 333 result.add(decoder('$jsonPath[$i]', json[i])); | 333 result.add(decoder('$jsonPath[$i]', json[i])); |
| 334 } | 334 } |
| 335 return result; | 335 return result; |
| 336 } else { | 336 } else { |
| 337 throw mismatch(jsonPath, 'List'); | 337 throw mismatch(jsonPath, 'List', json); |
| 338 } | 338 } |
| 339 } | 339 } |
| 340 | 340 |
| 341 /** | 341 /** |
| 342 * Decode a JSON object that is expected to be a Map. [keyDecoder] is used | 342 * Decode a JSON object that is expected to be a Map. [keyDecoder] is used |
| 343 * to decode the keys, and [valueDecoder] is used to decode the values. | 343 * to decode the keys, and [valueDecoder] is used to decode the values. |
| 344 */ | 344 */ |
| 345 Map _decodeMap(String jsonPath, Object json, | 345 Map _decodeMap(String jsonPath, Object json, |
| 346 {JsonDecoderCallback keyDecoder, JsonDecoderCallback valueDecoder}) { | 346 {JsonDecoderCallback keyDecoder, JsonDecoderCallback valueDecoder}) { |
| 347 if (json == null) { | 347 if (json == null) { |
| 348 return {}; | 348 return {}; |
| 349 } else if (json is Map) { | 349 } else if (json is Map) { |
| 350 Map result = {}; | 350 Map result = {}; |
| 351 json.forEach((String key, value) { | 351 json.forEach((String key, value) { |
| 352 Object decodedKey; | 352 Object decodedKey; |
| 353 if (keyDecoder != null) { | 353 if (keyDecoder != null) { |
| 354 decodedKey = keyDecoder('$jsonPath.key', key); | 354 decodedKey = keyDecoder('$jsonPath.key', key); |
| 355 } else { | 355 } else { |
| 356 decodedKey = key; | 356 decodedKey = key; |
| 357 } | 357 } |
| 358 if (valueDecoder != null) { | 358 if (valueDecoder != null) { |
| 359 value = valueDecoder('$jsonPath[${JSON.encode(key)}]', value); | 359 value = valueDecoder('$jsonPath[${JSON.encode(key)}]', value); |
| 360 } | 360 } |
| 361 result[decodedKey] = value; | 361 result[decodedKey] = value; |
| 362 }); | 362 }); |
| 363 return result; | 363 return result; |
| 364 } else { | 364 } else { |
| 365 throw mismatch(jsonPath, 'Map'); | 365 throw mismatch(jsonPath, 'Map', json); |
| 366 } | 366 } |
| 367 } | 367 } |
| 368 | 368 |
| 369 /** | 369 /** |
| 370 * Decode a JSON object that is expected to be a string. | 370 * Decode a JSON object that is expected to be a string. |
| 371 */ | 371 */ |
| 372 String _decodeString(String jsonPath, Object json) { | 372 String _decodeString(String jsonPath, Object json) { |
| 373 if (json is String) { | 373 if (json is String) { |
| 374 return json; | 374 return json; |
| 375 } else { | 375 } else { |
| 376 throw mismatch(jsonPath, 'String'); | 376 throw mismatch(jsonPath, 'String', json); |
| 377 } | 377 } |
| 378 } | 378 } |
| 379 | 379 |
| 380 /** | 380 /** |
| 381 * Decode a JSON object that is expected to be one of several choices, | 381 * Decode a JSON object that is expected to be one of several choices, |
| 382 * where the choices are disambiguated by the contents of the field [field]. | 382 * where the choices are disambiguated by the contents of the field [field]. |
| 383 * [decoders] is a map from each possible string in the field to the decoder | 383 * [decoders] is a map from each possible string in the field to the decoder |
| 384 * that should be used to decode the JSON object. | 384 * that should be used to decode the JSON object. |
| 385 */ | 385 */ |
| 386 Object _decodeUnion(String jsonPath, Map json, String field, | 386 Object _decodeUnion(String jsonPath, Map json, String field, |
| 387 Map<String, JsonDecoderCallback> decoders) { | 387 Map<String, JsonDecoderCallback> decoders) { |
| 388 if (json is Map) { | 388 if (json is Map) { |
| 389 if (!json.containsKey(field)) { | 389 if (!json.containsKey(field)) { |
| 390 throw missingKey(jsonPath, field); | 390 throw missingKey(jsonPath, field); |
| 391 } | 391 } |
| 392 var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]'; | 392 var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]'; |
| 393 String disambiguator = _decodeString(disambiguatorPath, json[field]); | 393 String disambiguator = _decodeString(disambiguatorPath, json[field]); |
| 394 if (!decoders.containsKey(disambiguator)) { | 394 if (!decoders.containsKey(disambiguator)) { |
| 395 throw mismatch(disambiguatorPath, 'One of: ${decoders.keys.toList()}'); | 395 throw mismatch(disambiguatorPath, 'One of: ${decoders.keys.toList()}', j
son); |
| 396 } | 396 } |
| 397 return decoders[disambiguator](jsonPath, json); | 397 return decoders[disambiguator](jsonPath, json); |
| 398 } else { | 398 } else { |
| 399 throw mismatch(jsonPath, 'Map'); | 399 throw mismatch(jsonPath, 'Map', json); |
| 400 } | 400 } |
| 401 } | 401 } |
| 402 } | 402 } |
| 403 | 403 |
| 404 /** | 404 /** |
| 405 * Instances of the class [Notification] represent a notification from the | 405 * Instances of the class [Notification] represent a notification from the |
| 406 * server about an event that occurred. | 406 * server about an event that occurred. |
| 407 */ | 407 */ |
| 408 class Notification { | 408 class Notification { |
| 409 /** | 409 /** |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 final Request _request; | 609 final Request _request; |
| 610 | 610 |
| 611 RequestDecoder(this._request); | 611 RequestDecoder(this._request); |
| 612 | 612 |
| 613 RefactoringKind get refactoringKind { | 613 RefactoringKind get refactoringKind { |
| 614 // Refactoring feedback objects should never appear in requests. | 614 // Refactoring feedback objects should never appear in requests. |
| 615 return null; | 615 return null; |
| 616 } | 616 } |
| 617 | 617 |
| 618 @override | 618 @override |
| 619 dynamic mismatch(String jsonPath, String expected) { | 619 dynamic mismatch(String jsonPath, String expected, [Object actual]) { |
| 620 StringBuffer buffer = new StringBuffer(); |
| 621 buffer.write('Expected to be '); |
| 622 buffer.write(expected); |
| 623 if (actual != null) { |
| 624 buffer.write('; found "'); |
| 625 buffer.write(JSON.encode(actual)); |
| 626 buffer.write('"'); |
| 627 } |
| 620 return new RequestFailure(new Response.invalidParameter( | 628 return new RequestFailure(new Response.invalidParameter( |
| 621 _request, jsonPath, 'Expected to be $expected')); | 629 _request, jsonPath, buffer.toString())); |
| 622 } | 630 } |
| 623 | 631 |
| 624 @override | 632 @override |
| 625 dynamic missingKey(String jsonPath, String key) { | 633 dynamic missingKey(String jsonPath, String key) { |
| 626 return new RequestFailure(new Response.invalidParameter( | 634 return new RequestFailure(new Response.invalidParameter( |
| 627 _request, jsonPath, 'Expected to contain key ${JSON.encode(key)}')); | 635 _request, jsonPath, 'Expected to contain key ${JSON.encode(key)}')); |
| 628 } | 636 } |
| 629 } | 637 } |
| 630 | 638 |
| 631 /** | 639 /** |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 /** | 916 /** |
| 909 * JsonDecoder for decoding responses from the server. This is intended to be | 917 * JsonDecoder for decoding responses from the server. This is intended to be |
| 910 * used only for testing. Errors are reported using bare [Exception] objects. | 918 * used only for testing. Errors are reported using bare [Exception] objects. |
| 911 */ | 919 */ |
| 912 class ResponseDecoder extends JsonDecoder { | 920 class ResponseDecoder extends JsonDecoder { |
| 913 final RefactoringKind refactoringKind; | 921 final RefactoringKind refactoringKind; |
| 914 | 922 |
| 915 ResponseDecoder(this.refactoringKind); | 923 ResponseDecoder(this.refactoringKind); |
| 916 | 924 |
| 917 @override | 925 @override |
| 918 dynamic mismatch(String jsonPath, String expected) { | 926 dynamic mismatch(String jsonPath, String expected, [Object actual]) { |
| 919 return new Exception('Expected $expected at $jsonPath'); | 927 StringBuffer buffer = new StringBuffer(); |
| 928 buffer.write('Expected '); |
| 929 buffer.write(expected); |
| 930 if (actual != null) { |
| 931 buffer.write(' found "'); |
| 932 buffer.write(JSON.encode(actual)); |
| 933 buffer.write('"'); |
| 934 } |
| 935 buffer.write(' at '); |
| 936 buffer.write(jsonPath); |
| 937 return new Exception(buffer.toString()); |
| 920 } | 938 } |
| 921 | 939 |
| 922 @override | 940 @override |
| 923 dynamic missingKey(String jsonPath, String key) { | 941 dynamic missingKey(String jsonPath, String key) { |
| 924 return new Exception('Missing key $key at $jsonPath'); | 942 return new Exception('Missing key $key at $jsonPath'); |
| 925 } | 943 } |
| 926 } | 944 } |
| 927 | 945 |
| 928 /** | 946 /** |
| 929 * Jenkins hash function, optimized for small integers. Borrowed from | 947 * Jenkins hash function, optimized for small integers. Borrowed from |
| (...skipping 12 matching lines...) Expand all Loading... |
| 942 hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | 960 hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); |
| 943 hash = hash ^ (hash >> 11); | 961 hash = hash ^ (hash >> 11); |
| 944 return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | 962 return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); |
| 945 } | 963 } |
| 946 | 964 |
| 947 static int hash2(a, b) => finish(combine(combine(0, a), b)); | 965 static int hash2(a, b) => finish(combine(combine(0, a), b)); |
| 948 | 966 |
| 949 static int hash4(a, b, c, d) => | 967 static int hash4(a, b, c, d) => |
| 950 finish(combine(combine(combine(combine(0, a), b), c), d)); | 968 finish(combine(combine(combine(combine(0, a), b), c), d)); |
| 951 } | 969 } |
| OLD | NEW |