diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart
index 10cd8ea8a1..1b684d7fe1 100644
--- a/lib/dartdoc.dart
+++ b/lib/dartdoc.dart
@@ -14,14 +14,10 @@ import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source_io.dart';
-
-import 'src/css.dart';
-import 'src/helpers.dart';
-import 'src/html_gen.dart';
+import 'src/generator.dart';
import 'src/io_utils.dart';
+import 'src/model.dart';
import 'src/model_utils.dart';
-import 'src/package_utils.dart';
-import 'src/utils.dart';
const String DEFAULT_OUTPUT_DIRECTORY = 'docs';
@@ -31,11 +27,9 @@ class DartDoc {
List _excludes;
Directory _rootDir;
- final CSS css = new CSS();
- HtmlGenerator html;
Directory out;
Set libraries = new Set();
- Generator generator;
+ HtmlGenerator generator;
DartDoc(this._rootDir, this._excludes);
@@ -54,19 +48,16 @@ class DartDoc {
libs.sort(elementCompare);
libraries.addAll(libs);
- generator = new GeneratorHelper(libraries);
+
// create the out directory
out = new Directory(DEFAULT_OUTPUT_DIRECTORY);
if (!out.existsSync()) {
out.createSync(recursive: true);
}
+
+ generator = new HtmlGenerator(new Package(libraries, _rootDir.path), out);
// generate the docs
- html = new HtmlGenerator();
- generatePackage();
- libraries.forEach((lib) => generateLibrary(lib));
- // copy the css resource into 'out'
- File f = joinFile(new Directory(out.path), [css.getCssName()]);
- f.writeAsStringSync(css.getCssContent());
+ generator.generate();
double seconds = stopwatch.elapsedMilliseconds / 1000.0;
print('');
@@ -114,489 +105,6 @@ class DartDoc {
return new File(Platform.executable).parent.parent;
}
- void generatePackage() {
- var packageName = getPackageName(_rootDir.path);
- var packageDesc = getPackageDescription(_rootDir.path);
- var packageVersion = getPackageVersion(_rootDir.path);
- if (packageName.isNotEmpty) {
- File f = joinFile(new Directory(out.path), ['${packageName}_package.html']);
- print('generating ${f.path}');
- html = new HtmlGenerator();
- html.start(title: 'Package ${packageName}', cssRef: css.getCssName());
- generateHeader();
-
- html.startTag('div', attributes: "class='container'", newLine: false);
- html.writeln();
- html.startTag('div', attributes: "class='row'", newLine: false);
- html.writeln();
- html.startTag('div', attributes: "class='span3'");
- html.startTag('ul', attributes: 'class="nav nav-tabs nav-stacked left-nav"');
- html.startTag('li', attributes: 'class="active"', newLine: false);
- html.write(''
- ' '
- '${packageName}-${packageVersion}');
- html.endTag(); //li
- html.endTag(); //ul
- html.endTag();
- html.startTag('div', attributes: "class='span9'");
- html.tag('h1', contents: packageName);
- html.writeln('
');
- html.write(packageDesc);
- html.startTag('dl');
- html.startTag('h4');
- html.tag('dt', contents: 'Libraries');
- html.endTag();
- html.startTag('dd');
- for (LibraryElement lib in libraries) {
- html.writeln(' ${lib.name}
');
- }
- html.endTag();
- html.endTag(); // div.container
- generateFooter();
- html.end();
- f.writeAsStringSync(html.toString());
- }
-
- }
-
- void generateLibrary(LibraryElement library) {
- File f = joinFile(new Directory(out.path), [getFileNameFor(library)]);
- print('generating ${f.path}');
- html = new HtmlGenerator();
- html.start(title: 'Library ${library.name}', cssRef: css.getCssName());
-
- generateHeader();
-
- html.startTag('div', attributes: "class='container'", newLine: false);
- html.writeln();
- html.startTag('div', attributes: "class='row'", newLine: false);
- html.writeln();
-
- // left nav
- html.startTag('div', attributes: "class='span3'");
- html.startTag('ul', attributes: 'class="nav nav-tabs nav-stacked left-nav"');
- html.startTag('li', attributes: 'class="active"', newLine: false);
- html.write(''
- ' '
- '${library.name}');
- html.endTag(); // li
- html.endTag(); // ul.nav
- html.endTag(); // div.span3
-
- // main content
- html.startTag('div', attributes: "class='span9'");
-
- html.tag('h1', contents: library.name);
-
- if (!library.exportedLibraries.isEmpty) {
- html.startTag('p');
- html.write('exports ');
- for (int i = 0; i < library.exportedLibraries.length; i++) {
- if (i > 0) {
- html.write(', ');
- }
-
- LibraryElement lib = library.exportedLibraries[i];
- if (libraries.contains(lib)) {
- html.write('${lib.name}');
- } else {
- html.write(lib.name);
- }
- }
- html.endTag();
- }
-
- html.writeln('
');
-
- LibraryHelper lib = new LibraryHelper(library);
-
- html.startTag('dl', attributes: "class=dl-horizontal");
-
- List variables = lib.getVariables();
- List accessors = lib.getAccessors();
- List functions = lib.getFunctions();
- List typedefs = lib.getTypedefs();
- List types = lib.getTypes();
-
- createToc(variables);
- createToc(accessors);
- createToc(functions);
- createToc(typedefs);
- createToc(types);
-
- html.endTag(); // dl
-
- printComments(library);
-
- generateElements(variables);
- generateElements(accessors);
- generateElements(functions);
- generateElements(typedefs);
-
- types.forEach(generateClass);
-
- html.writeln('
');
-
- html.endTag(); // div.span9
-
- html.endTag(); // div.row
-
- html.endTag(); // div.container
-
- generateFooter();
-
- html.end();
-
- // write the file contents
- f.writeAsStringSync(html.toString());
- }
-
- void generateHeader() {
- // header
- html.startTag('header');
- html.endTag();
- }
-
- void generateFooter() {
- // footer
- html.startTag('footer');
-// html.startTag('div', 'class="navbar navbar-fixed-bottom"');
-// html.startTag('div', 'class="navbar-inner"');
-// html.startTag('div', 'class="container" style="width: auto; padding: 0 20px;"');
-// html.tag('a', 'Title'); //Title
-// html.startTag('ul', 'class="nav"');
-// html.tag('li', 'Link');
-// html.endTag();
-// html.endTag();
-// html.endTag();
-// html.endTag();
- html.endTag();
- }
-
- void createToc(List elements) {
- if (!elements.isEmpty) {
- html.tag('dt', contents: elements[0].typeName);
- html.startTag('dd');
- for (ElementHelper e in elements) {
- html.writeln('${createIconFor(e.element)}${e.createLinkedSummary(generator)}
');
- }
- html.endTag();
- }
- }
-
- String getFileNameFor(LibraryElement library) {
- return '${library.name}.html';
- }
-
- void generateElements(List elements, [bool header = true]) {
- if (!elements.isEmpty) {
- html.tag('h4', contents: elements[0].typeName);
- if (header) {
- html.startTag('div', attributes: "class=indent");
- }
- elements.forEach(generateElement);
- if (header) {
- html.endTag();
- }
- }
- }
-
- void generateAnnotations(List annotations) {
- if (!annotations.isEmpty) {
- html.write(' ');
- for (ElementAnnotation a in annotations) {
- Element e = a.element;
- // TODO: I don't believe we get back the right elements for const
- // ctor annotations
- html.writeln('@${e.name} ');
- }
- html.writeln('
');
- }
- }
-
- void generateElement(ElementHelper f) {
- html.startTag('b', newLine: false);
- html.write('${createAnchor(f.element)}');
- generateAnnotations(f.element.metadata);
- html.write(createIconFor(f.element));
- if (f.element is MethodElement) {
- html.write(generateOverrideIcon(f.element as MethodElement));
- }
- html.write(f.createLinkedDescription(generator));
- html.endTag();
- printComments(f.element);
- }
-
- String createIconFor(Element e) {
- if (e is PropertyAccessorElement) {
- PropertyAccessorElement a = e;
-
- if (a.isGetter) {
- return ' ';
- } else {
- return ' ';
- }
- } else if (e is ClassElement) {
- return ' ';
- } else if (e is FunctionTypeAliasElement) {
- return ' ';
- } else if (e is PropertyInducingElement) {
- return ' ';
- } else if (e is ConstructorElement) {
- return ' ';
- } else if (e is ExecutableElement) {
- return ' ';
- } else {
- return '';
- }
- }
-
- String generateOverrideIcon(MethodElement element) {
- Element o = getOverriddenElement(element);
-
- if (o == null) {
- return '';
- } else if (!generator.isDocumented(o)) {
- return " ";
- } else {
- return "" " ";
- }
- }
-
- String getNameFor(Element e) {
- ClassElement c = getEnclosingElement(e);
- // TODO: upscale this! handle ctors
- String ext = (e is ExecutableElement) ? '()' : '';
- return '${c.name}.${htmlEscape(e.name)}${ext}';
- }
-
- void generateClass(ClassHelper helper) {
- ClassElement c = helper.element;
- html.write(createAnchor(c));
- html.writeln('
');
- html.startTag('h4');
- generateAnnotations(c.metadata);
- html.write(createIconFor(c));
- if (c.isAbstract) {
- html.write('Abstract class ${c.name}');
- } else {
- html.write('Class ${c.name}');
- }
- if (c.supertype != null && c.supertype.element.supertype != null) {
- html.write(' extends ${generator.createLinkedTypeName(c.supertype)}');
- }
- if (!c.mixins.isEmpty) {
- html.write(' with');
- for (int i = 0; i < c.mixins.length; i++) {
- if (i == 0) {
- html.write(' ');
- } else {
- html.write(', ');
- }
- html.write(generator.createLinkedTypeName(c.mixins[i]));
- }
- }
-
- if (!c.interfaces.isEmpty) {
- html.write(' implements');
- for (int i = 0; i < c.interfaces.length; i++) {
- if (i == 0) {
- html.write(' ');
- } else {
- html.write(', ');
- }
- html.write(generator.createLinkedTypeName(c.interfaces[i]));
- }
- }
-
- html.endTag();
-
- html.startTag('dl', attributes: 'class=dl-horizontal');
- createToc(helper.getStaticFields());
- createToc(helper.getInstanceFields());
- createToc(helper.getAccessors());
- createToc(helper.getCtors());
- createToc(helper.getMethods());
- html.endTag();
-
- printComments(c);
-
- generateElements(helper.getStaticFields(), false);
- generateElements(helper.getInstanceFields(), false);
- generateElements(helper.getAccessors(), false);
- generateElements(helper.getCtors(), false);
- generateElements(helper.getMethods(), false);
- }
-
- void printComments(Element e, [bool indent = true]) {
- String comments = getDocumentationFor(e);
- if (comments != null) {
- if (indent) {
- html.startTag('div', attributes: "class=indent");
- }
- html.tag('p', contents: prettifyDocs(new Resolver(generator, e), comments));
- if (indent) {
- html.endTag();
- }
- } else {
- if (indent) {
- html.tag('div', attributes: "class=indent");
- }
- }
- }
-}
-
-class Resolver extends CodeResolver {
- Generator generator;
- Element element;
-
- Resolver(this.generator, this.element);
-
- String resolveCodeReference(String reference) {
- Element e = (element as ElementImpl).getChild(reference);
-
- if (e is LocalElement /*|| e is TypeVariableElement*/) {
- e = null;
- }
- if (e != null) {
- return generator.createLinkedName(e, true);
- } else {
- //return "$reference";
- return "$reference
";
- }
- }
-}
-
-class GeneratorHelper implements Generator {
-
- Set libraries;
-
- GeneratorHelper(this.libraries);
-
- bool isDocumented(Element e) {
- return libraries.contains(e.library);
- }
-
-
- String createLinkedName(Element e, [bool appendParens = false]) {
- if (e == null) {
- return '';
- }
- if (!isDocumented(e)) {
- return htmlEscape(e.name);
- }
- if (e.name.startsWith('_')) {
- return htmlEscape(e.name);
- }
- ClassElement c = getEnclosingElement(e);
- if (c != null && c.name.startsWith('_')) {
- return '${c.name}.${htmlEscape(e.name)}';
- }
- if (c != null && e is ConstructorElement) {
- String name;
- if (e.name.isEmpty) {
- name = c.name;
- } else {
- name = '${c.name}.${htmlEscape(e.name)}';
- }
- if (appendParens) {
- return "${name}()";
- } else {
- return "${name}";
- }
- } else {
- String append = '';
-
- if (appendParens && (e is MethodElement || e is FunctionElement)) {
- append = '()';
- }
- return "${htmlEscape(e.name)}$append";
- }
- }
-
- String createLinkedTypeName(DartType type) {
- StringBuffer buf = new StringBuffer();
-
- if (type is TypeParameterType) {
- buf.write(type.element.name);
- } else {
- buf.write(createLinkedName(type.element));
- }
-
- if (type is ParameterizedType) {
- ParameterizedType pType = type;
-
- if (!pType.typeArguments.isEmpty) {
- buf.write('<');
- for (int i = 0; i < pType.typeArguments.length; i++) {
- if (i > 0) {
- buf.write(', ');
- }
- DartType t = pType.typeArguments[i];
- buf.write(createLinkedTypeName(t));
- }
- buf.write('>');
- }
- }
- return buf.toString();
- }
-
- String createLinkedReturnTypeName(FunctionType type) {
- if (type.returnType.element == null) {
- if (type.returnType.name != null) {
- return type.returnType.name;
- } else {
- return '';
- }
- } else {
- return createLinkedTypeName(type.returnType);
- }
- }
-
- String printParams(List params) {
- StringBuffer buf = new StringBuffer();
-
- for (ParameterElement p in params) {
- if (buf.length > 0) {
- buf.write(', ');
- }
-
- if (p.type != null && p.type.name != null) {
- buf.write(createLinkedTypeName(p.type));
- buf.write(' ');
- }
-
- buf.write(p.name);
- }
-
- return buf.toString();
- }
-
- String createHrefFor(Element e) {
- if (!isDocumented(e)) {
- return '';
- }
-
- ClassElement c = getEnclosingElement(e);
-
- if (c != null) {
- return '${getFileNameFor(e.library)}#${c.name}.${escapeBrackets(e.name)}';
- } else {
- return '${getFileNameFor(e.library)}#${e.name}';
- }
- }
-
-
}
-
-String createAnchor(Element e) {
- ClassElement c = getEnclosingElement(e);
-
- if (c != null) {
- return '';
- } else {
- return '';
- }
-}
diff --git a/lib/src/css.dart b/lib/src/css.dart
index 68053e0498..383a9d1309 100644
--- a/lib/src/css.dart
+++ b/lib/src/css.dart
@@ -1,3 +1,6 @@
+// Copyright (c) 2014, 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.
library css;
diff --git a/lib/src/generator.dart b/lib/src/generator.dart
new file mode 100644
index 0000000000..d02200e2af
--- /dev/null
+++ b/lib/src/generator.dart
@@ -0,0 +1,539 @@
+// Copyright (c) 2014, 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.
+
+library dartdoc.generator;
+
+import 'dart:io';
+
+import 'css.dart';
+import 'html_gen.dart';
+import 'html_utils.dart';
+import 'io_utils.dart';
+import 'model.dart';
+
+/// Generates the HTML files
+class HtmlGenerator {
+
+ Directory out;
+ Package package;
+ HtmlHelper html = new HtmlHelper();
+ CSS css = new CSS();
+ HtmlGeneratorHelper helper;
+
+ HtmlGenerator(this.package, this.out) {
+ helper = new HtmlGeneratorHelper(package);
+ }
+
+ void generate() {
+ generatePackage();
+ package.libraries.forEach((lib) => generateLibrary(lib));
+ // copy the css resource into 'out'
+ File f = joinFile(new Directory(out.path), [css.getCssName()]);
+ f.writeAsStringSync(css.getCssContent());
+ }
+
+ void generatePackage() {
+ var packageName = package.name;
+ var packageDesc = package.description;
+ var packageVersion = package.version;
+ if (packageName.isNotEmpty) {
+ File f = joinFile(new Directory(out.path), ['${packageName}_package.html']);
+ print('generating ${f.path}');
+
+ html.start(title: 'Package ${packageName}', cssRef: css.getCssName());
+ html.generateHeader();
+ html.startTag('div', attributes: "class='container'", newLine: false);
+ html.writeln();
+ html.startTag('div', attributes: "class='row'", newLine: false);
+ html.writeln();
+ html.startTag('div', attributes: "class='span3'");
+ html.startTag('ul', attributes: 'class="nav nav-tabs nav-stacked left-nav"');
+ html.startTag('li', attributes: 'class="active"', newLine: false);
+ html.write('' ' ' '${packageName}-${packageVersion}');
+ html.endTag(); //li
+ html.endTag(); //ul
+ html.endTag();
+ html.startTag('div', attributes: "class='span9'");
+ html.tag('h1', contents: packageName);
+ html.writeln('
');
+ html.write(packageDesc);
+ html.startTag('dl');
+ html.startTag('h4');
+ html.tag('dt', contents: 'Libraries');
+ html.endTag();
+ html.startTag('dd');
+ for (Library lib in package.libraries) {
+ html.writeln(' ${lib.name}
');
+ }
+ html.endTag();
+ html.endTag(); // div.container
+ html.generateFooter();
+ html.end();
+ f.writeAsStringSync(html.toString());
+ }
+ }
+
+ void generateLibrary(Library library) {
+ File f = joinFile(new Directory(out.path), [_getFileNameFor(library)]);
+ print('generating ${f.path}');
+ html = new HtmlHelper();
+ html.start(title: 'Library ${library.name}', cssRef: css.getCssName());
+
+ html.generateHeader();
+
+ html.startTag('div', attributes: "class='container'", newLine: false);
+ html.writeln();
+ html.startTag('div', attributes: "class='row'", newLine: false);
+ html.writeln();
+
+ // left nav
+ html.startTag('div', attributes: "class='span3'");
+ html.startTag('ul', attributes: 'class="nav nav-tabs nav-stacked left-nav"');
+ html.startTag('li', attributes: 'class="active"', newLine: false);
+ html.write('' ' ' '${library.name}');
+ html.endTag(); // li
+ html.endTag(); // ul.nav
+ html.endTag(); // div.span3
+
+ // main content
+ html.startTag('div', attributes: "class='span9'");
+
+ html.tag('h1', contents: library.name);
+
+ if (!library.exported.isEmpty) {
+ html.startTag('p');
+ html.write('exports ');
+ for (int i = 0; i < library.exported.length; i++) {
+ if (i > 0) {
+ html.write(', ');
+ }
+
+ Library lib = library.exported[i];
+ if (package.libraries.contains(lib)) {
+ html.write('${lib.name}');
+ } else {
+ html.write(lib.name);
+ }
+ }
+ html.endTag();
+ }
+
+ html.writeln('
');
+
+ html.startTag('dl', attributes: "class=dl-horizontal");
+
+ List variables = library.getVariables();
+ List accessors = library.getAccessors();
+ List functions = library.getFunctions();
+ List typedefs = library.getTypedefs();
+ List types = library.getTypes();
+
+ createToc(variables);
+ createToc(accessors);
+ createToc(functions);
+ createToc(typedefs);
+ createToc(types);
+
+ html.endTag(); // dl
+
+ printComments(library);
+
+ generateElements(variables);
+ generateElements(accessors);
+ generateElements(functions);
+ generateElements(typedefs);
+
+ types.forEach(generateClass);
+
+ html.writeln('
');
+
+ html.endTag(); // div.span9
+
+ html.endTag(); // div.row
+
+ html.endTag(); // div.container
+
+ html.generateFooter();
+
+ html.end();
+
+ // write the file contents
+ f.writeAsStringSync(html.toString());
+ }
+
+ void createToc(List elements) {
+ if (!elements.isEmpty) {
+ html.tag('dt', contents: elements[0].typeName);
+ html.startTag('dd');
+ for (ModelElement e in elements) {
+ html.writeln('${createIconFor(e)}${e.createLinkedSummary(helper)}
');
+ }
+ html.endTag();
+ }
+ }
+
+ void generateClass(Class cls) {
+
+ html.write(createAnchor(cls));
+ html.writeln('
');
+ html.startTag('h4');
+ generateAnnotations(cls.getAnnotations());
+ html.write(createIconFor(cls));
+ if (cls.isAbstract) {
+ html.write('Abstract class ${cls.name}');
+ } else {
+ html.write('Class ${cls.name}');
+ }
+ if (cls.hasSupertype) {
+ html.write(' extends ${helper.createLinkedTypeName(cls.supertype)}');
+ }
+ if (!cls.mixins.isEmpty) {
+ html.write(' with');
+ for (int i = 0; i < cls.mixins.length; i++) {
+ if (i == 0) {
+ html.write(' ');
+ } else {
+ html.write(', ');
+ }
+ html.write(helper.createLinkedTypeName(cls.mixins[i]));
+ }
+ }
+
+ if (!cls.interfaces.isEmpty) {
+ html.write(' implements');
+ for (int i = 0; i < cls.interfaces.length; i++) {
+ if (i == 0) {
+ html.write(' ');
+ } else {
+ html.write(', ');
+ }
+ html.write(helper.createLinkedTypeName(cls.interfaces[i]));
+ }
+ }
+
+ html.endTag();
+
+ html.startTag('dl', attributes: 'class=dl-horizontal');
+ createToc(cls.getStaticFields());
+ createToc(cls.getInstanceFields());
+ createToc(cls.getAccessors());
+ createToc(cls.getCtors());
+ createToc(cls.getMethods());
+ html.endTag();
+
+ printComments(cls);
+
+ generateElements(cls.getStaticFields(), false);
+ generateElements(cls.getInstanceFields(), false);
+ generateElements(cls.getAccessors(), false);
+ generateElements(cls.getCtors(), false);
+ generateElements(cls.getMethods(), false);
+ }
+
+
+ void printComments(ModelElement e, [bool indent = true]) {
+ String comments = e.getDocumentation();
+ if (comments != null) {
+ if (indent) {
+ html.startTag('div', attributes: "class=indent");
+ }
+ html.tag('p', contents: cleanupDocs(e, comments));
+ if (indent) {
+ html.endTag();
+ }
+ } else {
+ if (indent) {
+ html.tag('div', attributes: "class=indent");
+ }
+ }
+ }
+
+
+ void generateElements(List elements, [bool header = true]) {
+ if (!elements.isEmpty) {
+ html.tag('h4', contents: elements[0].typeName);
+ if (header) {
+ html.startTag('div', attributes: "class=indent");
+ }
+ elements.forEach(generateElement);
+ if (header) {
+ html.endTag();
+ }
+ }
+ }
+
+ void generateElement(ModelElement f) {
+ html.startTag('b', newLine: false);
+ html.write('${createAnchor(f)}');
+ generateAnnotations(f.getAnnotations());
+ html.write(createIconFor(f));
+ if (f is Method) {
+ html.write(generateOverrideIcon(f));
+ }
+ html.write(f.createLinkedDescription(helper));
+ html.endTag();
+ printComments(f);
+ }
+
+ void generateAnnotations(List annotations) {
+ if (!annotations.isEmpty) {
+ html.write(' ');
+ for (String a in annotations) {
+ // TODO: I don't believe we get back the right elements for const
+ // ctor annotations
+ html.writeln('@${a} ');
+ }
+ html.writeln('
');
+ }
+ }
+
+ String generateOverrideIcon(Method method) {
+ ModelElement o = method.getOverriddenElement();
+ if (o == null) {
+ return '';
+ } else if (!package.isDocumented(o)) {
+ return " ";
+ } else {
+ return "" " ";
+ }
+ }
+
+ String getNameFor(ModelElement e) {
+ Class c = e.getEnclosingElement();
+ // TODO: upscale this! handle ctors
+ String ext = (e.isExecutable) ? '()' : '';
+ return '${c.name}.${htmlEscape(e.name)}${ext}';
+ }
+
+ String createAnchor(ModelElement e) {
+ Class c = e.getEnclosingElement();
+
+ if (c != null) {
+ return '';
+ } else {
+ return '';
+ }
+ }
+
+ String createIconFor(ModelElement e) {
+ if (e.isPropertyAccessor) {
+ Accessor a = (e as Accessor);
+ if (a.isGetter) {
+ return ' ';
+ } else {
+ return ' ';
+ }
+ } else if (e is Class) {
+ return ' ';
+ } else if (e is Function) {
+ return ' ';
+ } else if (e.isPropertyInducer) {
+ return ' ';
+ } else if (e is Constructor) {
+ return ' ';
+ } else if (e.isExecutable) {
+ return ' ';
+ } else {
+ return '';
+ }
+ }
+
+ String cleanupDocs(ModelElement e, String docs) {
+ if (docs == null) {
+ return '';
+ }
+ docs = htmlEscape(docs);
+ docs = stripComments(docs);
+ StringBuffer buf = new StringBuffer();
+
+ bool inCode = false;
+ bool inList = false;
+ for (String line in docs.split('\n')) {
+ if (inList && !line.startsWith("* ")) {
+ inList = false;
+ buf.write('');
+ }
+ if (inCode && !(line.startsWith(' ') || line.trim().isEmpty)) {
+ inCode = false;
+ buf.write('');
+ } else if (line.startsWith(' ') && !inCode) {
+ inCode = true;
+ buf.write('');
+ } else if (line.trim().startsWith('* ') && !inList) {
+ inList = true;
+ buf.write('
');
+ }
+ if (inCode) {
+ if (line.startsWith(' ')) {
+ buf.write('${line.substring(4)}\n');
+ } else {
+ buf.write('${line}\n');
+ }
+ } else if (inList) {
+ buf.write('- ${_cleanupMarkdown(e, line.trim().substring(2))}
');
+ } else if (line.trim().length == 0) {
+ buf.write('
\n');
+ } else {
+ buf.write('${_cleanupMarkdown(e, line)} ');
+ }
+ }
+ if (inCode) {
+ buf.write('');
+ }
+ return buf.toString().replaceAll('\n\n', '\n').trim();
+ }
+
+ String _cleanupMarkdown(ModelElement e, String line) {
+ line = ltrim(line);
+ if (line.startsWith("##")) {
+ line = line.substring(2);
+ if (line.endsWith("##")) {
+ line = line.substring(0, line.length - 2);
+ }
+ line = "
$line
";
+ } else {
+ line = replaceAll(line, ['[:', ':]'], htmlEntity: 'code');
+ line = replaceAll(line, ['`', '`'], htmlEntity: 'code');
+ line = replaceAll(line, ['*', '*'], htmlEntity: 'i');
+ line = replaceAll(line, ['__', '__'], htmlEntity: 'b');
+ line = replaceAll(line, ['[', ']'], replaceFunction: (String ref) {
+ return _resolveCodeReference(e, ref);
+ });
+ }
+ return line;
+ }
+
+ String _resolveCodeReference(ModelElement e, String reference) {
+ ModelElement element = e.getChild(reference);
+
+ if (element.isLocalElement) {
+ element = null;
+ }
+ if (element != null) {
+ return helper.createLinkedName(element, true);
+ } else {
+ //return "$reference";
+ return "$reference
";
+ }
+ }
+
+
+}
+
+String _getFileNameFor(Library library) {
+ return '${library.name}.html';
+}
+
+
+class HtmlGeneratorHelper extends Helper {
+
+ Package package;
+
+ HtmlGeneratorHelper(this.package);
+
+ String createLinkedName(ModelElement e, [bool appendParens = false]) {
+ if (e == null) {
+ return '';
+ }
+ if (!package.isDocumented(e)) {
+ return htmlEscape(e.name);
+ }
+ if (e.name.startsWith('_')) {
+ return htmlEscape(e.name);
+ }
+ Class c = e.getEnclosingElement();
+ if (c != null && c.name.startsWith('_')) {
+ return '${c.name}.${htmlEscape(e.name)}';
+ }
+ if (c != null && e is Constructor) {
+ String name;
+ if (e.name.isEmpty) {
+ name = c.name;
+ } else {
+ name = '${c.name}.${htmlEscape(e.name)}';
+ }
+ if (appendParens) {
+ return "${name}()";
+ } else {
+ return "${name}";
+ }
+ } else {
+ String append = '';
+
+ if (appendParens && (e is Method || e is Fnction)) {
+ append = '()';
+ }
+ return "${htmlEscape(e.name)}$append";
+ }
+ }
+
+ String createHrefFor(ModelElement e) {
+ if (!package.isDocumented(e)) {
+ return '';
+ }
+ Class c = e.getEnclosingElement();
+ if (c != null) {
+ return '${_getFileNameFor(e.library)}#${c.name}.${escapeBrackets(e.name)}';
+ } else {
+ return '${_getFileNameFor(e.library)}#${e.name}';
+ }
+ }
+
+ String printParams(List params) {
+ StringBuffer buf = new StringBuffer();
+
+ for (Parameter p in params) {
+ if (buf.length > 0) {
+ buf.write(', ');
+ }
+ if (p.type != null && p.type.name != null) {
+ buf.write(createLinkedTypeName(p.type));
+ buf.write(' ');
+ }
+ buf.write(p.name);
+ }
+ return buf.toString();
+ }
+
+ String createLinkedTypeName(ElementType type) {
+ StringBuffer buf = new StringBuffer();
+
+ if (type.isParameterType) {
+ buf.write(type.element.name);
+ } else {
+ buf.write(createLinkedName(type.element));
+ }
+
+ if (type.isParameterizedType) {
+ if (!type.typeArguments.isEmpty) {
+ buf.write('<');
+ for (int i = 0; i < type.typeArguments.length; i++) {
+ if (i > 0) {
+ buf.write(', ');
+ }
+ ElementType t = type.typeArguments[i];
+ buf.write(createLinkedTypeName(t));
+ }
+ buf.write('>');
+ }
+ }
+ return buf.toString();
+ }
+
+
+ String createLinkedReturnTypeName(ElementType type) {
+ if (type.returnElement == null) {
+ if (type.returnTypeName != null) {
+ return type.returnTypeName;
+ } else {
+ return '';
+ }
+ } else {
+ return createLinkedTypeName(type.returnType);
+ }
+ }
+}
+
+
+
diff --git a/lib/src/helpers.dart b/lib/src/helpers.dart
deleted file mode 100644
index c1bb460879..0000000000
--- a/lib/src/helpers.dart
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright (c) 2014, 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.
-
-library dartdoc.helpers;
-
-import 'package:analyzer/src/generated/element.dart';
-
-import 'model_utils.dart';
-import 'utils.dart';
-
-class LibraryHelper {
- LibraryElement library;
-
- LibraryHelper(this.library);
-
- List getVariables() {
- List variables = [];
-
- variables.addAll(library.definingCompilationUnit.topLevelVariables);
- for (CompilationUnitElement cu in library.parts) {
- variables.addAll(cu.topLevelVariables);
- }
-
- variables
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
-
- return variables.map((e) => new VariableHelper(e)).toList();
- }
-
- List getAccessors() {
- List accessors = [];
-
- accessors.addAll(library.definingCompilationUnit.accessors);
- for (CompilationUnitElement cu in library.parts) {
- accessors.addAll(cu.accessors);
- }
-
- accessors
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
- accessors.removeWhere((e) => e.isSynthetic);
-
- return accessors.map((e) => new AccessorHelper(e)).toList();
- }
-
- List getTypedefs() {
- List functions = [];
-
- functions.addAll(library.definingCompilationUnit.functionTypeAliases);
- for (CompilationUnitElement cu in library.parts) {
- functions.addAll(cu.functionTypeAliases);
- }
-
- functions
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
-
- return functions.map((e) => new TypedefHelper(e)).toList();
- }
-
- List getFunctions() {
- List functions = [];
-
- functions.addAll(library.definingCompilationUnit.functions);
- for (CompilationUnitElement cu in library.parts) {
- functions.addAll(cu.functions);
- }
-
- functions
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
-
- return functions.map((e) => new FunctionHelper(e)).toList();
- }
-
- List getTypes() {
- List types = [];
-
- types.addAll(library.definingCompilationUnit.types);
- for (CompilationUnitElement cu in library.parts) {
- types.addAll(cu.types);
- }
-
- types
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
-
- return types.map((e) => new ClassHelper(e)).toList();
- }
-}
-
-abstract class ElementHelper {
- Element element;
-
- ElementHelper(this.element);
-
- String get typeName;
-
- String createLinkedSummary(Generator generator) {
- return generator.createLinkedName(element);
- }
-
- String createLinkedDescription(Generator generator);
-}
-
-class ClassHelper extends ElementHelper {
-
- ClassHelper(ClassElement element) : super(element);
-
- String get typeName => 'Classes';
-
- ClassElement get _cls => element as ClassElement;
-
- String createLinkedDescription(Generator generator) {
- return '';
- }
-
- List _getAllfields() {
- return _cls.fields.toList()
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
- }
-
- List getStaticFields() {
- List fields = _getAllfields()..removeWhere((e) => !isStatic(e));
- return fields.map((e) => new StaticFieldHelper(e)).toList();
- }
-
- List getInstanceFields() {
- List fields = _getAllfields()..removeWhere(isStatic);
- return fields.map((e) => new FieldHelper(e)).toList();
- }
-
- List getAccessors() {
- List accessors = _cls.accessors.toList()
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
- accessors.removeWhere((e) => e.isSynthetic);
- return accessors.map((e) => new AccessorHelper(e)).toList();
- }
-
- List getCtors() {
- List c = _cls.constructors.toList()
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
- return c.map((e) => new ConstructorHelper(e)).toList();
- }
-
- List getMethods() {
- List m = _cls.methods.toList()
- ..removeWhere(isPrivate)
- ..sort(elementCompare);
- return m.map((e) => new MethodHelper(e)).toList();
- }
-}
-
-abstract class PropertyInducingHelper extends ElementHelper {
- PropertyInducingHelper(PropertyInducingElement element) : super(element);
-
- PropertyInducingElement get _var => (element as PropertyInducingElement);
-
- String createLinkedSummary(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- buf.write('${generator.createLinkedName(_var)}');
-
- String type = generator.createLinkedName(_var.type == null ? null : _var.type.element);
-
- if (!type.isEmpty) {
- buf.write(': $type');
- }
-
- return buf.toString();
- }
-
- String createLinkedDescription(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_var.isStatic) {
- buf.write('static ');
- }
- if (_var.isFinal) {
- buf.write('final ');
- }
- if (_var.isConst) {
- buf.write('const ');
- }
-
- buf.write(generator.createLinkedName(_var.type == null ? null : _var.type.element));
- buf.write(' ${_var.name}');
-
- // write out any constant value
- Object value = getConstantValue(_var);
-
- if (value != null) {
- if (value is String) {
- String str = stringEscape(value, "'");
- buf.write(" = '${str}'");
- } else if (value is num) {
- buf.write(" = ${value}");
- }
- //NumberFormat.decimalPattern
- }
-
- return buf.toString();
- }
-}
-
-class VariableHelper extends PropertyInducingHelper {
- VariableHelper(TopLevelVariableElement element) : super(element);
-
- String get typeName => 'Top-Level Variables';
-}
-
-class FieldHelper extends PropertyInducingHelper {
- FieldHelper(FieldElement element) : super(element);
-
- String get typeName => 'Fields';
-}
-
-class StaticFieldHelper extends PropertyInducingHelper {
- StaticFieldHelper(FieldElement element) : super(element);
-
- String get typeName => 'Static Fields';
-}
-
-class AccessorHelper extends ElementHelper {
- AccessorHelper(PropertyAccessorElement element) : super(element);
-
- String get typeName => 'Getters and Setters';
-
- PropertyAccessorElement get _acc => (element as PropertyAccessorElement);
-
- String createLinkedSummary(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_acc.isGetter) {
- buf.write(generator.createLinkedName(element));
- buf.write(': ');
- buf.write(generator.createLinkedReturnTypeName(_acc.type));
- } else {
- buf.write('${generator.createLinkedName(element)}(' '${generator.printParams(_acc.parameters)})');
- }
-
- return buf.toString();
- }
-
- String createLinkedDescription(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_acc.isStatic) {
- buf.write('static ');
- }
-
- if (_acc.isGetter) {
- buf.write('${generator.createLinkedReturnTypeName(_acc.type)} get ${_acc.name}');
- } else {
- buf.write('set ${_acc.name}(${generator.printParams(_acc.parameters)})');
- }
-
- return buf.toString();
- }
-}
-
-class FunctionHelper extends ElementHelper {
- FunctionHelper(FunctionElement element) : super(element);
-
- String get typeName => 'Functions';
-
- FunctionElement get _func => (element as FunctionElement);
-
- String createLinkedSummary(Generator generator) {
- String retType = generator.createLinkedReturnTypeName(_func.type);
-
- return '${generator.createLinkedName(element)}' '(${generator.printParams(_func.parameters)})' '${retType.isEmpty ? '' : ': $retType'}';
- }
-
- String createLinkedDescription(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_func.isStatic) {
- buf.write('static ');
- }
-
- buf.write(generator.createLinkedReturnTypeName(_func.type));
- buf.write(' ${_func.name}(${generator.printParams(_func.parameters)})');
-
- return buf.toString();
- }
-}
-
-class TypedefHelper extends ElementHelper {
- TypedefHelper(FunctionTypeAliasElement element) : super(element);
-
- String get typeName => 'Typedefs';
-
- FunctionTypeAliasElement get _typedef => (element as FunctionTypeAliasElement);
-
- String createLinkedSummary(Generator generator) {
- // Comparator(T a, T b): int
- StringBuffer buf = new StringBuffer();
-
- buf.write(generator.createLinkedName(element));
- if (!_typedef.typeParameters.isEmpty) {
- buf.write('<');
- for (int i = 0; i < _typedef.typeParameters.length; i++) {
- if (i > 0) {
- buf.write(', ');
- }
- buf.write(_typedef.typeParameters[i].name);
- }
- buf.write('>');
- }
- buf.write('(${generator.printParams(_typedef.parameters)}): ');
- buf.write(generator.createLinkedReturnTypeName(_typedef.type));
-
- return buf.toString();
- }
-
- String createLinkedDescription(Generator generator) {
- // typedef int Comparator(T a, T b)
-
- StringBuffer buf = new StringBuffer();
-
- buf.write('typedef ${generator.createLinkedReturnTypeName(_typedef.type)} ${_typedef.name}');
- if (!_typedef.typeParameters.isEmpty) {
- buf.write('<');
- for (int i = 0; i < _typedef.typeParameters.length; i++) {
- if (i > 0) {
- buf.write(', ');
- }
- buf.write(_typedef.typeParameters[i].name);
- }
- buf.write('>');
- }
- buf.write('(${generator.printParams(_typedef.parameters)}): ');
-
- return buf.toString();
- }
-}
-
-abstract class ExecutableHelper extends ElementHelper {
- ExecutableHelper(ExecutableElement element) : super(element);
-
- ExecutableElement get _ex => (element as ExecutableElement);
-
- String createLinkedSummary(Generator generator) {
- String retType = generator.createLinkedReturnTypeName(_ex.type);
-
- return '${generator.createLinkedName(element)}' '(${generator.printParams(_ex.parameters)})' '${retType.isEmpty ? '' : ': $retType'}';
- }
-
- String createLinkedDescription(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_ex.isStatic) {
- buf.write('static ');
- }
-
- buf.write(generator.createLinkedReturnTypeName(_ex.type));
- buf.write(' ${_ex.name}(${generator.printParams(_ex.parameters)})');
-
- return buf.toString();
- }
-}
-
-class ConstructorHelper extends ExecutableHelper {
- ConstructorHelper(ConstructorElement element) : super(element);
-
- String get typeName => 'Constructors';
-
- ConstructorElement get _ctor => (element as ConstructorElement);
-
- String createLinkedSummary(Generator generator) {
- return '${generator.createLinkedName(element)}' '(${generator.printParams(_ex.parameters)})';
- }
-
- String createLinkedDescription(Generator generator) {
- StringBuffer buf = new StringBuffer();
-
- if (_ex.isStatic) {
- buf.write('static ');
- }
- if (_ctor.isFactory) {
- buf.write('factory ');
- }
-
- buf.write('${_ctor.type.returnType.name}${_ctor.name.isEmpty?'':'.'}' '${_ctor.name}(${generator.printParams(_ex.parameters)})');
-
- return buf.toString();
- }
-}
-
-class MethodHelper extends ExecutableHelper {
- MethodHelper(MethodElement element) : super(element);
-
- String get typeName => 'Methods';
-}
-
-bool isStatic(PropertyInducingElement e) => e.isStatic;
-
-bool isPrivate(Element e) => e.name.startsWith('_');
-
-int elementCompare(Element a, Element b) => a.name.compareTo(b.name);
-
-abstract class Generator {
- String createLinkedName(Element e, [bool appendParens = false]);
- String createLinkedReturnTypeName(FunctionType type);
- String createLinkedTypeName(DartType type);
- String printParams(List params);
- String createHrefFor(Element e);
- bool isDocumented(Element e);
-}
diff --git a/lib/src/html_gen.dart b/lib/src/html_gen.dart
index ff2a0d1bb6..1b3aadb69c 100644
--- a/lib/src/html_gen.dart
+++ b/lib/src/html_gen.dart
@@ -4,41 +4,48 @@
library html_gen;
-class HtmlGenerator {
+class HtmlHelper {
StringBuffer buffer = new StringBuffer();
bool startOfLine = true;
List tags = [];
List indents = [];
String indent = '';
- HtmlGenerator() {
+ HtmlHelper() {
writeln('');
writeln();
writeln('');
writeln();
}
+ void generateHeader() {
+ // header
+ startTag('header');
+ endTag();
+ }
+
+ void generateFooter() {
+ // footer
+ startTag('footer');
+ endTag();
+ }
+
+
void start({String title, String cssRef}) {
startTag('html', newLine: false);
writeln();
startTag('head');
-
writeln('');
writeln('');
-
if (title != null) {
writeln('${title}');
}
-
if (cssRef != null) {
writeln('');
}
-
// head
endTag();
-
writeln();
-
startTag('body', newLine: false);
writeln();
}
@@ -92,7 +99,6 @@ class HtmlGenerator {
void end() {
// body
endTag();
-
// html
endTag();
}
diff --git a/lib/src/utils.dart b/lib/src/html_utils.dart
similarity index 90%
rename from lib/src/utils.dart
rename to lib/src/html_utils.dart
index bb889b77ad..dc1a01d88c 100644
--- a/lib/src/utils.dart
+++ b/lib/src/html_utils.dart
@@ -2,7 +2,7 @@
// 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.
-library dartdoc.utils;
+library dartdoc.html_utils;
String htmlEscape(String text) {
return text.replaceAll('&', '&').replaceAll('>', '>').replaceAll('<', '<');
@@ -116,18 +116,18 @@ String _processMarkdown(CodeResolver resolver, String line) {
}
line = "$line
";
} else {
- line = _replaceAll(line, ['[:', ':]'], htmlEntity: 'code');
- line = _replaceAll(line, ['`', '`'], htmlEntity: 'code');
- line = _replaceAll(line, ['*', '*'], htmlEntity: 'i');
- line = _replaceAll(line, ['__', '__'], htmlEntity: 'b');
- line = _replaceAll(line, ['[', ']'], replaceFunction: (String ref) {
+ line = replaceAll(line, ['[:', ':]'], htmlEntity: 'code');
+ line = replaceAll(line, ['`', '`'], htmlEntity: 'code');
+ line = replaceAll(line, ['*', '*'], htmlEntity: 'i');
+ line = replaceAll(line, ['__', '__'], htmlEntity: 'b');
+ line = replaceAll(line, ['[', ']'], replaceFunction: (String ref) {
return resolver.resolveCodeReference(ref);
});
}
return line;
}
-String _replaceAll(String str, List matchChars, {String htmlEntity, var replaceFunction}) {
+String replaceAll(String str, List matchChars, {String htmlEntity, var replaceFunction}) {
int lastWritten = 0;
int index = str.indexOf(matchChars[0]);
StringBuffer buf = new StringBuffer();
@@ -155,3 +155,5 @@ String _replaceAll(String str, List matchChars, {String htmlEntity, var
}
return buf.toString();
}
+
+
diff --git a/lib/src/model.dart b/lib/src/model.dart
new file mode 100644
index 0000000000..dd106f8403
--- /dev/null
+++ b/lib/src/model.dart
@@ -0,0 +1,583 @@
+// Copyright (c) 2014, 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.
+
+
+/// The models used to represent Dart code
+library dartdoc.models;
+
+import 'package:analyzer/src/generated/element.dart';
+
+import 'html_utils.dart';
+import 'model_utils.dart';
+import 'package_utils.dart';
+
+
+abstract class ModelElement {
+
+ Element element;
+
+ Library library;
+
+ ModelElement(this.element, this.library);
+
+ factory ModelElement.from(Element e, Library library) {
+ if (e is ClassElement) {
+ return new Class(e, library);
+ }
+ if (e is FunctionElement) {
+ return new Fnction(e, library);
+ }
+ if (e is FunctionTypeAliasElement) {
+ return new Typedef(e, library);
+ }
+ if (e is FieldElement) {
+ return new Field(e, library);
+ }
+ if (e is ConstructorElement) {
+ return new Constructor(e, library);
+ }
+ if (e is MethodElement) {
+ return new Method(e, library);
+ }
+ if (e is PropertyAccessorElement) {
+ return new Accessor(e, library);
+ }
+ if (e is TopLevelVariableElement) {
+ return new Variable(e, library);
+ }
+ }
+
+ String getDocumentation() {
+ if (element == null) {
+ return null;
+ }
+
+ String comments = element.computeDocumentationComment();
+
+ if (comments != null) {
+ return comments;
+ }
+
+ if (canOverride()) {
+ if (getOverriddenElement() != null) {
+ return getOverriddenElement().getDocumentation();
+ }
+ }
+ return null;
+ }
+
+ ModelElement getChild(String reference) {
+ Element e = (element as ElementImpl).getChild(reference);
+ if (e is LocalElement /*|| e is TypeVariableElement*/) {
+ return null;
+ }
+ return new ModelElement.from(e, library);
+ }
+
+ List getAnnotations() {
+ List a = element.metadata;
+ if (a.isNotEmpty) {
+ return a.map((f) => f.element.name).toList();
+ }
+ return [];
+ }
+
+ bool canOverride() => element is ClassMemberElement;
+
+ ModelElement getOverriddenElement() => null;
+
+ String get typeName => 'element';
+
+ String get name => element.name;
+
+ bool get isExecutable => element is ExecutableElement;
+
+ bool get isPropertyInducer => element is PropertyInducingElement;
+
+ bool get isPropertyAccessor => element is PropertyAccessorElement;
+
+ bool get isLocalElement => element is LocalElement;
+
+ bool get isStatic {
+ if (isPropertyInducer) {
+ return (element as PropertyInducingElement).isStatic;
+ }
+ return false;
+ }
+
+ bool get isFinal => false;
+
+ bool get isConst => false;
+
+ Class getEnclosingElement() {
+ if (element is ClassMemberElement) {
+ return new Class(element.enclosingElement, library);
+ } else {
+ return null;
+ }
+ }
+
+ String createLinkedSummary(Helper generator) {
+ if (isExecutable) {
+ ExecutableElement ex = (element as ExecutableElement);
+ String retType = generator.createLinkedReturnTypeName(new ElementType(ex.type, library));
+
+ return '${generator.createLinkedName(this)}'
+ '(${generator.printParams(ex.parameters.map((f)=>
+ new Parameter(f, library)))})'
+ '${retType.isEmpty ? '' : ': $retType'}';
+ }
+ if (isPropertyInducer) {
+ PropertyInducingElement pe = (element as PropertyInducingElement);
+ StringBuffer buf = new StringBuffer();
+ buf.write('${generator.createLinkedName(this)}');
+ String type = generator.createLinkedName(pe.type == null ? null : new ModelElement.from(pe.type.element, library));
+ if (!type.isEmpty) {
+ buf.write(': $type');
+ }
+ return buf.toString();
+ }
+ return generator.createLinkedName(this);
+ }
+
+ String createLinkedDescription(Helper generator) {
+ if (isExecutable && !(element is ConstructorElement)) {
+ ExecutableElement e = (element as ExecutableElement);
+ StringBuffer buf = new StringBuffer();
+
+ if (e.isStatic) {
+ buf.write('static ');
+ }
+
+ buf.write(generator.createLinkedReturnTypeName(new ElementType(e.type, library)));
+ buf.write(' ${e.name}(${generator.printParams(e.parameters.map((f)=> new Parameter(f, library)).toList())})');
+ return buf.toString();
+ }
+ if (isPropertyInducer) {
+ PropertyInducingElement e = (element as PropertyInducingElement);
+ StringBuffer buf = new StringBuffer();
+ if (e.isStatic) {
+ buf.write('static ');
+ }
+ if (e.isFinal) {
+ buf.write('final ');
+ }
+ if (e.isConst) {
+ buf.write('const ');
+ }
+
+ buf.write(generator.createLinkedName(e.type == null ? null : new ModelElement.from(e.type.element, library)));
+ buf.write(' ${e.name}');
+
+ // write out any constant value
+ Object value = getConstantValue(e);
+
+ if (value != null) {
+ if (value is String) {
+ String str = stringEscape(value, "'");
+ buf.write(" = '${str}'");
+ } else if (value is num) {
+ buf.write(" = ${value}");
+ }
+ //NumberFormat.decimalPattern
+ }
+ return buf.toString();
+ }
+ return null;
+ }
+}
+
+class Package {
+
+ String _rootDirPath;
+
+ List _libraries = [];
+
+ String get name => getPackageName(_rootDirPath);
+
+ String get version => getPackageVersion(_rootDirPath);
+
+ String get description => getPackageDescription(_rootDirPath);
+
+ List get libraries => _libraries;
+
+ Package(Iterable libraryElements, this._rootDirPath) {
+ libraryElements.forEach((element) {
+ _libraries.add(new Library(element));
+ });
+ }
+
+ bool isDocumented(ModelElement e) {
+ if (e is Library) {
+ return _libraries.contains(e);
+ }
+ return _libraries.contains(e.library);
+ }
+}
+
+class Library extends ModelElement {
+
+ LibraryElement get _library => (element as LibraryElement);
+
+ Library(LibraryElement element) : super(element, null);
+
+ List get exported => _library.exportedLibraries.map((lib) => new Library(lib)).toList();
+
+ List getVariables() {
+ List elements = [];
+ elements.addAll(_library.definingCompilationUnit.topLevelVariables);
+ for (CompilationUnitElement cu in _library.parts) {
+ elements.addAll(cu.topLevelVariables);
+ }
+ elements
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return elements.map((e) => new Variable(e, this)).toList();
+ }
+
+ List getAccessors() {
+ List elements = [];
+ elements.addAll(_library.definingCompilationUnit.accessors);
+ for (CompilationUnitElement cu in _library.parts) {
+ elements.addAll(cu.accessors);
+ }
+ elements
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ elements.removeWhere((e) => e.isSynthetic);
+ return elements.map((e) => new Accessor(e, this)).toList();
+ }
+
+ List getTypedefs() {
+ List elements = [];
+ elements.addAll(_library.definingCompilationUnit.functionTypeAliases);
+ for (CompilationUnitElement cu in _library.parts) {
+ elements.addAll(cu.functionTypeAliases);
+ }
+ elements
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return elements.map((e) => new Typedef(e, this)).toList();
+ }
+
+ List getFunctions() {
+ List elements = [];
+ elements.addAll(_library.definingCompilationUnit.functions);
+ for (CompilationUnitElement cu in _library.parts) {
+ elements.addAll(cu.functions);
+ }
+ elements
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return elements.map((e) => new Fnction(e, this)).toList();
+ }
+
+ List getTypes() {
+ List types = [];
+ types.addAll(_library.definingCompilationUnit.types);
+ for (CompilationUnitElement cu in _library.parts) {
+ types.addAll(cu.types);
+ }
+ types
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return types.map((e) => new Class(e, this)).toList();
+ }
+}
+
+class Class extends ModelElement {
+
+ ClassElement get _cls => (element as ClassElement);
+
+ String get typeName => 'Classes';
+
+ Class(ClassElement element, Library library) : super(element, library);
+
+ bool get isAbstract => _cls.isAbstract;
+
+ bool get hasSupertype => _cls.supertype != null && _cls.supertype.element.supertype != null;
+
+ ElementType get supertype => new ElementType(_cls.supertype, library);
+
+ List get mixins => _cls.mixins.map((f) => new ElementType(f, library)).toList();
+
+ List get interfaces => _cls.interfaces.map((f) => new ElementType(f, library)).toList();
+
+ List _getAllfields() {
+ List elements = _cls.fields.toList()
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return elements.map((e) => new Field(e, library)).toList();
+ }
+
+ List getStaticFields() => _getAllfields()..removeWhere((f) => !f.isStatic);
+
+ List getInstanceFields() => _getAllfields()..removeWhere((f) => f.isStatic);
+
+ List getAccessors() {
+ List accessors = _cls.accessors.toList()
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ accessors.removeWhere((e) => e.isSynthetic);
+ return accessors.map((e) => new Accessor(e, library)).toList();
+ }
+
+ List getCtors() {
+ List c = _cls.constructors.toList()
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return c.map((e) => new Constructor(e, library)).toList();
+ }
+
+ List getMethods() {
+ List m = _cls.methods.toList()
+ ..removeWhere(isPrivate)
+ ..sort(elementCompare);
+ return m.map((e) => new Method(e, library)).toList();
+ }
+
+ String createLinkedDescription(Helper generator) {
+ return '';
+ }
+}
+
+
+class Fnction extends ModelElement {
+
+ Fnction(FunctionElement element, Library library) : super(element, library);
+
+ FunctionElement get _func => (element as FunctionElement);
+
+ String get typeName => 'Functions';
+
+ String createLinkedSummary(Helper generator) {
+ String retType = generator.createLinkedReturnTypeName(new ElementType(_func.type, library));
+
+ return '${generator.createLinkedName(this)}'
+ '(${generator.printParams(_func.parameters.map((f)=> new Parameter(f, library)))})'
+ '${retType.isEmpty ? '' : ': $retType'}';
+ }
+
+ String createLinkedDescription(Helper generator) {
+ StringBuffer buf = new StringBuffer();
+ if (_func.isStatic) {
+ buf.write('static ');
+ }
+ buf.write(generator.createLinkedReturnTypeName(new ElementType(_func.type, library)));
+ buf.write(' ${_func.name}(${generator.printParams(_func.parameters.map((f)=> new Parameter(f, library)))})');
+ return buf.toString();
+ }
+}
+
+
+class Typedef extends ModelElement {
+
+ FunctionTypeAliasElement get _typedef => (element as FunctionTypeAliasElement);
+
+ Typedef(FunctionTypeAliasElement element, Library library) : super(element, library);
+
+ String get typeName => 'Typedefs';
+
+ String createLinkedSummary(Helper generator) {
+ // Comparator(T a, T b): int
+ StringBuffer buf = new StringBuffer();
+ buf.write(generator.createLinkedName(this));
+ if (!_typedef.typeParameters.isEmpty) {
+ buf.write('<');
+ for (int i = 0; i < _typedef.typeParameters.length; i++) {
+ if (i > 0) {
+ buf.write(', ');
+ }
+ buf.write(_typedef.typeParameters[i].name);
+ }
+ buf.write('>');
+ }
+ buf.write('(${generator.printParams(_typedef.parameters.map((f)=> new Parameter(f, library)))}): ');
+ buf.write(generator.createLinkedReturnTypeName(new ElementType(_typedef.type, library)));
+ return buf.toString();
+ }
+
+ String createLinkedDescription(Helper generator) {
+ // typedef int Comparator(T a, T b)
+
+ StringBuffer buf = new StringBuffer();
+ buf.write('typedef ${generator.createLinkedReturnTypeName(new ElementType(_typedef.type, library))} ${_typedef.name}');
+ if (!_typedef.typeParameters.isEmpty) {
+ buf.write('<');
+ for (int i = 0; i < _typedef.typeParameters.length; i++) {
+ if (i > 0) {
+ buf.write(', ');
+ }
+ buf.write(_typedef.typeParameters[i].name);
+ }
+ buf.write('>');
+ }
+ buf.write('(${generator.printParams(_typedef.parameters.map((f)=> new Parameter(f, library)))}): ');
+ return buf.toString();
+ }
+
+}
+
+class Field extends ModelElement {
+
+ FieldElement get _field => (element as FieldElement);
+
+ Field(FieldElement element, Library library) : super(element, library);
+
+ bool get isFinal => _field.isFinal;
+
+ bool get isConst => _field.isConst;
+
+ String get typeName => 'Fields';
+}
+
+class Constructor extends ModelElement {
+
+ ConstructorElement get _constructor => (element as ConstructorElement);
+
+ Constructor(ConstructorElement element, Library library) : super(element, library);
+
+ String get typeName => 'Constructors';
+
+ String createLinkedSummary(Helper generator) {
+ return '${generator.createLinkedName(this)}' '(${generator.printParams(_constructor.parameters.map((f) => new Parameter(f, library)).toList())})';
+ }
+
+ String createLinkedDescription(Helper generator) {
+ StringBuffer buf = new StringBuffer();
+ if (_constructor.isStatic) {
+ buf.write('static ');
+ }
+ if (_constructor.isFactory) {
+ buf.write('factory ');
+ }
+ buf.write('${_constructor.type.returnType.name}${_constructor.name.isEmpty?'':'.'}'
+ '${_constructor.name}'
+ '(${generator.printParams(
+ _constructor.parameters.map((f)=> new Parameter(f, library)))})');
+ return buf.toString();
+ }
+}
+
+
+class Method extends ModelElement {
+ // MethodElement get _method => (element as MethodElement);
+
+ Method(MethodElement element, Library library) : super(element, library);
+
+ Method getOverriddenElement() {
+ ClassElement parent = element.enclosingElement;
+ for (InterfaceType t in getAllSupertypes(parent)) {
+ if (t.getMethod(element.name) != null) {
+ return new Method(t.getMethod(element.name), library);
+ }
+ }
+ return null;
+ }
+
+ String get typeName => 'Methods';
+}
+
+class Accessor extends ModelElement {
+
+ PropertyAccessorElement get _accessor => (element as PropertyAccessorElement);
+
+ Accessor(PropertyAccessorElement element, Library library) : super(element, library);
+
+ String get typeName => 'Getters and Setters';
+
+ bool get isGetter => _accessor.isGetter;
+
+ String createLinkedSummary(Helper generator) {
+ StringBuffer buf = new StringBuffer();
+
+ if (_accessor.isGetter) {
+ buf.write(generator.createLinkedName(this));
+ buf.write(': ');
+ buf.write(generator.createLinkedReturnTypeName(
+ new ElementType(_accessor.type,
+ new ModelElement.from(_accessor.type.element, library))));
+ } else {
+ buf.write('${generator.createLinkedName(this)}('
+ '${generator.printParams(_accessor.parameters.map((f)=>
+ new Parameter(f,library)))})');
+ }
+ return buf.toString();
+ }
+
+ String createLinkedDescription(Helper generator) {
+ StringBuffer buf = new StringBuffer();
+ if (_accessor.isStatic) {
+ buf.write('static ');
+ }
+ if (_accessor.isGetter) {
+ buf.write('${generator.createLinkedReturnTypeName(new ElementType(_accessor.type, new ModelElement.from(_accessor.type.element, library)))} get ${_accessor.name}');
+ } else {
+ buf.write('set ${_accessor.name}(${generator.printParams(_accessor.parameters.map((f)=> new Parameter(f,library)))})');
+ }
+ return buf.toString();
+ }
+
+}
+
+class Variable extends ModelElement {
+
+ TopLevelVariableElement get _variable => (element as TopLevelVariableElement);
+
+ Variable(TopLevelVariableElement element, Library library) : super(element, library);
+
+ String get typeName => 'Top-Level Variables';
+
+ bool get isFinal => _variable.isFinal;
+
+ bool get isConst => _variable.isConst;
+}
+
+class Parameter extends ModelElement {
+
+ Parameter(ParameterElement element, Library library) : super(element, library);
+
+ ParameterElement get _parameter => (element as ParameterElement);
+
+ ElementType get type => new ElementType(_parameter.type, library);
+
+}
+
+class ElementType {
+ DartType _type;
+ Library library;
+
+ ElementType(this._type, this.library);
+
+ bool get isParameterType => (_type is TypeParameterType);
+
+ ModelElement get element => new ModelElement.from(_type.element, library);
+
+ String get name => _type.name;
+
+ bool get isParameterizedType => (_type is ParameterizedType);
+
+ String get returnTypeName => (_type as FunctionType).returnType.name;
+
+ ElementType get returnType => new ElementType((_type as FunctionType).returnType, library);
+
+ ModelElement get returnElement {
+ Element e = (_type as FunctionType).returnType.element;
+ if (e == null) {
+ return null;
+ }
+ return (new ModelElement.from(e, element.library));
+ }
+ List get typeArguments => (_type as ParameterizedType).typeArguments.map((f) => new ElementType(f, library)).toList();
+}
+
+
+abstract class Helper {
+ String createLinkedName(ModelElement e, [bool appendParens = false]);
+ String createLinkedReturnTypeName(ElementType type);
+ String createLinkedTypeName(ElementType type);
+ String printParams(List params);
+ String createHrefFor(ModelElement e);
+}
+
diff --git a/lib/src/model_utils.dart b/lib/src/model_utils.dart
index 7f7169f69a..1eda179f98 100644
--- a/lib/src/model_utils.dart
+++ b/lib/src/model_utils.dart
@@ -7,37 +7,6 @@ library model_utils;
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/constant.dart';
-String getDocumentationFor(Element e) {
- if (e == null) {
- return null;
- }
-
- String comments = e.computeDocumentationComment();
-
- if (comments != null) {
- return comments;
- }
-
- if (canOverride(e)) {
- return getDocumentationFor(getOverriddenElement(e));
- } else {
- return null;
- }
-}
-
-String getFileNameFor(LibraryElement library) {
- return '${library.name}.html';
-}
-
-Element getOverriddenElement(Element element) {
- if (element is MethodElement) {
- return getOverriddenElementMethod(element);
- } else {
- // TODO: ctors, fields, accessors -
-
- return null;
- }
-}
Object getConstantValue(PropertyInducingElement element) {
if (element is ConstFieldElementImpl) {
@@ -59,25 +28,9 @@ Object _valueFor(EvaluationResultImpl result) {
}
}
-MethodElement getOverriddenElementMethod(MethodElement element) {
- ClassElement parent = element.enclosingElement;
- for (InterfaceType t in getAllSupertypes(parent)) {
- if (t.getMethod(element.name) != null) {
- return t.getMethod(element.name);
- }
- }
- return null;
-}
-
-bool canOverride(Element e) => e is ClassMemberElement;
+int elementCompare(Element a, Element b) => a.name.compareTo(b.name);
-ClassElement getEnclosingElement(Element e) {
- if (e is ClassMemberElement) {
- return e.enclosingElement;
- } else {
- return null;
- }
-}
+bool isPrivate(Element e) => e.name.startsWith('_');
List getAllSupertypes(ClassElement c) {
InterfaceType t = c.type;