| 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 |