Index: sdk/lib/_internal/dartdoc/lib/universe_serializer.dart |
diff --git a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart |
new file mode 100755 |
index 0000000000000000000000000000000000000000..c6c1ec082b29fe49e594cf5f5812baaa99c68ad9 |
--- /dev/null |
+++ b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart |
@@ -0,0 +1,231 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+/** |
+ * This library serializes the Dart2Js AST into a compact and easy to use |
+ * [Element] tree useful for code exploration tools such as DartDoc. |
+ */ |
+library universe_serializer; |
+ |
+import '../../compiler/implementation/mirrors/mirrors.dart'; |
+import '../../compiler/implementation/mirrors/mirrors_util.dart'; |
+import '../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js; |
+import '../../libraries.dart'; |
+import 'dartdoc.dart'; |
+ |
+/** |
+ * Base class for all nodes. |
+ */ |
+class Element { |
+ /** Human readable type name for the node. */ |
+ final String kind; |
+ /** Human readable name for the element. */ |
+ final String name; |
+ /** Id for the node that is unique within its parent's children. */ |
+ final String id; |
+ /** Raw text of the comment associated with the Element if any. */ |
+ final String comment; |
+ /** Children of the node. */ |
+ List<Element> children; |
+ |
+ Element(this.kind, this.name, this.id, this.comment); |
+ |
+ void addChild(Element child) { |
+ if (children == null) { |
+ children = <Element>[]; |
+ } |
+ children.add(child); |
+ } |
+} |
+ |
+/** |
+ * Converts false to null. Useful as the serialization scheme we use |
+ * omits null values. |
+ */ |
+bool _optionalBool(bool value) => value == true ? true : null; |
+ |
+/** |
+ * [Element] describing a Dart library. |
+ */ |
+class LibraryElement extends Element { |
+ LibraryElement(String name, LibraryMirror mirror, CommentMap comments) |
+ : super('library', name, mirror.uri.toString(), |
+ comments.findLibrary(mirror.location)) { |
+ |
+ mirror.functions.forEach((childName, childMirror) { |
+ addChild(new MethodElement(childName, childMirror, comments)); |
+ }); |
+ |
+ mirror.getters.forEach((childName, childMirror) { |
+ addChild(new GetterElement(childName, childMirror, comments)); |
+ }); |
+ |
+ mirror.variables.forEach((childName, childMirror) { |
+ addChild(new VariableElement(childName, childMirror)); |
+ }); |
+ |
+ mirror.classes.forEach((className, classMirror) { |
+ if (!classMirror.isPrivate) { |
+ if (classMirror is TypedefMirror) { |
+ addChild(new TypedefElement(className, classMirror, comments)); |
+ } else { |
+ addChild(new ClassElement(className, classMirror, comments)); |
+ } |
+ } |
+ }); |
+ } |
+} |
+ |
+/** |
+ * [Element] describing a Dart class. |
+ */ |
+class ClassElement extends Element { |
+ /** Base class.*/ |
+ final Reference superclass; |
+ /** Interfaces the class implements. */ |
+ List<Reference> interfaces; |
+ |
+ ClassElement(String name, ClassMirror mirror, CommentMap comments) |
+ : super('class', mirror.simpleName, name, |
+ comments.find(mirror.location)), |
+ superclass = mirror.superclass != null ? |
+ new Reference(mirror.superclass) : null { |
+ for (var interface in mirror.superinterfaces) { |
+ if (this.interfaces == null) { |
+ this.interfaces = <Reference>[]; |
+ } |
+ this.interfaces.add(new Reference(interface)); |
+ } |
+ |
+ mirror.methods.forEach((childName, childMirror) { |
+ addChild(new MethodElement(childName, childMirror, comments)); |
+ }); |
+ |
+ mirror.getters.forEach((childName, childMirror) { |
+ addChild(new GetterElement(childName, childMirror, comments)); |
+ }); |
+ |
+ mirror.variables.forEach((childName, childMirror) { |
+ addChild(new VariableElement(childName, childMirror)); |
+ }); |
+ |
+ mirror.constructors.forEach((constructorName, methodMirror) { |
+ addChild(new MethodElement(constructorName, methodMirror, comments, 'constructor')); |
+ }); |
+ } |
+} |
+ |
+/** |
+ * [Element] describing a getter. |
+ */ |
+class GetterElement extends Element { |
+ /** Type of the getter. */ |
+ final Reference ref; |
+ final bool isStatic; |
+ |
+ GetterElement(String name, MethodMirror mirror, CommentMap comments) |
+ : super('property', mirror.simpleName, name, |
+ comments.find(mirror.location)), |
+ ref = mirror.returnType != null ? |
+ new Reference(mirror.returnType) : null, |
+ isStatic = _optionalBool(mirror.isStatic); |
+} |
+ |
+/** |
+ * [Element] describing a method which may be a regular method, a setter, or an |
+ * operator. |
+ */ |
+class MethodElement extends Element { |
+ final Reference returnType; |
+ final bool isSetter; |
+ final bool isOperator; |
+ final bool isStatic; |
+ |
+ MethodElement(String name, MethodMirror mirror, CommentMap comments, [String kind = 'method']) |
+ : super(kind, name, '$name${mirror.parameters.length}()', |
+ comments.find(mirror.location)), |
+ returnType = mirror.returnType != null ? |
+ new Reference(mirror.returnType) : null, |
+ isSetter = _optionalBool(mirror.isSetter), |
+ isOperator = _optionalBool(mirror.isOperator), |
+ isStatic = _optionalBool(mirror.isStatic) { |
+ |
+ for (var param in mirror.parameters) { |
+ addChild(new ParameterElement(param)); |
+ } |
+ } |
+} |
+ |
+/** |
+ * Element describing a parameter. |
+ */ |
+class ParameterElement extends Element { |
+ /** Type of the parameter. */ |
+ final Reference ref; |
+ /** Whether the parameter is optional. */ |
+ final bool isOptional; |
+ |
+ ParameterElement(ParameterMirror mirror) |
+ : super('param', mirror.simpleName, mirror.simpleName, null), |
+ ref = new Reference(mirror.type), |
+ isOptional = _optionalBool(mirror.isOptional) { |
+ } |
+} |
+ |
+/** |
+ * Element describing a variable. |
+ */ |
+class VariableElement extends Element { |
+ /** Type of the variable. */ |
+ final Reference ref; |
+ final bool isStatic; |
+ |
+ VariableElement(String name, VariableMirror mirror) |
+ : super('property', mirror.simpleName, name, null), |
+ ref = new Reference(mirror.type), |
+ isStatic = _optionalBool(mirror.isStatic); |
+} |
+// TODO(jacobr): this seems incomplete. |
+/** |
+ * Element describing a typedef element. |
+ */ |
+class TypedefElement extends Element { |
+ TypedefElement(String name, TypedefMirror mirror, CommentMap comments) |
+ : super('typedef', mirror.simpleName, name, |
+ comments.find(mirror.location)); |
+} |
+ |
+/** |
+ * Reference to an Element with type argument if the reference is parameterized. |
+ */ |
+class Reference { |
+ final String name; |
+ final String refId; |
+ List<Reference> arguments; |
+ |
+ Reference(Mirror mirror) |
+ : name = mirror.simpleName, |
+ refId = getId(mirror) { |
+ if (mirror is ClassMirror) { |
+ if (mirror is !TypedefMirror |
+ && mirror.typeArguments.length > 0) { |
+ arguments = <Reference>[]; |
+ for (var typeArg in mirror.typeArguments) { |
+ arguments.add(new Reference(typeArg)); |
+ } |
+ } |
+ } |
+ } |
+ |
+ static String getId(Mirror mirror) { |
+ String id = mirror.simpleName; |
+ if (mirror is MemberMirror) { |
+ MemberMirror memberMirror = mirror; |
+ if (memberMirror.owner != null) { |
+ id = '${getId(memberMirror.owner)}/$id'; |
+ } |
+ } |
+ return id; |
+ } |
+} |