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 /** | 5 /** |
6 * Data structures representing an API definition, and visitor base classes | 6 * Data structures representing an API definition, and visitor base classes |
7 * for visiting those data structures. | 7 * for visiting those data structures. |
8 */ | 8 */ |
9 library api; | 9 library api; |
10 | 10 |
11 import 'dart:collection'; | 11 import 'dart:collection'; |
12 | 12 |
13 import 'package:html/dom.dart' as dom; | 13 import 'package:html/dom.dart' as dom; |
14 | 14 |
15 /** | 15 /** |
16 * Toplevel container for the API. | 16 * Toplevel container for the API. |
17 */ | 17 */ |
18 class Api extends ApiNode { | 18 class Api extends ApiNode { |
19 final String version; | 19 final String version; |
20 final List<Domain> domains; | 20 final List<Domain> domains; |
21 final Types types; | 21 final Types types; |
22 final Refactorings refactorings; | 22 final Refactorings refactorings; |
23 | 23 |
24 Api(this.version, this.domains, this.types, this.refactorings, | 24 Api(this.version, this.domains, this.types, this.refactorings, |
25 dom.Element html) | 25 dom.Element html, |
26 : super(html); | 26 {bool experimental}) |
| 27 : super(html, experimental); |
27 } | 28 } |
28 | 29 |
29 /** | 30 /** |
30 * Base class for objects in the API model. | 31 * Base class for objects in the API model. |
31 */ | 32 */ |
32 class ApiNode { | 33 class ApiNode { |
33 /** | 34 /** |
| 35 * A flag to indicate if this API is experimental. |
| 36 */ |
| 37 final bool experimental; |
| 38 |
| 39 /** |
34 * Html element representing this part of the API. | 40 * Html element representing this part of the API. |
35 */ | 41 */ |
36 final dom.Element html; | 42 final dom.Element html; |
37 | 43 |
38 ApiNode(this.html); | 44 ApiNode(this.html, bool experimental) |
| 45 : this.experimental = experimental ?? false; |
39 } | 46 } |
40 | 47 |
41 /** | 48 /** |
42 * Base class for visiting the API definition. | 49 * Base class for visiting the API definition. |
43 */ | 50 */ |
44 abstract class ApiVisitor<T> { | 51 abstract class ApiVisitor<T> { |
45 /** | 52 /** |
46 * Dispatch the given [type] to the visitor. | 53 * Dispatch the given [type] to the visitor. |
47 */ | 54 */ |
48 T visitTypeDecl(TypeDecl type) => type.accept(this); | 55 T visitTypeDecl(TypeDecl type) => type.accept(this); |
49 T visitTypeEnum(TypeEnum typeEnum); | 56 T visitTypeEnum(TypeEnum typeEnum); |
50 T visitTypeList(TypeList typeList); | 57 T visitTypeList(TypeList typeList); |
51 T visitTypeMap(TypeMap typeMap); | 58 T visitTypeMap(TypeMap typeMap); |
52 T visitTypeObject(TypeObject typeObject); | 59 T visitTypeObject(TypeObject typeObject); |
53 T visitTypeReference(TypeReference typeReference); | 60 T visitTypeReference(TypeReference typeReference); |
54 | 61 |
55 T visitTypeUnion(TypeUnion typeUnion); | 62 T visitTypeUnion(TypeUnion typeUnion); |
56 } | 63 } |
57 | 64 |
58 /** | 65 /** |
59 * Definition of a single domain. | 66 * Definition of a single domain. |
60 */ | 67 */ |
61 class Domain extends ApiNode { | 68 class Domain extends ApiNode { |
62 final String name; | 69 final String name; |
63 final bool experimental; | |
64 final List<Request> requests; | 70 final List<Request> requests; |
65 final List<Notification> notifications; | 71 final List<Notification> notifications; |
66 | 72 |
67 Domain(this.name, this.experimental, this.requests, this.notifications, | 73 Domain(this.name, this.requests, this.notifications, dom.Element html, |
68 dom.Element html) | 74 {bool experimental}) |
69 : super(html); | 75 : super(html, experimental); |
70 } | 76 } |
71 | 77 |
72 /** | 78 /** |
73 * API visitor that visits the entire API hierarchically by default. | 79 * API visitor that visits the entire API hierarchically by default. |
74 */ | 80 */ |
75 class HierarchicalApiVisitor extends ApiVisitor { | 81 class HierarchicalApiVisitor extends ApiVisitor { |
76 /** | 82 /** |
77 * The API to visit. | 83 * The API to visit. |
78 */ | 84 */ |
79 final Api api; | 85 final Api api; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 * Name of the notification, without the domain prefix. | 196 * Name of the notification, without the domain prefix. |
191 */ | 197 */ |
192 final String event; | 198 final String event; |
193 | 199 |
194 /** | 200 /** |
195 * Type of the object associated with the "params" key in the notification | 201 * Type of the object associated with the "params" key in the notification |
196 * object, or null if the notification has no parameters. | 202 * object, or null if the notification has no parameters. |
197 */ | 203 */ |
198 final TypeObject params; | 204 final TypeObject params; |
199 | 205 |
200 Notification(this.domainName, this.event, this.params, dom.Element html) | 206 Notification(this.domainName, this.event, this.params, dom.Element html, |
201 : super(html); | 207 {bool experimental}) |
| 208 : super(html, experimental); |
202 | 209 |
203 /** | 210 /** |
204 * Get the name of the notification, including the domain prefix. | 211 * Get the name of the notification, including the domain prefix. |
205 */ | 212 */ |
206 String get longEvent => '$domainName.$event'; | 213 String get longEvent => '$domainName.$event'; |
207 | 214 |
208 /** | 215 /** |
209 * Get the full type of the notification object, including the common "id" | 216 * Get the full type of the notification object, including the common "id" |
210 * and "error" fields. | 217 * and "error" fields. |
211 */ | 218 */ |
(...skipping 23 matching lines...) Expand all Loading... |
235 * Type of the refactoring feedback, or null if the refactoring has no | 242 * Type of the refactoring feedback, or null if the refactoring has no |
236 * feedback. | 243 * feedback. |
237 */ | 244 */ |
238 final TypeObject feedback; | 245 final TypeObject feedback; |
239 | 246 |
240 /** | 247 /** |
241 * Type of the refactoring options, or null if the refactoring has no options. | 248 * Type of the refactoring options, or null if the refactoring has no options. |
242 */ | 249 */ |
243 final TypeObject options; | 250 final TypeObject options; |
244 | 251 |
245 Refactoring(this.kind, this.feedback, this.options, dom.Element html) | 252 Refactoring(this.kind, this.feedback, this.options, dom.Element html, |
246 : super(html); | 253 {bool experimental}) |
| 254 : super(html, experimental); |
247 } | 255 } |
248 | 256 |
249 /** | 257 /** |
250 * A collection of refactoring definitions. | 258 * A collection of refactoring definitions. |
251 */ | 259 */ |
252 class Refactorings extends ApiNode with IterableMixin<Refactoring> { | 260 class Refactorings extends ApiNode with IterableMixin<Refactoring> { |
253 final List<Refactoring> refactorings; | 261 final List<Refactoring> refactorings; |
254 | 262 |
255 Refactorings(this.refactorings, dom.Element html) : super(html); | 263 Refactorings(this.refactorings, dom.Element html, {bool experimental}) |
| 264 : super(html, experimental); |
256 | 265 |
257 @override | 266 @override |
258 Iterator<Refactoring> get iterator => refactorings.iterator; | 267 Iterator<Refactoring> get iterator => refactorings.iterator; |
259 } | 268 } |
260 | 269 |
261 /** | 270 /** |
262 * Description of a request method. | 271 * Description of a request method. |
263 */ | 272 */ |
264 class Request extends ApiNode { | 273 class Request extends ApiNode { |
265 /** | 274 /** |
(...skipping 12 matching lines...) Expand all Loading... |
278 */ | 287 */ |
279 final TypeObject params; | 288 final TypeObject params; |
280 | 289 |
281 /** | 290 /** |
282 * Type of the object associated with the "result" key in the response object, | 291 * Type of the object associated with the "result" key in the response object, |
283 * or null if the response has no results. | 292 * or null if the response has no results. |
284 */ | 293 */ |
285 final TypeObject result; | 294 final TypeObject result; |
286 | 295 |
287 Request( | 296 Request( |
288 this.domainName, this.method, this.params, this.result, dom.Element html) | 297 this.domainName, this.method, this.params, this.result, dom.Element html, |
289 : super(html); | 298 {bool experimental}) |
| 299 : super(html, experimental); |
290 | 300 |
291 /** | 301 /** |
292 * Get the name of the request, including the domain prefix. | 302 * Get the name of the request, including the domain prefix. |
293 */ | 303 */ |
294 String get longMethod => '$domainName.$method'; | 304 String get longMethod => '$domainName.$method'; |
295 | 305 |
296 /** | 306 /** |
297 * Get the full type of the request object, including the common "id" and | 307 * Get the full type of the request object, including the common "id" and |
298 * "method" fields. | 308 * "method" fields. |
299 */ | 309 */ |
(...skipping 24 matching lines...) Expand all Loading... |
324 fields.add(new TypeObjectField('result', result, null)); | 334 fields.add(new TypeObjectField('result', result, null)); |
325 } | 335 } |
326 return new TypeObject(fields, null); | 336 return new TypeObject(fields, null); |
327 } | 337 } |
328 } | 338 } |
329 | 339 |
330 /** | 340 /** |
331 * Base class for all possible types. | 341 * Base class for all possible types. |
332 */ | 342 */ |
333 abstract class TypeDecl extends ApiNode { | 343 abstract class TypeDecl extends ApiNode { |
334 TypeDecl(dom.Element html) : super(html); | 344 TypeDecl(dom.Element html, bool experimental) : super(html, experimental); |
335 | 345 |
336 accept(ApiVisitor visitor); | 346 accept(ApiVisitor visitor); |
337 } | 347 } |
338 | 348 |
339 /** | 349 /** |
340 * Description of a named type definition. | 350 * Description of a named type definition. |
341 */ | 351 */ |
342 class TypeDefinition extends ApiNode { | 352 class TypeDefinition extends ApiNode { |
343 final String name; | 353 final String name; |
344 final TypeDecl type; | 354 final TypeDecl type; |
345 | 355 |
346 TypeDefinition(this.name, this.type, dom.Element html) : super(html); | 356 TypeDefinition(this.name, this.type, dom.Element html, {bool experimental}) |
| 357 : super(html, experimental); |
347 } | 358 } |
348 | 359 |
349 /** | 360 /** |
350 * Type of an enum. We represent enums in JSON as strings, so this type | 361 * Type of an enum. We represent enums in JSON as strings, so this type |
351 * declaration simply lists the allowed values. | 362 * declaration simply lists the allowed values. |
352 */ | 363 */ |
353 class TypeEnum extends TypeDecl { | 364 class TypeEnum extends TypeDecl { |
354 final List<TypeEnumValue> values; | 365 final List<TypeEnumValue> values; |
355 | 366 |
356 TypeEnum(this.values, dom.Element html) : super(html); | 367 TypeEnum(this.values, dom.Element html, {bool experimental}) |
| 368 : super(html, experimental); |
357 | 369 |
358 accept(ApiVisitor visitor) => visitor.visitTypeEnum(this); | 370 accept(ApiVisitor visitor) => visitor.visitTypeEnum(this); |
359 } | 371 } |
360 | 372 |
361 /** | 373 /** |
362 * Description of a single allowed value for an enum. | 374 * Description of a single allowed value for an enum. |
363 */ | 375 */ |
364 class TypeEnumValue extends ApiNode { | 376 class TypeEnumValue extends ApiNode { |
365 final String value; | 377 final String value; |
366 | 378 |
367 TypeEnumValue(this.value, dom.Element html) : super(html); | 379 TypeEnumValue(this.value, dom.Element html, {bool experimental}) |
| 380 : super(html, experimental); |
368 } | 381 } |
369 | 382 |
370 /** | 383 /** |
371 * Type of a JSON list. | 384 * Type of a JSON list. |
372 */ | 385 */ |
373 class TypeList extends TypeDecl { | 386 class TypeList extends TypeDecl { |
374 final TypeDecl itemType; | 387 final TypeDecl itemType; |
375 | 388 |
376 TypeList(this.itemType, dom.Element html) : super(html); | 389 TypeList(this.itemType, dom.Element html, {bool experimental}) |
| 390 : super(html, experimental); |
377 | 391 |
378 accept(ApiVisitor visitor) => visitor.visitTypeList(this); | 392 accept(ApiVisitor visitor) => visitor.visitTypeList(this); |
379 } | 393 } |
380 | 394 |
381 /** | 395 /** |
382 * Type of a JSON map. | 396 * Type of a JSON map. |
383 */ | 397 */ |
384 class TypeMap extends TypeDecl { | 398 class TypeMap extends TypeDecl { |
385 /** | 399 /** |
386 * Type of map keys. Note that since JSON map keys must always be strings, | 400 * Type of map keys. Note that since JSON map keys must always be strings, |
387 * this must either be a [TypeReference] for [String], or a [TypeReference] | 401 * this must either be a [TypeReference] for [String], or a [TypeReference] |
388 * to a type which is defined in the API as an enum or a synonym for [String]. | 402 * to a type which is defined in the API as an enum or a synonym for [String]. |
389 */ | 403 */ |
390 final TypeReference keyType; | 404 final TypeReference keyType; |
391 | 405 |
392 /** | 406 /** |
393 * Type of map values. | 407 * Type of map values. |
394 */ | 408 */ |
395 final TypeDecl valueType; | 409 final TypeDecl valueType; |
396 | 410 |
397 TypeMap(this.keyType, this.valueType, dom.Element html) : super(html); | 411 TypeMap(this.keyType, this.valueType, dom.Element html, {bool experimental}) |
| 412 : super(html, experimental); |
398 | 413 |
399 accept(ApiVisitor visitor) => visitor.visitTypeMap(this); | 414 accept(ApiVisitor visitor) => visitor.visitTypeMap(this); |
400 } | 415 } |
401 | 416 |
402 /** | 417 /** |
403 * Type of a JSON object with specified fields, some of which may be optional. | 418 * Type of a JSON object with specified fields, some of which may be optional. |
404 */ | 419 */ |
405 class TypeObject extends TypeDecl { | 420 class TypeObject extends TypeDecl { |
406 final List<TypeObjectField> fields; | 421 final List<TypeObjectField> fields; |
407 | 422 |
408 TypeObject(this.fields, dom.Element html) : super(html); | 423 TypeObject(this.fields, dom.Element html, {bool experimental}) |
| 424 : super(html, experimental); |
409 | 425 |
410 accept(ApiVisitor visitor) => visitor.visitTypeObject(this); | 426 accept(ApiVisitor visitor) => visitor.visitTypeObject(this); |
411 | 427 |
412 /** | 428 /** |
413 * Return the field with the given [name], or null if there is no such field. | 429 * Return the field with the given [name], or null if there is no such field. |
414 */ | 430 */ |
415 TypeObjectField getField(String name) { | 431 TypeObjectField getField(String name) { |
416 for (TypeObjectField field in fields) { | 432 for (TypeObjectField field in fields) { |
417 if (field.name == name) { | 433 if (field.name == name) { |
418 return field; | 434 return field; |
(...skipping 10 matching lines...) Expand all Loading... |
429 final String name; | 445 final String name; |
430 final TypeDecl type; | 446 final TypeDecl type; |
431 final bool optional; | 447 final bool optional; |
432 | 448 |
433 /** | 449 /** |
434 * Value that the field is required to contain, or null if it may vary. | 450 * Value that the field is required to contain, or null if it may vary. |
435 */ | 451 */ |
436 final Object value; | 452 final Object value; |
437 | 453 |
438 TypeObjectField(this.name, this.type, dom.Element html, | 454 TypeObjectField(this.name, this.type, dom.Element html, |
439 {this.optional: false, this.value}) | 455 {this.optional: false, this.value, bool experimental}) |
440 : super(html); | 456 : super(html, experimental); |
441 } | 457 } |
442 | 458 |
443 /** | 459 /** |
444 * A reference to a type which is either defined elsewhere in the API or which | 460 * A reference to a type which is either defined elsewhere in the API or which |
445 * is built-in ([String], [bool], or [int]). | 461 * is built-in ([String], [bool], or [int]). |
446 */ | 462 */ |
447 class TypeReference extends TypeDecl { | 463 class TypeReference extends TypeDecl { |
448 final String typeName; | 464 final String typeName; |
449 | 465 |
450 TypeReference(this.typeName, dom.Element html) : super(html) { | 466 TypeReference(this.typeName, dom.Element html, {bool experimental}) |
| 467 : super(html, experimental) { |
451 if (typeName.isEmpty) { | 468 if (typeName.isEmpty) { |
452 throw new Exception('Empty type name'); | 469 throw new Exception('Empty type name'); |
453 } | 470 } |
454 } | 471 } |
455 | 472 |
456 accept(ApiVisitor visitor) => visitor.visitTypeReference(this); | 473 accept(ApiVisitor visitor) => visitor.visitTypeReference(this); |
457 } | 474 } |
458 | 475 |
459 /** | 476 /** |
460 * A collection of type definitions. | 477 * A collection of type definitions. |
461 */ | 478 */ |
462 class Types extends ApiNode with IterableMixin<TypeDefinition> { | 479 class Types extends ApiNode with IterableMixin<TypeDefinition> { |
463 final Map<String, TypeDefinition> types; | 480 final Map<String, TypeDefinition> types; |
464 | 481 |
465 Types(this.types, dom.Element html) : super(html); | 482 Types(this.types, dom.Element html, {bool experimental}) |
| 483 : super(html, experimental); |
466 | 484 |
467 @override | 485 @override |
468 Iterator<TypeDefinition> get iterator => types.values.iterator; | 486 Iterator<TypeDefinition> get iterator => types.values.iterator; |
469 | 487 |
470 Iterable<String> get keys => types.keys; | 488 Iterable<String> get keys => types.keys; |
471 | 489 |
472 TypeDefinition operator [](String typeName) => types[typeName]; | 490 TypeDefinition operator [](String typeName) => types[typeName]; |
473 | 491 |
474 bool containsKey(String typeName) => types.containsKey(typeName); | 492 bool containsKey(String typeName) => types.containsKey(typeName); |
475 } | 493 } |
476 | 494 |
477 /** | 495 /** |
478 * Type which represents a union among multiple choices. | 496 * Type which represents a union among multiple choices. |
479 */ | 497 */ |
480 class TypeUnion extends TypeDecl { | 498 class TypeUnion extends TypeDecl { |
481 final List<TypeDecl> choices; | 499 final List<TypeDecl> choices; |
482 | 500 |
483 /** | 501 /** |
484 * The field that is used to disambiguate this union | 502 * The field that is used to disambiguate this union |
485 */ | 503 */ |
486 final String field; | 504 final String field; |
487 | 505 |
488 TypeUnion(this.choices, this.field, dom.Element html) : super(html); | 506 TypeUnion(this.choices, this.field, dom.Element html, {bool experimental}) |
| 507 : super(html, experimental); |
489 | 508 |
490 accept(ApiVisitor visitor) => visitor.visitTypeUnion(this); | 509 accept(ApiVisitor visitor) => visitor.visitTypeUnion(this); |
491 } | 510 } |
OLD | NEW |