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: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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |