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

Side by Side Diff: pkg/analysis_server/lib/src/protocol.dart

Issue 1246573002: Improve error messages for invalid requests (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Address comments Created 5 years, 5 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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/generated_protocol.dart ('k') | pkg/analysis_server/tool/spec/codegen_dart_protocol.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698