Index: pkg/analysis_server/tool/spec/api.dart |
diff --git a/pkg/analysis_server/tool/spec/api.dart b/pkg/analysis_server/tool/spec/api.dart |
index 98a9e7100a8a36298383d51aea80df88dbb62a81..070437ce7adb4d7bf3e964faabbc81cc5ad4e60d 100644 |
--- a/pkg/analysis_server/tool/spec/api.dart |
+++ b/pkg/analysis_server/tool/spec/api.dart |
@@ -13,20 +13,58 @@ import 'dart:collection'; |
import 'package:html5lib/dom.dart' as dom; |
/** |
+ * Toplevel container for the API. |
+ */ |
+class Api extends ApiNode { |
+ final String version; |
+ final List<Domain> domains; |
+ final Types types; |
+ final Refactorings refactorings; |
+ |
+ Api(this.version, this.domains, this.types, this.refactorings, |
+ dom.Element html) |
+ : super(html); |
+} |
+ |
+/** |
+ * Base class for objects in the API model. |
+ */ |
+class ApiNode { |
+ /** |
+ * Html element representing this part of the API. |
+ */ |
+ final dom.Element html; |
+ |
+ ApiNode(this.html); |
+} |
+ |
+/** |
* Base class for visiting the API definition. |
*/ |
abstract class ApiVisitor<T> { |
- T visitTypeReference(TypeReference typeReference); |
- T visitTypeUnion(TypeUnion typeUnion); |
- T visitTypeObject(TypeObject typeObject); |
- T visitTypeList(TypeList typeList); |
- T visitTypeMap(TypeMap typeMap); |
- T visitTypeEnum(TypeEnum typeEnum); |
- |
/** |
* Dispatch the given [type] to the visitor. |
*/ |
T visitTypeDecl(TypeDecl type) => type.accept(this); |
+ T visitTypeEnum(TypeEnum typeEnum); |
+ T visitTypeList(TypeList typeList); |
+ T visitTypeMap(TypeMap typeMap); |
+ T visitTypeObject(TypeObject typeObject); |
+ T visitTypeReference(TypeReference typeReference); |
+ |
+ T visitTypeUnion(TypeUnion typeUnion); |
+} |
+ |
+/** |
+ * Definition of a single domain. |
+ */ |
+class Domain extends ApiNode { |
+ final String name; |
+ final List<Request> requests; |
+ final List<Notification> notifications; |
+ |
+ Domain(this.name, this.requests, this.notifications, dom.Element html) |
+ : super(html); |
} |
/** |
@@ -40,14 +78,35 @@ class HierarchicalApiVisitor extends ApiVisitor { |
HierarchicalApiVisitor(this.api); |
+ /** |
+ * If [type] is a [TypeReference] that is defined in the API, follow the |
+ * chain until a non-[TypeReference] is found, if possible. |
+ * |
+ * If it is not possible (because the chain ends with a [TypeReference] that |
+ * is not defined in the API), then that final [TypeReference] is returned. |
+ */ |
+ TypeDecl resolveTypeReferenceChain(TypeDecl type) { |
+ while (type is TypeReference && api.types.containsKey(type.typeName)) { |
+ type = api.types[(type as TypeReference).typeName].type; |
+ } |
+ return type; |
+ } |
+ |
void visitApi() { |
api.domains.forEach(visitDomain); |
visitTypes(api.types); |
visitRefactorings(api.refactorings); |
} |
- void visitRefactorings(Refactorings refactorings) { |
- refactorings.forEach(visitRefactoring); |
+ void visitDomain(Domain domain) { |
+ domain.requests.forEach(visitRequest); |
+ domain.notifications.forEach(visitNotification); |
+ } |
+ |
+ void visitNotification(Notification notification) { |
+ if (notification.params != null) { |
+ visitTypeDecl(notification.params); |
+ } |
} |
void visitRefactoring(Refactoring refactoring) { |
@@ -59,19 +118,8 @@ class HierarchicalApiVisitor extends ApiVisitor { |
} |
} |
- void visitTypes(Types types) { |
- types.forEach(visitTypeDefinition); |
- } |
- |
- void visitDomain(Domain domain) { |
- domain.requests.forEach(visitRequest); |
- domain.notifications.forEach(visitNotification); |
- } |
- |
- void visitNotification(Notification notification) { |
- if (notification.params != null) { |
- visitTypeDecl(notification.params); |
- } |
+ void visitRefactorings(Refactorings refactorings) { |
+ refactorings.forEach(visitRefactoring); |
} |
void visitRequest(Request request) { |
@@ -119,61 +167,60 @@ class HierarchicalApiVisitor extends ApiVisitor { |
void visitTypeReference(TypeReference typeReference) { |
} |
+ void visitTypes(Types types) { |
+ types.forEach(visitTypeDefinition); |
+ } |
+ |
@override |
void visitTypeUnion(TypeUnion typeUnion) { |
typeUnion.choices.forEach(visitTypeDecl); |
} |
- |
- /** |
- * If [type] is a [TypeReference] that is defined in the API, follow the |
- * chain until a non-[TypeReference] is found, if possible. |
- * |
- * If it is not possible (because the chain ends with a [TypeReference] that |
- * is not defined in the API), then that final [TypeReference] is returned. |
- */ |
- TypeDecl resolveTypeReferenceChain(TypeDecl type) { |
- while (type is TypeReference && api.types.containsKey(type.typeName)) { |
- type = api.types[(type as TypeReference).typeName].type; |
- } |
- return type; |
- } |
} |
/** |
- * Base class for objects in the API model. |
+ * Description of a request method. |
*/ |
-class ApiNode { |
+class Notification extends ApiNode { |
/** |
- * Html element representing this part of the API. |
+ * Name of the domain enclosing this request. |
*/ |
- final dom.Element html; |
- |
- ApiNode(this.html); |
-} |
+ final String domainName; |
-/** |
- * Toplevel container for the API. |
- */ |
-class Api extends ApiNode { |
- final String version; |
- final List<Domain> domains; |
- final Types types; |
- final Refactorings refactorings; |
+ /** |
+ * Name of the notification, without the domain prefix. |
+ */ |
+ final String event; |
- Api(this.version, this.domains, this.types, this.refactorings, dom.Element |
- html) : super(html); |
-} |
+ /** |
+ * Type of the object associated with the "params" key in the notification |
+ * object, or null if the notification has no parameters. |
+ */ |
+ final TypeObject params; |
-/** |
- * A collection of refactoring definitions. |
- */ |
-class Refactorings extends ApiNode with IterableMixin<Refactoring> { |
- final List<Refactoring> refactorings; |
+ Notification(this.domainName, this.event, this.params, dom.Element html) |
+ : super(html); |
- Refactorings(this.refactorings, dom.Element html) : super(html); |
+ /** |
+ * Get the name of the notification, including the domain prefix. |
+ */ |
+ String get longEvent => '$domainName.$event'; |
- @override |
- Iterator<Refactoring> get iterator => refactorings.iterator; |
+ /** |
+ * Get the full type of the notification object, including the common "id" |
+ * and "error" fields. |
+ */ |
+ TypeDecl get notificationType { |
+ List<TypeObjectField> fields = [ |
+ new TypeObjectField( |
+ 'event', |
+ new TypeReference('String', null), |
+ null, |
+ value: '$domainName.$event')]; |
+ if (params != null) { |
+ fields.add(new TypeObjectField('params', params, null)); |
+ } |
+ return new TypeObject(fields, null); |
+ } |
} |
/** |
@@ -197,38 +244,20 @@ class Refactoring extends ApiNode { |
*/ |
final TypeObject options; |
- Refactoring(this.kind, this.feedback, this.options, dom.Element html) : super( |
- html); |
+ Refactoring(this.kind, this.feedback, this.options, dom.Element html) |
+ : super(html); |
} |
/** |
- * A collection of type definitions. |
+ * A collection of refactoring definitions. |
*/ |
-class Types extends ApiNode with IterableMixin<TypeDefinition> { |
- final Map<String, TypeDefinition> types; |
- |
- Types(this.types, dom.Element html) : super(html); |
+class Refactorings extends ApiNode with IterableMixin<Refactoring> { |
+ final List<Refactoring> refactorings; |
- bool containsKey(String typeName) => types.containsKey(typeName); |
+ Refactorings(this.refactorings, dom.Element html) : super(html); |
@override |
- Iterator<TypeDefinition> get iterator => types.values.iterator; |
- |
- TypeDefinition operator [](String typeName) => types[typeName]; |
- |
- Iterable<String> get keys => types.keys; |
-} |
- |
-/** |
- * Definition of a single domain. |
- */ |
-class Domain extends ApiNode { |
- final String name; |
- final List<Request> requests; |
- final List<Notification> notifications; |
- |
- Domain(this.name, this.requests, this.notifications, dom.Element html) : |
- super(html); |
+ Iterator<Refactoring> get iterator => refactorings.iterator; |
} |
/** |
@@ -257,8 +286,9 @@ class Request extends ApiNode { |
*/ |
final TypeObject result; |
- Request(this.domainName, this.method, this.params, this.result, dom.Element |
- html) : super(html); |
+ Request(this.domainName, this.method, this.params, this.result, |
+ dom.Element html) |
+ : super(html); |
/** |
* Get the name of the request, including the domain prefix. |
@@ -270,9 +300,13 @@ class Request extends ApiNode { |
* "method" fields. |
*/ |
TypeDecl get requestType { |
- List<TypeObjectField> fields = [new TypeObjectField('id', new TypeReference( |
- 'String', null), null), new TypeObjectField('method', new TypeReference( |
- 'String', null), null, value: '$domainName.$method')]; |
+ List<TypeObjectField> fields = [ |
+ new TypeObjectField('id', new TypeReference('String', null), null), |
+ new TypeObjectField( |
+ 'method', |
+ new TypeReference('String', null), |
+ null, |
+ value: '$domainName.$method')]; |
if (params != null) { |
fields.add(new TypeObjectField('params', params, null)); |
} |
@@ -299,45 +333,12 @@ class Request extends ApiNode { |
} |
/** |
- * Description of a request method. |
+ * Base class for all possible types. |
*/ |
-class Notification extends ApiNode { |
- /** |
- * Name of the domain enclosing this request. |
- */ |
- final String domainName; |
- |
- /** |
- * Name of the notification, without the domain prefix. |
- */ |
- final String event; |
- |
- /** |
- * Type of the object associated with the "params" key in the notification |
- * object, or null if the notification has no parameters. |
- */ |
- final TypeObject params; |
- |
- Notification(this.domainName, this.event, this.params, dom.Element html) : |
- super(html); |
- |
- /** |
- * Get the name of the notification, including the domain prefix. |
- */ |
- String get longEvent => '$domainName.$event'; |
+abstract class TypeDecl extends ApiNode { |
+ TypeDecl(dom.Element html) : super(html); |
- /** |
- * Get the full type of the notification object, including the common "id" |
- * and "error" fields. |
- */ |
- TypeDecl get notificationType { |
- List<TypeObjectField> fields = [new TypeObjectField('event', |
- new TypeReference('String', null), null, value: '$domainName.$event')]; |
- if (params != null) { |
- fields.add(new TypeObjectField('params', params, null)); |
- } |
- return new TypeObject(fields, null); |
- } |
+ accept(ApiVisitor visitor); |
} |
/** |
@@ -351,44 +352,56 @@ class TypeDefinition extends ApiNode { |
} |
/** |
- * Base class for all possible types. |
+ * Type of an enum. We represent enums in JSON as strings, so this type |
+ * declaration simply lists the allowed values. |
*/ |
-abstract class TypeDecl extends ApiNode { |
- TypeDecl(dom.Element html) : super(html); |
+class TypeEnum extends TypeDecl { |
+ final List<TypeEnumValue> values; |
- accept(ApiVisitor visitor); |
+ TypeEnum(this.values, dom.Element html) : super(html); |
+ |
+ accept(ApiVisitor visitor) => visitor.visitTypeEnum(this); |
} |
/** |
- * A reference to a type which is either defined elsewhere in the API or which |
- * is built-in ([String], [bool], or [int]). |
+ * Description of a single allowed value for an enum. |
*/ |
-class TypeReference extends TypeDecl { |
- final String typeName; |
+class TypeEnumValue extends ApiNode { |
+ final String value; |
- TypeReference(this.typeName, dom.Element html) : super(html) { |
- if (typeName.isEmpty) { |
- throw new Exception('Empty type name'); |
- } |
- } |
+ TypeEnumValue(this.value, dom.Element html) : super(html); |
+} |
- accept(ApiVisitor visitor) => visitor.visitTypeReference(this); |
+/** |
+ * Type of a JSON list. |
+ */ |
+class TypeList extends TypeDecl { |
+ final TypeDecl itemType; |
+ |
+ TypeList(this.itemType, dom.Element html) : super(html); |
+ |
+ accept(ApiVisitor visitor) => visitor.visitTypeList(this); |
} |
/** |
- * Type which represents a union among multiple choices. |
+ * Type of a JSON map. |
*/ |
-class TypeUnion extends TypeDecl { |
- final List<TypeDecl> choices; |
+class TypeMap extends TypeDecl { |
+ /** |
+ * Type of map keys. Note that since JSON map keys must always be strings, |
+ * this must either be a [TypeReference] for [String], or a [TypeReference] |
+ * to a type which is defined in the API as an enum or a synonym for [String]. |
+ */ |
+ final TypeReference keyType; |
/** |
- * The field that is used to disambiguate this union |
+ * Type of map values. |
*/ |
- final String field; |
+ final TypeDecl valueType; |
- TypeUnion(this.choices, this.field, dom.Element html) : super(html); |
+ TypeMap(this.keyType, this.valueType, dom.Element html) : super(html); |
- accept(ApiVisitor visitor) => visitor.visitTypeUnion(this); |
+ accept(ApiVisitor visitor) => visitor.visitTypeMap(this); |
} |
/** |
@@ -427,59 +440,57 @@ class TypeObjectField extends ApiNode { |
*/ |
final Object value; |
- TypeObjectField(this.name, this.type, dom.Element html, {this.optional: |
- false, this.value}) : super(html); |
+ TypeObjectField(this.name, this.type, dom.Element html, {this.optional: false, |
+ this.value}) |
+ : super(html); |
} |
/** |
- * Type of a JSON list. |
+ * A reference to a type which is either defined elsewhere in the API or which |
+ * is built-in ([String], [bool], or [int]). |
*/ |
-class TypeList extends TypeDecl { |
- final TypeDecl itemType; |
+class TypeReference extends TypeDecl { |
+ final String typeName; |
- TypeList(this.itemType, dom.Element html) : super(html); |
+ TypeReference(this.typeName, dom.Element html) : super(html) { |
+ if (typeName.isEmpty) { |
+ throw new Exception('Empty type name'); |
+ } |
+ } |
- accept(ApiVisitor visitor) => visitor.visitTypeList(this); |
+ accept(ApiVisitor visitor) => visitor.visitTypeReference(this); |
} |
/** |
- * Type of a JSON map. |
+ * A collection of type definitions. |
*/ |
-class TypeMap extends TypeDecl { |
- /** |
- * Type of map keys. Note that since JSON map keys must always be strings, |
- * this must either be a [TypeReference] for [String], or a [TypeReference] |
- * to a type which is defined in the API as an enum or a synonym for [String]. |
- */ |
- final TypeReference keyType; |
- |
- /** |
- * Type of map values. |
- */ |
- final TypeDecl valueType; |
+class Types extends ApiNode with IterableMixin<TypeDefinition> { |
+ final Map<String, TypeDefinition> types; |
- TypeMap(this.keyType, this.valueType, dom.Element html) : super(html); |
+ Types(this.types, dom.Element html) : super(html); |
- accept(ApiVisitor visitor) => visitor.visitTypeMap(this); |
-} |
+ @override |
+ Iterator<TypeDefinition> get iterator => types.values.iterator; |
-/** |
- * Type of an enum. We represent enums in JSON as strings, so this type |
- * declaration simply lists the allowed values. |
- */ |
-class TypeEnum extends TypeDecl { |
- final List<TypeEnumValue> values; |
+ Iterable<String> get keys => types.keys; |
- TypeEnum(this.values, dom.Element html) : super(html); |
+ TypeDefinition operator [](String typeName) => types[typeName]; |
- accept(ApiVisitor visitor) => visitor.visitTypeEnum(this); |
+ bool containsKey(String typeName) => types.containsKey(typeName); |
} |
/** |
- * Description of a single allowed value for an enum. |
+ * Type which represents a union among multiple choices. |
*/ |
-class TypeEnumValue extends ApiNode { |
- final String value; |
+class TypeUnion extends TypeDecl { |
+ final List<TypeDecl> choices; |
- TypeEnumValue(this.value, dom.Element html) : super(html); |
+ /** |
+ * The field that is used to disambiguate this union |
+ */ |
+ final String field; |
+ |
+ TypeUnion(this.choices, this.field, dom.Element html) : super(html); |
+ |
+ accept(ApiVisitor visitor) => visitor.visitTypeUnion(this); |
} |