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 |
index f2ffbcfecb88ecbd65c572587a34a7182bb50c9d..53da5830f5a2d778c542f0d263686c5f99090a14 100755 |
--- a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart |
+++ b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart |
@@ -24,6 +24,10 @@ String _stripUri(String uri) { |
} |
} |
+String _escapeId(String id) { |
+ return id.replaceAll(new RegExp('[/]'), '#slash'); |
+} |
+ |
/** |
* Base class for all elements in the AST. |
*/ |
@@ -36,6 +40,14 @@ class Element { |
final String id; |
/** Raw text of the comment associated with the Element if any. */ |
final String comment; |
+ /** Raw html comment for the Element from MDN. */ |
+ String mdnCommentHtml; |
+ /** |
+ * The URL to the page on MDN that content was pulled from for the current |
+ * type being documented. Will be `null` if the type doesn't use any MDN |
+ * content. |
+ */ |
+ String mdnUrl; |
/** Children of the node. */ |
List<Element> children; |
/** Whether the element is private. */ |
@@ -50,10 +62,20 @@ class Element { |
*/ |
String line; |
- Element(Mirror mirror, this.kind, this.name, this.id, this.comment) |
+ Element(Mirror mirror, this.kind, this.name, String id, this.comment, |
+ MdnComment lookupMdnComment(Mirror)) |
: line = mirror.location.line.toString(), |
+ id = _escapeId(id), |
isPrivate = _optionalBool(mirror.isPrivate), |
- uri = _stripUri(mirror.location.sourceUri.toString()); |
+ uri = _stripUri(mirror.location.sourceUri.toString()) { |
+ if (lookupMdnComment != null) { |
+ var mdnComment = lookupMdnComment(mirror); |
+ if (mdnComment != null) { |
+ mdnCommentHtml = mdnComment.mdnComment; |
+ mdnUrl = mdnComment.mdnUrl; |
+ } |
+ } |
+ } |
void addChild(Element child) { |
if (children == null) { |
@@ -97,31 +119,69 @@ Reference _optionalReference(Mirror mirror) { |
* [Element] describing a Dart library. |
*/ |
class LibraryElement extends Element { |
- LibraryElement(String name, LibraryMirror mirror) |
- : super(mirror, 'library', name, name, computeComment(mirror)) { |
- |
+ LibraryElement(String name, LibraryMirror mirror, |
+ MdnComment lookupMdnComment(Mirror)) |
+ : super(mirror, 'library', _libraryName(mirror), name, |
+ computeComment(mirror), lookupMdnComment) { |
+ |
mirror.functions.forEach((childName, childMirror) { |
- addChild(new MethodElement(childName, childMirror)); |
+ addChild(new MethodElement(childName, childMirror, lookupMdnComment)); |
}); |
mirror.getters.forEach((childName, childMirror) { |
- addChild(new GetterElement(childName, childMirror)); |
+ addChild(new GetterElement(childName, childMirror, lookupMdnComment)); |
}); |
mirror.variables.forEach((childName, childMirror) { |
- addChild(new VariableElement(childName, childMirror)); |
+ addChild(new VariableElement(childName, childMirror, lookupMdnComment)); |
}); |
mirror.classes.forEach((className, classMirror) { |
- if (!classMirror.isPrivate) { |
- if (classMirror is TypedefMirror) { |
- addChild(new TypedefElement(className, classMirror)); |
- } else { |
- addChild(new ClassElement(className, classMirror)); |
- } |
+ if (classMirror is TypedefMirror) { |
+ addChild(new TypedefElement(className, classMirror)); |
+ } else { |
+ addChild(new ClassElement(className, classMirror, lookupMdnComment)); |
} |
}); |
} |
+ |
+ static String _libraryName(LibraryMirror mirror) { |
+ if (mirror.uri.scheme == 'file') { |
+ // TODO(jacobr): this is a hack. Remove once these libraries are removed |
+ // from the sdk. |
+ var uri = mirror.uri; |
+ var path = uri.path; |
+ var pattern = new RegExp(r'[\\/]dart[\\/]pkg[\\/]([^\\/]+)[\\/]lib[\\/](.+)$'); |
+ var match = pattern.firstMatch(path); |
+ var package; |
+ if (match != null) { |
+ package = match.group(1); |
+ path = match.group(2); |
+ } |
+ // TODO(jacobr): add a second pattern for a more typical pub environment. |
+ if (package != null) { |
+ return 'package:$package/$path'; |
+ } else { |
+ // TODO(jacobr): this is a lousy fallback. |
+ print("Unable to determine package for $path."); |
+ return mirror.uri.toString(); |
+ } |
+ } else { |
+ return mirror.uri.toString(); |
+ } |
+ } |
+} |
+ |
+/** |
+ * Returns whether the class implements or extends [Error] or [Exception]. |
+ */ |
+bool _isThrowable(ClassMirror mirror) { |
+ if (mirror.library.uri.toString() == 'dart:core' && |
+ mirror.simpleName == 'Error' || mirror.simpleName == 'Exception') |
+ return true; |
+ if (mirror.superclass != null && _isThrowable(mirror.superclass)) |
+ return true; |
+ return mirror.superinterfaces.any(_isThrowable); |
} |
/** |
@@ -134,11 +194,16 @@ class ClassElement extends Element { |
final bool isAbstract; |
/** Interfaces the class implements. */ |
List<Reference> interfaces; |
+ /** Whether the class implements or extends [Error] or [Exception]. */ |
+ bool isThrowable; |
- ClassElement(String name, ClassMirror mirror) |
- : super(mirror, 'class', mirror.simpleName, name, computeComment(mirror)), |
+ ClassElement(String name, ClassMirror mirror, |
+ MdnComment lookupMdnComment(Mirror)) |
+ : super(mirror, 'class', mirror.simpleName, name, computeComment(mirror), |
+ lookupMdnComment), |
superclass = _optionalReference(mirror.superclass), |
isAbstract = _optionalBool(mirror.isAbstract) { |
+ isThrowable = _optionalBool(_isThrowable(mirror)); |
for (var interface in mirror.superinterfaces) { |
if (this.interfaces == null) { |
this.interfaces = <Reference>[]; |
@@ -148,20 +213,22 @@ class ClassElement extends Element { |
mirror.methods.forEach((childName, childMirror) { |
if (!childMirror.isConstructor && !childMirror.isGetter) { |
- addChild(new MethodElement(childName, childMirror)); |
+ addChild(new MethodElement(childName, childMirror, lookupMdnComment)); |
} |
}); |
mirror.getters.forEach((childName, childMirror) { |
- addChild(new GetterElement(childName, childMirror)); |
+ addChild(new GetterElement(childName, childMirror, lookupMdnComment)); |
}); |
mirror.variables.forEach((childName, childMirror) { |
- addChild(new VariableElement(childName, childMirror)); |
+ addChild(new VariableElement(childName, childMirror, |
+ lookupMdnComment)); |
}); |
mirror.constructors.forEach((constructorName, methodMirror) { |
- addChild(new MethodElement(constructorName, methodMirror, 'constructor')); |
+ addChild(new MethodElement(constructorName, methodMirror, |
+ lookupMdnComment, 'constructor')); |
}); |
for (var typeVariable in mirror.originalDeclaration.typeVariables) { |
@@ -178,8 +245,10 @@ class GetterElement extends Element { |
final Reference ref; |
final bool isStatic; |
- GetterElement(String name, MethodMirror mirror) |
- : super(mirror, 'property', mirror.simpleName, name, computeComment(mirror)), |
+ GetterElement(String name, MethodMirror mirror, |
+ MdnComment lookupMdnComment(Mirror)) |
+ : super(mirror, 'property', mirror.simpleName, name, computeComment(mirror), |
+ lookupMdnComment), |
ref = _optionalReference(mirror.returnType), |
isStatic = _optionalBool(mirror.isStatic); |
} |
@@ -194,9 +263,10 @@ class MethodElement extends Element { |
final bool isOperator; |
final bool isStatic; |
- MethodElement(String name, MethodMirror mirror, [String kind = 'method']) |
+ MethodElement(String name, MethodMirror mirror, |
+ MdnComment lookupMdnComment(Mirror), [String kind = 'method']) |
: super(mirror, kind, name, '$name${mirror.parameters.length}()', |
- computeComment(mirror)), |
+ computeComment(mirror), lookupMdnComment), |
returnType = _optionalReference(mirror.returnType), |
isSetter = _optionalBool(mirror.isSetter), |
isOperator = _optionalBool(mirror.isOperator), |
@@ -214,13 +284,55 @@ class MethodElement extends Element { |
class ParameterElement extends Element { |
/** Type of the parameter. */ |
final Reference ref; |
- /** Whether the parameter is optional. */ |
+ |
+ /** |
+ * Returns the default value for this parameter. |
+ */ |
+ final String defaultValue; |
+ |
+ /** |
+ * Is this parameter optional? |
+ */ |
final bool isOptional; |
+ /** |
+ * Is this parameter named? |
+ */ |
+ final bool isNamed; |
+ |
+ /** |
+ * Returns the initialized field, if this parameter is an initializing formal. |
+ */ |
+ final Reference initializedField; |
+ |
ParameterElement(ParameterMirror mirror) |
- : super(mirror, 'param', mirror.simpleName, mirror.simpleName, null), |
+ : super(mirror, 'param', mirror.simpleName, mirror.simpleName, null, |
+ null), |
ref = _optionalReference(mirror.type), |
- isOptional = _optionalBool(mirror.isOptional) { |
+ isOptional = _optionalBool(mirror.isOptional), |
+ defaultValue = mirror.defaultValue, |
+ isNamed = _optionalBool(mirror.isNamed), |
+ initializedField = _optionalReference(mirror.initializedField) { |
+ |
+ if (mirror.type is FunctionTypeMirror) { |
+ addChild(new FunctionTypeElement(mirror.type)); |
+ } |
+ } |
+} |
+ |
+class FunctionTypeElement extends Element { |
+ final Reference returnType; |
+ |
+ FunctionTypeElement(FunctionTypeMirror mirror) |
+ : super(mirror, 'functiontype', mirror.simpleName, mirror.simpleName, null, null), |
+ returnType = _optionalReference(mirror.returnType) { |
+ for (var param in mirror.parameters) { |
+ addChild(new ParameterElement(param)); |
+ } |
+ // TODO(jacobr): can a FunctionTypeElement really have type variables? |
+ for (var typeVariable in mirror.originalDeclaration.typeVariables) { |
+ addChild(new TypeParameterElement(typeVariable)); |
+ } |
} |
} |
@@ -234,10 +346,11 @@ class TypeParameterElement extends Element { |
* In the following code sample, [:Bar:] is an upper bound: |
* [: class Bar<T extends Foo> { } :] |
*/ |
- Reference upperBound; |
+ final Reference upperBound; |
TypeParameterElement(TypeMirror mirror) |
- : super(mirror, 'typeparam', mirror.simpleName, mirror.simpleName, null), |
+ : super(mirror, 'typeparam', mirror.simpleName, mirror.simpleName, null, |
+ null), |
upperBound = mirror.upperBound != null && !mirror.upperBound.isObject ? |
new Reference(mirror.upperBound) : null; |
} |
@@ -253,8 +366,10 @@ class VariableElement extends Element { |
/** Whether the variable is final. */ |
final bool isFinal; |
- VariableElement(String name, VariableMirror mirror) |
- : super(mirror, 'variable', mirror.simpleName, name, null), |
+ VariableElement(String name, VariableMirror mirror, |
+ MdnComment lookupMdnComment(Mirror)) |
+ : super(mirror, 'variable', mirror.simpleName, name, |
+ computeComment(mirror), lookupMdnComment), |
ref = _optionalReference(mirror.type), |
isStatic = _optionalBool(mirror.isStatic), |
isFinal = _optionalBool(mirror.isFinal); |
@@ -270,7 +385,7 @@ class TypedefElement extends Element { |
TypedefElement(String name, TypedefMirror mirror) |
: super(mirror, 'typedef', mirror.simpleName, name, |
- computeComment(mirror)), |
+ computeComment(mirror), null), |
returnType = _optionalReference(mirror.value.returnType) { |
for (var param in mirror.value.parameters) { |
addChild(new ParameterElement(param)); |
@@ -301,9 +416,13 @@ class Reference { |
} |
} |
} |
+ |
+ // TODO(jacobr): compute the referenceId correctly for the general case so |
+ // that this method can work with all element types not just LibraryElements. |
+ Reference.fromElement(LibraryElement e) : name = e.name, refId = e.id; |
static String getId(Mirror mirror) { |
- String id = mirror.simpleName; |
+ String id = _escapeId(mirror.simpleName); |
if (mirror.owner != null) { |
id = '${getId(mirror.owner)}/$id'; |
} |