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

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

Issue 138833010: Add structured error support (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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:convert' show JsonDecoder; 7 import 'dart:convert' show JsonDecoder;
8 8
9 /** 9 /**
10 * Instances of the class [Request] represent a request that was received. 10 * Instances of the class [Request] represent a request that was received.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 /** 48 /**
49 * Initialize a newly created [Request] to have the given [id] and [method] 49 * Initialize a newly created [Request] to have the given [id] and [method]
50 * name. 50 * name.
51 */ 51 */
52 Request(this.id, this.method); 52 Request(this.id, this.method);
53 53
54 /** 54 /**
55 * Return a request parsed from the given [data], or `null` if the [data] is 55 * Return a request parsed from the given [data], or `null` if the [data] is
56 * not a valid json representation of a request. The [data] is expected to 56 * not a valid json representation of a request. The [data] is expected to
57 * have the following format: 57 * have the following format:
58 * 58 *
59 * { 59 * {
60 * 'id': String, 60 * 'id': String,
61 * 'method': methodName, 61 * 'method': methodName,
62 * 'params': { 62 * 'params': {
63 * paramter_name: value 63 * paramter_name: value
64 * } 64 * }
65 * } 65 * }
66 * 66 *
67 * where the parameters are optional and can contain any number of name/value 67 * where the parameters are optional and can contain any number of name/value
68 * pairs. 68 * pairs.
69 */ 69 */
70 factory Request.fromString(String data) { 70 factory Request.fromString(String data) {
71 try { 71 try {
72 var result = DECODER.convert(data); 72 var result = DECODER.convert(data);
73 if (result is! Map) { 73 if (result is! Map) {
74 return null; 74 return null;
75 } 75 }
76 String id = result[Request.ID]; 76 String id = result[Request.ID];
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 /** 108 /**
109 * Set the value of the parameter with the given [name] to the given [value]. 109 * Set the value of the parameter with the given [name] to the given [value].
110 */ 110 */
111 void setParameter(String name, Object value) { 111 void setParameter(String name, Object value) {
112 params[name] = value; 112 params[name] = value;
113 } 113 }
114 114
115 /** 115 /**
116 * Convert the given [value] to a boolean, or throw a [RequestFailure] 116 * Convert the given [value] to a boolean, or throw a [RequestFailure]
117 * exception if the [value] could not be converted. 117 * exception if the [value] could not be converted.
118 * 118 *
119 * The value is typically the result of invoking either [getParameter] or 119 * The value is typically the result of invoking either [getParameter] or
120 * [getRequiredParameter]. 120 * [getRequiredParameter].
121 */ 121 */
122 bool toBool(Object value) { 122 bool toBool(Object value) {
123 if (value is bool) { 123 if (value is bool) {
124 return value; 124 return value;
125 } else if (value is String) { 125 } else if (value is String) {
126 return value == 'true'; 126 return value == 'true';
127 } 127 }
128 throw new RequestFailure(new Response.expectedBoolean(this, value)); 128 throw new RequestFailure(new Response.expectedBoolean(this, value));
129 } 129 }
130 130
131 /** 131 /**
132 * Convert the given [value] to an integer, or throw a [RequestFailure] 132 * Convert the given [value] to an integer, or throw a [RequestFailure]
133 * exception if the [value] could not be converted. 133 * exception if the [value] could not be converted.
134 * 134 *
135 * The value is typically the result of invoking either [getParameter] or 135 * The value is typically the result of invoking either [getParameter] or
136 * [getRequiredParameter]. 136 * [getRequiredParameter].
137 */ 137 */
138 int toInt(Object value) { 138 int toInt(Object value) {
139 if (value is int) { 139 if (value is int) {
140 return value; 140 return value;
141 } else if (value is String) { 141 } else if (value is String) {
142 return int.parse(value, onError: (String value) { 142 return int.parse(value, onError: (String value) {
143 throw new RequestFailure(new Response.expectedInteger(this, value)); 143 throw new RequestFailure(new Response.expectedInteger(this, value));
144 }); 144 });
(...skipping 25 matching lines...) Expand all
170 /** 170 /**
171 * The unique identifier used to identify the request that this response is 171 * The unique identifier used to identify the request that this response is
172 * associated with. 172 * associated with.
173 */ 173 */
174 final String id; 174 final String id;
175 175
176 /** 176 /**
177 * The error that was caused by attempting to handle the request, or `null` if 177 * The error that was caused by attempting to handle the request, or `null` if
178 * there was no error. 178 * there was no error.
179 */ 179 */
180 final Object error; 180 final RequestError error;
181 181
182 /** 182 /**
183 * A table mapping the names of result fields to their values. The table 183 * A table mapping the names of result fields to their values. The table
184 * should be empty if there was an error. 184 * should be empty if there was an error.
185 */ 185 */
186 final Map<String, Object> result = new Map<String, Object>(); 186 final Map<String, Object> result = new Map<String, Object>();
187 187
188 /** 188 /**
189 * Initialize a newly created instance to represent a response to a request 189 * Initialize a newly created instance to represent a response to a request
190 * with the given [id]. If an [error] is provided then the response will 190 * with the given [id]. If an [error] is provided then the response will
191 * represent an error condition. 191 * represent an error condition.
192 */ 192 */
193 Response(this.id, [this.error]); 193 Response(this.id, [this.error]);
194 194
195 /** 195 /**
196 * Initialize a newly created instance to represent an error condition caused 196 * Initialize a newly created instance to represent an error condition caused
197 * by a [request] referencing a context that does not exist. 197 * by a [request] referencing a context that does not exist.
198 */ 198 */
199 Response.contextDoesNotExist(Request request) 199 Response.contextDoesNotExist(Request request)
200 : this(request.id, 'Context does not exist'); 200 : this(request.id, new RequestError(-1, 'Context does not exist'));
201 201
202 /** 202 /**
203 * Initialize a newly created instance to represent an error condition caused 203 * Initialize a newly created instance to represent an error condition caused
204 * by a [request] that was expected to have a boolean-valued parameter but was 204 * by a [request] that was expected to have a boolean-valued parameter but was
205 * passed a non-boolean value. 205 * passed a non-boolean value.
206 */ 206 */
207 Response.expectedBoolean(Request request, String value) 207 Response.expectedBoolean(Request request, String value)
208 : this(request.id, 'Expected a boolean value, but found "$value"'); 208 : this(request.id, new RequestError(-2, 'Expected a boolean value, but found "$value"'));
209 209
210 /** 210 /**
211 * Initialize a newly created instance to represent an error condition caused 211 * Initialize a newly created instance to represent an error condition caused
212 * by a [request] that was expected to have a integer-valued parameter but was 212 * by a [request] that was expected to have a integer-valued parameter but was
213 * passed a non-integer value. 213 * passed a non-integer value.
214 */ 214 */
215 Response.expectedInteger(Request request, String value) 215 Response.expectedInteger(Request request, String value)
216 : this(request.id, 'Expected an integer value, but found "$value"'); 216 : this(request.id, new RequestError(-3, 'Expected an integer value, but foun d "$value"'));
217 217
218 /** 218 /**
219 * Initialize a newly created instance to represent an error condition caused 219 * Initialize a newly created instance to represent an error condition caused
220 * by a malformed request. 220 * by a malformed request.
221 */ 221 */
222 Response.invalidRequestFormat() 222 Response.invalidRequestFormat()
223 : this('', 'Invalid request'); 223 : this('', new RequestError(-4, 'Invalid request'));
224 224
225 /** 225 /**
226 * Initialize a newly created instance to represent an error condition caused 226 * Initialize a newly created instance to represent an error condition caused
227 * by a [request] that does not have a required parameter. 227 * by a [request] that does not have a required parameter.
228 */ 228 */
229 Response.missingRequiredParameter(Request request, String parameterName) 229 Response.missingRequiredParameter(Request request, String parameterName)
230 : this(request.id, 'Missing required parameter: $parameterName'); 230 : this(request.id, new RequestError(-5, 'Missing required parameter: $parame terName'));
231 231
232 /** 232 /**
233 * Initialize a newly created instance to represent an error condition caused 233 * Initialize a newly created instance to represent an error condition caused
234 * by a [request] that takes a set of analysis options but for which an 234 * by a [request] that takes a set of analysis options but for which an
235 * unknown analysis option was provided. 235 * unknown analysis option was provided.
236 */ 236 */
237 Response.unknownAnalysisOption(Request request, String optionName) 237 Response.unknownAnalysisOption(Request request, String optionName)
238 : this(request.id, 'Unknown analysis option: "$optionName"'); 238 : this(request.id, new RequestError(-6, 'Unknown analysis option: "$optionNa me"'));
239 239
240 /** 240 /**
241 * Initialize a newly created instance to represent an error condition caused 241 * Initialize a newly created instance to represent an error condition caused
242 * by a [request] that cannot be handled by any known handlers. 242 * by a [request] that cannot be handled by any known handlers.
243 */ 243 */
244 Response.unknownRequest(Request request) 244 Response.unknownRequest(Request request)
245 : this(request.id, 'Unknown request'); 245 : this(request.id, new RequestError(-7, 'Unknown request'));
246 246
247 /** 247 /**
248 * Return the value of the result field with the given [name]. 248 * Return the value of the result field with the given [name].
249 */ 249 */
250 Object getResult(String name) { 250 Object getResult(String name) {
251 return result[name]; 251 return result[name];
252 } 252 }
253 253
254 /** 254 /**
255 * Set the value of the result field with the given [name] to the given [value ]. 255 * Set the value of the result field with the given [name] to the given [value ].
256 */ 256 */
257 void setResult(String name, Object value) { 257 void setResult(String name, Object value) {
258 result[name] = value; 258 result[name] = value;
259 } 259 }
260 260
261 /** 261 /**
262 * Return a table representing the structure of the Json object that will be 262 * Return a table representing the structure of the Json object that will be
263 * sent to the client to represent this response. 263 * sent to the client to represent this response.
264 */ 264 */
265 Map<String, Object> toJson() { 265 Map<String, Object> toJson() {
266 Map jsonObject = new Map(); 266 Map jsonObject = new Map();
267 jsonObject[ID] = id; 267 jsonObject[ID] = id;
268 jsonObject[ERROR] = error; 268 jsonObject[ERROR] = error.toJson();
269 if (!result.isEmpty) { 269 if (!result.isEmpty) {
270 jsonObject[RESULT] = result; 270 jsonObject[RESULT] = result;
271 } 271 }
272 return jsonObject; 272 return jsonObject;
273 } 273 }
274 } 274 }
275 275
276 /** 276 /**
277 * Instances of the class [RequestError] represent information about an error th at
278 * occurred while attempting to respond to a [Request].
279 */
280 class RequestError {
281 /**
282 * The name of the JSON attribute containing the code that uniquely identifies
283 * the error that occurred.
284 */
285 static const String CODE = 'code';
286
287 /**
288 * The name of the JSON attribute containing an object with additional data
289 * related to the error.
290 */
291 static const String DATA = 'data';
292
293 /**
294 * The name of the JSON attribute containing a short description of the error.
295 */
296 static const String MESSAGE = 'message';
297
298 /**
299 * An error code indicating a parse error. Invalid JSON was received by the
300 * server. An error occurred on the server while parsing the JSON text.
301 */
302 static const int CODE_PARSE_ERROR = -32700;
303
304 /**
305 * An error code indicating an invalid request. The JSON sent is not a valid
306 * [Request] object.
307 */
308 static const int CODE_INVALID_REQUEST = -32600;
309
310 /**
311 * An error code indicating a method not found. The method does not exist or
312 * is not currently available.
313 */
314 static const int CODE_METHOD_NOT_FOUND = -32601;
315
316 /**
317 * An error code indicating one or more invalid parameters.
318 */
319 static const int CODE_INVALID_PARAMS = -32602;
320
321 /**
322 * An error code indicating an internal error.
323 */
324 static const int CODE_INTERNAL_ERROR = -32603;
325
326 /*
327 * In addition, codes -32000 to -32099 indicate a server error. They are
328 * reserved for implementation-defined server-errors.
329 */
330
331 /**
332 * The code that uniquely identifies the error that occurred.
333 */
334 final int code;
335
336 /**
337 * A short description of the error.
338 */
339 final String message;
340
341 /**
342 * A table mapping the names of notification parameters to their values.
343 */
344 final Map<String, Object> data = new Map<String, Object>();
345
346 /**
347 * Initialize a newly created [Error] to have the given [code] and [message].
348 */
349 RequestError(this.code, this.message);
350
351 /**
352 * Initialize a newly created [Error] to indicate a parse error. Invalid JSON
353 * was received by the server. An error occurred on the server while parsing
354 * the JSON text.
355 */
356 RequestError.parseError() : this(CODE_PARSE_ERROR, "Parse error");
357
358 /**
359 * Initialize a newly created [Error] to indicate an invalid request. The
360 * JSON sent is not a valid [Request] object.
361 */
362 RequestError.invalidRequest() : this(CODE_INVALID_REQUEST, "Invalid request");
363
364 /**
365 * Initialize a newly created [Error] to indicate that a method was not found.
366 * Either the method does not exist or is not currently available.
367 */
368 RequestError.methodNotFound() : this(CODE_METHOD_NOT_FOUND, "Method not found" );
369
370 /**
371 * Initialize a newly created [Error] to indicate one or more invalid
372 * parameters.
373 */
374 RequestError.invalidParameters() : this(CODE_INVALID_PARAMS, "Invalid paramete rs");
375
376 /**
377 * Initialize a newly created [Error] to indicate an internal error.
378 */
379 RequestError.internalError() : this(CODE_INTERNAL_ERROR, "Internal error");
380
381 /**
382 * Return the value of the data with the given [name], or `null` if there is
383 * no such data associated with this error.
384 */
385 Object getData(String name) => data[name];
386
387 /**
388 * Set the value of the data with the given [name] to the given [value].
389 */
390 void setData(String name, Object value) {
391 data[name] = value;
392 }
393
394 /**
395 * Return a table representing the structure of the Json object that will be
396 * sent to the client to represent this response.
397 */
398 Map<String, Object> toJson() {
399 Map jsonObject = new Map();
400 jsonObject[CODE] = code;
401 jsonObject[MESSAGE] = message;
402 if (!data.isEmpty) {
403 jsonObject[DATA] = data;
404 }
405 return jsonObject;
406 }
407 }
408
409 /**
277 * Instances of the class [Notification] represent a notification from the 410 * Instances of the class [Notification] represent a notification from the
278 * server about an event that occurred. 411 * server about an event that occurred.
279 */ 412 */
280 class Notification { 413 class Notification {
281 /** 414 /**
282 * The name of the JSON attribute containing the name of the event that 415 * The name of the JSON attribute containing the name of the event that
283 * triggered the notification. 416 * triggered the notification.
284 */ 417 */
285 static const String EVENT = 'event'; 418 static const String EVENT = 'event';
286 419
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 /** 487 /**
355 * The response to be returned as a result of the failure. 488 * The response to be returned as a result of the failure.
356 */ 489 */
357 final Response response; 490 final Response response;
358 491
359 /** 492 /**
360 * Initialize a newly created exception to return the given reponse. 493 * Initialize a newly created exception to return the given reponse.
361 */ 494 */
362 RequestFailure(this.response); 495 RequestFailure(this.response);
363 } 496 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698