// Copyright (c) 2013, 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.

/**
 * To generate docs for a library, run this script with the path to an
 * entrypoint .dart file, like:
 *
 *     $ dart dartdoc.dart foo.dart
 *
 * This will create a "docs" directory with the docs for your libraries. To
 * create these beautiful docs, dartdoc parses your library and every library
 * it imports (recursively). From each library, it parses all classes and
 * members, finds the associated doc comments and builds crosslinked docs from
 * them.
 */
library dartdoc;

import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:json' as json;
import 'dart:math';

import 'package:pathos/path.dart' as pathos;

import 'classify.dart';
import 'markdown.dart' as md;
import 'universe_serializer.dart';

import 'src/dartdoc/nav.dart';
import 'src/dartdoc/utils.dart';
import 'src/export_map.dart';
import 'src/json_serializer.dart' as json_serializer;

// TODO(rnystrom): Use "package:" URL (#4968).
import 'src/dart2js_mirrors.dart' as dart2js;
import '../../compiler/implementation/mirrors/mirrors.dart';
import '../../compiler/implementation/mirrors/mirrors_util.dart';
import '../../libraries.dart';

/**
 * Generates completely static HTML containing everything you need to browse
 * the docs. The only client side behavior is trivial stuff like syntax
 * highlighting code.
 */
const MODE_STATIC = 0;

/**
 * Generated docs do not include baked HTML navigation. Instead, a single
 * `nav.json` file is created and the appropriate navigation is generated
 * client-side by parsing that and building HTML.
 *
 * This dramatically reduces the generated size of the HTML since a large
 * fraction of each static page is just redundant navigation links.
 *
 * In this mode, the browser will do a XHR for nav.json which means that to
 * preview docs locally, you will need to enable requesting file:// links in
 * your browser or run a little local server like `python -m SimpleHTTPServer`.
 */
const MODE_LIVE_NAV = 1;

const API_LOCATION = 'http://api.dartlang.org/';

/**
 * Gets the full path to the directory containing the entrypoint of the current
 * script. In other words, if you invoked dartdoc, directly, it will be the
 * path to the directory containing `dartdoc.dart`. If you're running a script
 * that imports dartdoc, it will be the path to that script.
 */
// TODO(johnniwinther): Convert to final (lazily initialized) variables when
// the feature is supported.
Path get scriptDir =>
    new Path(new Options().script).directoryPath;

/**
 * Deletes and recreates the output directory at [path] if it exists.
 */
void cleanOutputDirectory(Path path) {
  final outputDir = new Directory.fromPath(path);
  if (outputDir.existsSync()) {
    outputDir.deleteSync(recursive: true);
  }

  try {
    // TODO(3914): Hack to avoid 'file already exists' exception thrown
    // due to invalid result from dir.existsSync() (probably due to race
    // conditions).
    outputDir.createSync();
  } on DirectoryIOException catch (e) {
    // Ignore.
  }
}

/**
 * Copies all of the files in the directory [from] to [to]. Does *not*
 * recursively copy subdirectories.
 *
 * Note: runs asynchronously, so you won't see any files copied until after the
 * event loop has had a chance to pump (i.e. after `main()` has returned).
 */
Future copyDirectory(Path from, Path to) {
  print('Copying static files...');
  final completer = new Completer();
  final fromDir = new Directory.fromPath(from);
  var futureList = [];
  fromDir.list(recursive: false).listen(
      (FileSystemEntity entity) {
        if (entity is File) {
          final name = new Path(entity.path).filename;
          // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store.
          if (name.startsWith('.')) return;

          File fromFile = entity;
          File toFile = new File.fromPath(to.append(name));
          futureList.add(fromFile.openRead().pipe(toFile.openWrite()));
        }
      },
      onDone: () => Future.wait(futureList).then((_) => completer.complete()),
      onError: (e) => completer.completeError(e));
  return completer.future;
}

/**
 * Compiles the dartdoc client-side code to JavaScript using Dart2js.
 */
Future compileScript(int mode, Path outputDir, Path libPath, String tmpPath) {
  print('Compiling client JavaScript...');
  var clientScript = (mode == MODE_STATIC) ?  'static' : 'live-nav';
  var dartdocLibPath = pathos.join(libPath.toNativePath(),
      'lib', '_internal', 'dartdoc', 'lib');
  var dartPath = mode == MODE_STATIC ?
    pathos.join(tmpPath, 'client.dart') :
    pathos.join(dartdocLibPath, 'src', 'client', 'client-live-nav.dart');

  var jsPath = pathos.join(outputDir.toNativePath(),
    'client-$clientScript.js');

  return dart2js.compile(
      new Path(dartPath), libPath,
      options: const <String>['--categories=Client,Server', '--minify'])
  .then((jsCode) {
    if (jsCode != null) {
      writeString(new File(jsPath), jsCode);
    }
  });
}

/**
 * Package manifest containing all information required to render the main page
 * for a package.
 *
 * The manifest specifies where to load the [LibraryElement]s describing each
 * library rather than including them directly.
 * For our purposes we treat the core Dart libraries as a package.
 */
class PackageManifest {
  /** Package name. */
  final name;
  /** Package description */
  final description;
  /** Libraries contained in this package. */
  final List<Reference> libraries = <Reference>[];
  /**
   * Descriptive string describing the version# of the package.
   *
   * The current format for dart-sdk versions is
   * $MAJOR.$MINOR.$BUILD.$PATCH$revisionString$userNameString
   * For example: 0.1.2.0_r18233_johndoe
   */
  final String fullVersion;
  /**
   * Source control revision number for the package. For SVN this is a number
   * while for GIT it is a hash.
   */
  final String revision;
  /**
   * Path to the directory containing data files for each library.
   *
   * Currently this is the serialized json version of the LibraryElement for
   * the library.
   */
  String location;
  /**
   * Packages depended on by this package.
   * We currently store the entire manifest for the depency here the manifests
   * are small.  We may want to change this to a reference in the future.
   */
  final List<PackageManifest> dependencies = <PackageManifest>[];

  PackageManifest(this.name, this.description, this.fullVersion, this.revision);
}

class Dartdoc {

  /** Set to `false` to not include the source code in the generated docs. */
  bool includeSource = true;

  /**
   * Dartdoc can generate docs in a few different ways based on how dynamic you
   * want the client-side behavior to be. The value for this should be one of
   * the `MODE_` constants.
   */
  int mode = MODE_LIVE_NAV;

  /**
   * Generates the App Cache manifest file, enabling offline doc viewing.
   */
  bool generateAppCache = false;

  /** Path to the dartdoc directory. */
  Path dartdocPath;

  /** Path to generate HTML files into. */
  Path outputDir = new Path('docs');

  /**
   * The title used for the overall generated output. Set this to change it.
   */
  String mainTitle = 'Dart Documentation';

  /**
   * The URL that the Dart logo links to. Defaults "index.html", the main
   * page for the generated docs, but can be anything.
   */
  String mainUrl = 'index.html';

  /**
   * The Google Custom Search ID that should be used for the search box. If
   * this is `null` then no search box will be shown.
   */
  String searchEngineId = null;

  /* The URL that the embedded search results should be displayed on. */
  String searchResultsUrl = 'results.html';

  /** Set this to add footer text to each generated page. */
  String footerText = null;

  /** Set this to omit generation timestamp from output */
  bool omitGenerationTime = false;

  /** Set by Dartdoc user to print extra information during generation. */
  bool verbose = false;

  /** Set this to include API libraries in the documentation. */
  bool includeApi = false;

  /** Set this to generate links to the online API. */
  bool linkToApi = false;

  /** Set this to generate docs for private types and members. */
  bool showPrivate = false;

  /** Set this to inherit from Object. */
  bool inheritFromObject = false;

  /** Version of the sdk or package docs are being generated for. */
  String version;

  /** Set this to select the libraries to include in the documentation. */
  List<String> includedLibraries = const <String>[];

  /** Set this to select the libraries to exclude from the documentation. */
  List<String> excludedLibraries = const <String>[];

  /** The package root for `package:` imports. */
  String _packageRoot;

  /** The map containing all the exports for each library. */
  ExportMap _exports;

  /** The path to a temporary directory used by Dartdoc. */
  String tmpPath;

  /**
   * This list contains the libraries sorted in by the library name.
   */
  List<LibraryMirror> _sortedLibraries;

  /** A map from absolute paths of libraries to the libraries at those paths. */
  Map<String, LibraryMirror> _librariesByPath;

  /**
   * A map from absolute paths of hidden libraries to lists of [Export]s that
   * export those libraries from visible libraries. This is used to determine
   * what public library any given entity belongs to.
   *
   * The lists of exports are sorted so that exports that hide the fewest number
   * of members come first.
   */
  Map<String, List<Export>> _hiddenLibraryExports;

  /** The library that we're currently generating docs for. */
  LibraryMirror _currentLibrary;

  /** The type that we're currently generating docs for. */
  ClassMirror _currentType;

  /** The member that we're currently generating docs for. */
  MemberMirror _currentMember;

  /** The path to the file currently being written to, relative to [outdir]. */
  Path _filePath;

  /** The file currently being written to. */
  StringBuffer _file;

  int _totalLibraries = 0;
  int _totalTypes = 0;
  int _totalMembers = 0;

  int get totalLibraries => _totalLibraries;
  int get totalTypes => _totalTypes;
  int get totalMembers => _totalMembers;

  // Check if the compilation has started and finished.
  bool _started = false;
  bool _finished = false;

  /**
   * Prints the status of dartdoc.
   *
   * Prints whether dartdoc is running, whether dartdoc has finished
   * succesfully or not, and how many libraries, types, and members were
   * documented.
   */
  String get status {
    // TODO(amouravski): Make this more full featured and remove all other
    // prints and put them under verbose flag.
    if (!_started) {
      return 'Documentation has not yet started.';
    } else if (!_finished) {
      return 'Documentation in progress -- documented $_statisticsSummary so far.';
    } else {
      if (totals == 0) {
        return 'Documentation complete -- warning: nothing was documented!';
      } else {
        return 'Documentation complete -- documented $_statisticsSummary.';
      }
    }
  }

  int get totals => totalLibraries + totalTypes + totalMembers;

  String get _statisticsSummary =>
      '${totalLibraries} libraries, ${totalTypes} types, and '
      '${totalMembers} members';

  static const List<String> COMPILER_OPTIONS =
      const <String>['--preserve-comments', '--categories=Client,Server'];

  /// Resolves Dart links to the correct Node.
  md.Resolver dartdocResolver;

  // Add support for [:...:]-style code to the markdown parser.
  List<md.InlineSyntax> dartdocSyntaxes =
    [new md.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')];

  Dartdoc() {
    tmpPath = new Directory('').createTempSync().path;
    dartdocResolver = (String name) => resolveNameReference(name,
        currentLibrary: _currentLibrary, currentType: _currentType,
        currentMember: _currentMember);
  }

  /**
   * Returns `true` if [library] is included in the generated documentation.
   */
  bool shouldIncludeLibrary(LibraryMirror library) {
    if (shouldLinkToPublicApi(library)) {
      return false;
    }
    var includeByDefault = true;
    String libraryName = displayName(library);
    if (excludedLibraries.contains(libraryName)) {
      return false;
    }
    if (!includedLibraries.isEmpty) {
      includeByDefault = false;
      if (includedLibraries.contains(libraryName)) {
        return true;
      }
    }
    Uri uri = library.uri;
    if (uri.scheme == 'dart') {
      String suffix = uri.path;
      LibraryInfo info = LIBRARIES[suffix];
      if (info != null) {
        return info.documented && includeApi;
      }
    }
    return includeByDefault;
  }

  /**
   * Returns `true` if links to the public API should be generated for
   * [library].
   */
  bool shouldLinkToPublicApi(LibraryMirror library) {
    if (linkToApi) {
      Uri uri = library.uri;
      if (uri.scheme == 'dart') {
        String suffix = uri.path;
        LibraryInfo info = LIBRARIES[suffix];
        if (info != null) {
          return info.documented;
        }
      }
    }
    return false;
  }

  String get footerContent{
    var footerItems = [];
    if (!omitGenerationTime) {
      footerItems.add("This page was generated at ${new DateTime.now()}");
    }
    if (footerText != null) {
      footerItems.add(footerText);
    }
    var content = '';
    for (int i = 0; i < footerItems.length; i++) {
      if (i > 0) {
        content += '\n';
      }
      content += '<div>${footerItems[i]}</div>';
    }
    return content;
  }

  Future documentLibraries(List<Uri> libraryList, Path libPath,
      String packageRoot) {
    _packageRoot = packageRoot;
    _exports = new ExportMap.parse(libraryList, packageRoot);
    var librariesToAnalyze = _exports.allExportedFiles.toList();
    librariesToAnalyze.addAll(libraryList.map((uri) {
      if (uri.scheme == 'file') return fileUriToPath(uri);
      // dart2js takes "dart:*" URIs as Path objects for some reason.
      return uri.toString();
    }));

    var packageRootPath = packageRoot == null ? null : new Path(packageRoot);

    // TODO(amouravski): make all of these print statements into logging
    // statements.
    print('Analyzing libraries...');
    return dart2js.analyze(
        librariesToAnalyze.map((path) => new Path(path)).toList(), libPath,
        packageRoot: packageRootPath, options: COMPILER_OPTIONS)
      .then((MirrorSystem mirrors) {
        print('Generating documentation...');
        _document(mirrors);
      });
  }

  void _document(MirrorSystem mirrors) {
    _started = true;

    // Sort the libraries by name (not key).
    _sortedLibraries = new List<LibraryMirror>.from(
        mirrors.libraries.values.where(shouldIncludeLibrary));
    _sortedLibraries.sort((x, y) {
      return displayName(x).toUpperCase().compareTo(
          displayName(y).toUpperCase());
    });

    _librariesByPath = <String, LibraryMirror>{};
    for (var library in mirrors.libraries.values) {
      var path = _libraryPath(library);
      if (path == null) continue;
      path = pathos.normalize(pathos.absolute(path));
      _librariesByPath[path] = library;
    }

    _hiddenLibraryExports = _generateHiddenLibraryExports();

    // Generate the docs.
    if (mode == MODE_LIVE_NAV) {
      docNavigationJson();
    } else {
      docNavigationDart();
    }

    docIndex();
    for (final library in _sortedLibraries) {
      docLibrary(library);
    }

    if (generateAppCache) {
      generateAppCacheManifest();
    }

    // TODO(nweiz): properly handle exports when generating JSON.
    // TODO(jacobr): handle arbitrary pub packages rather than just the system
    // libraries.
    var revision = '0';
    if (version != null) {
      var match = new RegExp(r"_r(\d+)").firstMatch(version);
      if (match != null) {
        revision = match.group(1);
      } else {
        print("Warning: could not parse version: $version");
      }
    }
    var packageManifest = new PackageManifest('dart:', 'Dart System Libraries',
        version, revision);

    for (final lib in _sortedLibraries) {
      var libraryElement = new LibraryElement(
          lib, lookupMdnComment: lookupMdnComment)
          ..stripDuplicateUris(null, null);
      packageManifest.libraries.add(new Reference.fromElement(libraryElement));
      startFile("$revision/${libraryElement.id}.json");
      write(json_serializer.serialize(libraryElement));
      endFile();
    }

    startFile("$revision/apidoc.json");
    write(json_serializer.serialize(packageManifest));
    endFile();

    // Write out top level json file with a relative path to the library json
    // files.
    startFile("apidoc.json");
    packageManifest.location = revision;
    write(json_serializer.serialize(packageManifest));
    endFile();

    _finished = true;
  }

  /**
   * Generate [_hiddenLibraryExports] from [_exports] and [_librariesByPath].
   */
  Map<String, List<Export>> _generateHiddenLibraryExports() {
    // First generate a map `exported path => exporter path => Export`. The
    // inner map makes it easier to merge multiple exports of the same library
    // by the same exporter.
    var hiddenLibraryExportMaps = <String, Map<String, Export>>{};
    _exports.exports.forEach((exporter, exports) {
      var library = _librariesByPath[exporter];
      // TODO(nweiz): remove this check when issue 9645 is fixed.
      if (library == null) return;
      if (!shouldIncludeLibrary(library)) return;
      for (var export in exports) {
        var library = _librariesByPath[export.path];
        // TODO(nweiz): remove this check when issue 9645 is fixed.
        if (library == null) continue;
        if (shouldIncludeLibrary(library)) continue;

        var hiddenExports = _exports.transitiveExports(export.path)
            .map((transitiveExport) => export.compose(transitiveExport))
            .toList();
        hiddenExports.add(export);

        for (var hiddenExport in hiddenExports) {
          var exportsByExporterPath = hiddenLibraryExportMaps
              .putIfAbsent(hiddenExport.path, () => <String, Export>{});
          addOrMergeExport(exportsByExporterPath, exporter, hiddenExport);
        }
      }
    });

    // Now sort the values of the inner maps of `hiddenLibraryExportMaps` to get
    // the final value of `_hiddenLibraryExports`.
    var hiddenLibraryExports = <String, List<Export>>{};
    hiddenLibraryExportMaps.forEach((exporteePath, exportsByExporterPath) {
      int rank(Export export) {
        if (export.show.isEmpty && export.hide.isEmpty) return 0;
        if (export.show.isEmpty) return export.hide.length;
        // Multiply by 1000 to ensure this sorts after an export with hides.
        return 1000 * export.show.length;
      }

      var exports = exportsByExporterPath.values.toList();
      exports.sort((export1, export2) {
        var comparison = Comparable.compare(rank(export1), rank(export2));
        if (comparison != 0) return comparison;

        var library1 = _librariesByPath[export1.exporter];
        var library2 = _librariesByPath[export2.exporter];
        return Comparable.compare(displayName(library1), displayName(library2));
      });
      hiddenLibraryExports[exporteePath] = exports;
    });
    return hiddenLibraryExports;
  }

  MdnComment lookupMdnComment(Mirror mirror) => null;

  void startFile(String path) {
    _filePath = new Path(path);
    _file = new StringBuffer();
  }

  void endFile() {
    final outPath = outputDir.join(_filePath);
    final dir = new Directory.fromPath(outPath.directoryPath);
    if (!dir.existsSync()) {
      // TODO(3914): Hack to avoid 'file already exists' exception
      // thrown due to invalid result from dir.existsSync() (probably due to
      // race conditions).
      try {
        dir.createSync();
      } on DirectoryIOException catch (e) {
        // Ignore.
      }
    }

    writeString(new File.fromPath(outPath), _file.toString());
    _filePath = null;
    _file = null;
  }

  void write(String s) {
    _file.write(s);
  }

  void writeln(String s) {
    write(s);
    write('\n');
  }

  /**
   * Writes the page header with the given [title] and [breadcrumbs]. The
   * breadcrumbs are an interleaved list of links and titles. If a link is null,
   * then no link will be generated. For example, given:
   *
   *     ['foo', 'foo.html', 'bar', null]
   *
   * It will output:
   *
   *     <a href="foo.html">foo</a> &rsaquo; bar
   */
  void writeHeader(String title, List<String> breadcrumbs) {
    final htmlAttributes = generateAppCache ?
        'manifest="/appcache.manifest"' : '';

    write(
        '''
        <!DOCTYPE html>
        <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}>
        <head>
        ''');
    writeHeadContents(title);

    // Add data attributes describing what the page documents.
    var data = '';
    if (_currentLibrary != null) {
      data = '$data data-library='
             '"${md.escapeHtml(displayName(_currentLibrary))}"';
    }

    if (_currentType != null) {
      data = '$data data-type="${md.escapeHtml(typeName(_currentType))}"';
    }

    write(
        '''
        </head>
        <body$data>
        <div class="page">
        <div class="header">
          ${a(mainUrl, '<div class="logo"></div>')}
          ${a('index.html', mainTitle)}
        ''');

    // Write the breadcrumb trail.
    for (int i = 0; i < breadcrumbs.length; i += 2) {
      if (breadcrumbs[i + 1] == null) {
        write(' &rsaquo; ${breadcrumbs[i]}');
      } else {
        write(' &rsaquo; ${a(breadcrumbs[i + 1], breadcrumbs[i])}');
      }
    }

    if (searchEngineId != null) {
      writeln(
        '''
        <form action="$searchResultsUrl" id="search-box">
          <input type="hidden" name="cx" value="$searchEngineId">
          <input type="hidden" name="ie" value="UTF-8">
          <input type="hidden" name="hl" value="en">
          <input type="search" name="q" id="q" autocomplete="off"
              class="search-input" placeholder="Search API">
        </form>
        ''');
    } else {
      writeln(
        '''
        <div id="search-box">
          <input type="search" name="q" id="q" autocomplete="off"
              class="search-input" placeholder="Search API">
        </div>
        ''');
    }

    writeln(
      '''
      </div>
      <div class="drop-down" id="drop-down"></div>
      ''');

    docNavigation();
    writeln('<div class="content">');
  }

  String get clientScript {
    switch (mode) {
      case MODE_STATIC:   return 'client-static';
      case MODE_LIVE_NAV: return 'client-live-nav';
      default: throw 'Unknown mode $mode.';
    }
  }

  void writeHeadContents(String title) {
    writeln(
        '''
        <meta charset="utf-8">
        <title>$title / $mainTitle</title>
        <link rel="stylesheet" type="text/css"
            href="${relativePath('styles.css')}">
        <link href="//fonts.googleapis.com/css?family=Open+Sans:400,600,700,800" rel="stylesheet" type="text/css">
        <link rel="shortcut icon" href="${relativePath('favicon.ico')}">
        ''');
  }

  void writeFooter() {
    writeln(
        '''
        </div>
        <div class="clear"></div>
        </div>
        <div class="footer">
          $footerContent
        </div>
        <script async src="${relativePath('$clientScript.js')}"></script>
        </body></html>
        ''');
  }

  void docIndex() {
    startFile('index.html');

    writeHeader(mainTitle, []);

    writeln('<h2>$mainTitle</h2>');
    writeln('<h3>Libraries</h3>');

    for (final library in _sortedLibraries) {
      docIndexLibrary(library);
    }

    writeFooter();
    endFile();
  }

  void docIndexLibrary(LibraryMirror library) {
    writeln('<h4>${a(libraryUrl(library), displayName(library))}</h4>');
  }

  /**
   * Walks the libraries and creates a JSON object containing the data needed
   * to generate navigation for them.
   */
  void docNavigationJson() {
    startFile('nav.json');
    writeln(json.stringify(createNavigationInfo()));
    endFile();
  }
  /// Whether dartdoc is running from within the Dart SDK or the
  /// Dart source repository.
  bool get runningFromSdk =>
    pathos.extension(new Options().script) == '.snapshot';

  /// Gets the path to the root directory of the SDK.
  String get sdkDir =>
    pathos.dirname(pathos.dirname(new Options().executable));

  /// Gets the path to the dartdoc directory normalized for running in different
  /// places.
  String get normalizedDartdocPath => runningFromSdk ?
      pathos.join(sdkDir, 'lib', '_internal', 'dartdoc') :
      dartdocPath.toString();

  void docNavigationDart() {
    var tmpDir = new Directory(tmpPath);
    if (!tmpDir.existsSync()) {
        tmpDir.createSync();
    }
    String jsonString = json.stringify(createNavigationInfo());
    String dartString = jsonString.replaceAll(r"$", r"\$");
    var filePath = pathos.join(tmpPath, 'client.dart');
    var clientDir = pathos.relative(
        pathos.join(normalizedDartdocPath, 'lib', 'src', 'client'),
        from: tmpPath);

    writeString(new File(filePath),
        '''library client;
        import 'dart:html';
        import 'dart:json';
        import '${pathos.join(clientDir, 'client-shared.dart')}';
        import '${pathos.join(clientDir, 'dropdown.dart')}';

        main() {
          setup();
          setupSearch(json);
        }

        get json => $dartString;''');
  }

  void cleanup() {
    var tmpDir = new Directory(tmpPath);
    if (tmpDir.existsSync()) {
      tmpDir.deleteSync(recursive: true);
    }
    tmpPath = null;
  }

  List createNavigationInfo() {
    final libraryList = [];
    for (final library in _sortedLibraries) {
      docLibraryNavigationJson(library, libraryList);
    }
    return libraryList;
  }

  void docLibraryNavigationJson(LibraryMirror library, List libraryList) {
    var libraryInfo = {};
    libraryInfo[NAME] = displayName(library);
    final List members = docMembersJson(library.members);
    if (!members.isEmpty) {
      libraryInfo[MEMBERS] = members;
    }

    final types = [];
    for (ClassMirror type in orderByName(library.classes.values)) {
      if (!showPrivate && type.isPrivate) continue;

      var typeInfo = {};
      typeInfo[NAME] = displayName(type);
      if (type.isClass) {
        typeInfo[KIND] = CLASS;
      } else {
        assert(type.isTypedef);
        typeInfo[KIND] = TYPEDEF;
      }
      final List typeMembers = docMembersJson(type.members);
      if (!typeMembers.isEmpty) {
        typeInfo[MEMBERS] = typeMembers;
      }

      if (!type.originalDeclaration.typeVariables.isEmpty) {
        final typeVariables = [];
        for (final typeVariable in type.originalDeclaration.typeVariables) {
          typeVariables.add(displayName(typeVariable));
        }
        typeInfo[ARGS] = typeVariables.join(', ');
      }
      types.add(typeInfo);
    }
    if (!types.isEmpty) {
      libraryInfo[TYPES] = types;
    }

    libraryList.add(libraryInfo);
  }

  List docMembersJson(Map<Object,MemberMirror> memberMap) {
    final members = [];
    for (MemberMirror member in orderByName(memberMap.values)) {
      if (!showPrivate && member.isPrivate) continue;

      var memberInfo = {};
      if (member.isVariable) {
        memberInfo[KIND] = FIELD;
      } else {
        MethodMirror method = member;
        if (method.isConstructor) {
          memberInfo[KIND] = CONSTRUCTOR;
        } else if (method.isSetter) {
          memberInfo[KIND] = SETTER;
        } else if (method.isGetter) {
          memberInfo[KIND] = GETTER;
        } else {
          memberInfo[KIND] = METHOD;
        }
        if (method.parameters.isEmpty) {
          memberInfo[NO_PARAMS] = true;
        }
      }
      memberInfo[NAME] = displayName(member);
      var anchor = memberAnchor(member);
      if (anchor != memberInfo[NAME]) {
        memberInfo[LINK_NAME] = anchor;
      }
      members.add(memberInfo);
    }
    return members;
  }

  void docNavigation() {
    writeln(
        '''
        <div class="nav">
        ''');

    if (mode == MODE_STATIC) {
      for (final library in _sortedLibraries) {
        write('<h2><div class="icon-library"></div>');

        if ((_currentLibrary == library) && (_currentType == null)) {
          write('<strong>${displayName(library)}</strong>');
        } else {
          write('${a(libraryUrl(library), displayName(library))}');
        }
        write('</h2>');

        // Only expand classes in navigation for current library.
        if (_currentLibrary == library) docLibraryNavigation(library);
      }
    }

    writeln('</div>');
  }

  /** Writes the navigation for the types contained by the given library. */
  void docLibraryNavigation(LibraryMirror library) {
    // Show the exception types separately.
    final types = <ClassMirror>[];
    final exceptions = <ClassMirror>[];

    for (ClassMirror type in orderByName(library.classes.values)) {
      if (!showPrivate && type.isPrivate) continue;

      if (isException(type)) {
        exceptions.add(type);
      } else {
        types.add(type);
      }
    }

    if ((types.length == 0) && (exceptions.length == 0)) return;

    writeln('<ul class="icon">');
    types.forEach(docTypeNavigation);
    exceptions.forEach(docTypeNavigation);
    writeln('</ul>');
  }

  /** Writes a linked navigation list item for the given type. */
  void docTypeNavigation(ClassMirror type) {
    var icon = 'interface';
    if (isException(type)) {
      icon = 'exception';
    } else if (type.isClass) {
      icon = 'class';
    }

    write('<li>');
    if (_currentType == type) {
      write(
          '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>');
    } else {
      write(a(typeUrl(type),
          '<div class="icon-$icon"></div>${typeName(type)}'));
    }
    writeln('</li>');
  }

  void docLibrary(LibraryMirror library) {
    if (verbose) {
      print('Library \'${displayName(library)}\':');
    }
    _totalLibraries++;
    _currentLibrary = library;
    _currentType = null;

    startFile(libraryUrl(library));
    writeHeader('${displayName(library)} Library',
        [displayName(library), libraryUrl(library)]);
    writeln('<h2><strong>${displayName(library)}</strong> library</h2>');

    // Look for a comment for the entire library.
    final comment = getLibraryComment(library);
    if (comment != null) {
      writeln('<div class="doc">${comment.html}</div>');
    }

    // Document the visible libraries exported by this library.
    docExports(library);

    // Document the top-level members.
    docMembers(library);

    // Document the types.
    final abstractClasses = <ClassMirror>[];
    final classes = <ClassMirror>[];
    final typedefs = <TypedefMirror>[];
    final exceptions = <ClassMirror>[];

    var allClasses = _libraryClasses(library);
    for (ClassMirror type in orderByName(allClasses)) {
      if (!showPrivate && type.isPrivate) continue;

      if (isException(type)) {
        exceptions.add(type);
      } else if (type.isClass) {
        if (type.isAbstract) {
          abstractClasses.add(type);
        } else {
          classes.add(type);
        }
      } else if (type is TypedefMirror) {
        typedefs.add(type);
      } else {
        throw new InternalError("internal error: unknown type $type.");
      }
    }

    docTypes(abstractClasses, 'Abstract Classes');
    docTypes(classes, 'Classes');
    docTypes(typedefs, 'Typedefs');
    docTypes(exceptions, 'Exceptions');

    writeFooter();
    endFile();

    for (final type in allClasses) {
      if (!showPrivate && type.isPrivate) continue;

      docType(type);
    }
  }

  void docTypes(List types, String header) {
    if (types.length == 0) return;

    writeln('<div>');
    writeln('<h3>$header</h3>');

    for (final type in types) {
      writeln(
          '''
          <div class="type">
          <h4>
            ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")}
          </h4>
          </div>
          ''');
    }
    writeln('</div>');
  }

  void docType(ClassMirror type) {
    if (verbose) {
      print('- ${type.simpleName}');
    }
    _totalTypes++;
    _currentType = type;

    startFile(typeUrl(type));

    var kind;
    if (type.isTypedef) {
      kind = 'typedef';
    } else {
      assert(type.isClass);
      if (type.isAbstract) {
        kind = 'abstract class';
      } else {
        kind = 'class';
      }
    }

    final typeTitle =
      '${typeName(type)} ${kind}';
    var library = _libraryFor(type);
    writeHeader('$typeTitle / ${displayName(library)} Library',
        [displayName(library), libraryUrl(library),
         typeName(type), typeUrl(type)]);
    writeln(
        '''
        <h2><strong>${typeName(type, showBounds: true)}</strong>
          $kind
        </h2>
        ''');
    writeln('<button id="show-inherited" class="show-inherited">'
            'Hide inherited</button>');

    writeln('<div class="doc">');
    docComment(type, getTypeComment(type));
    docCode(type.location);
    writeln('</div>');

    docInheritance(type);
    docTypedef(type);

    docMembers(type);

    writeTypeFooter();
    writeFooter();
    endFile();
  }

  /** Override this to write additional content at the end of a type's page. */
  void writeTypeFooter() {
    // Do nothing.
  }

  /**
   * Writes an inline type span for the given type. This is a little box with
   * an icon and the type's name. It's similar to how types appear in the
   * navigation, but is suitable for inline (as opposed to in a `<ul>`) use.
   */
  void typeSpan(ClassMirror type) {
    var icon = 'interface';
    if (isException(type)) {
      icon = 'exception';
    } else if (type.isClass) {
      icon = 'class';
    }

    write('<span class="type-box"><span class="icon-$icon"></span>');
    if (_currentType == type) {
      write('<strong>${typeName(type)}</strong>');
    } else {
      write(a(typeUrl(type), typeName(type)));
    }
    write('</span>');
  }

  /**
   * Document the other types that touch [Type] in the inheritance hierarchy:
   * subclasses, superclasses, subinterfaces, superinferfaces, and default
   * class.
   */
  void docInheritance(ClassMirror type) {
    // Don't show the inheritance details for Object. It doesn't have any base
    // class (obviously) and it has too many subclasses to be useful.
    if (type.isObject) return;
    if (type.isTypedef) return;

    // Writes an unordered list of references to types with an optional header.
    listTypes(types, header) {
      if (types == null) return;

      // Filter out injected types. (JavaScriptIndexingBehavior)
      types = new List.from(types.where((t) => t.library != null));

      var publicTypes;
      if (showPrivate) {
        publicTypes = types;
      } else {
        // Skip private types.
        publicTypes = new List.from(types.where((t) => !t.isPrivate));
      }
      if (publicTypes.length == 0) return;

      writeln('<h3>$header</h3>');
      writeln('<p>');
      bool first = true;
      for (final t in publicTypes) {
        if (!first) write(', ');
        typeSpan(t);
        first = false;
      }
      writeln('</p>');
    }

    final subtypes = [];
    for (final subtype in computeSubdeclarations(type)) {
      subtypes.add(subtype);
    }
    subtypes.sort((x, y) => x.simpleName.compareTo(y.simpleName));

    // Show the chain of superclasses.
    if (!type.superclass.isObject) {
      final supertypes = [];
      var thisType = type.superclass;
      do {
        supertypes.add(thisType);
        thisType = thisType.superclass;
      } while (!thisType.isObject);

      writeln('<h3>Extends</h3>');
      writeln('<p>');
      for (var i = supertypes.length - 1; i >= 0; i--) {
        typeSpan(supertypes[i]);
        write('&nbsp;&gt;&nbsp;');
      }

      // Write this class.
      typeSpan(type);
      writeln('</p>');
    }

    listTypes(subtypes, 'Subclasses');
    listTypes(type.superinterfaces, 'Implements');
  }

  /**
   * Documents the definition of [type] if it is a typedef.
   */
  void docTypedef(TypeMirror type) {
    if (type is! TypedefMirror) {
      return;
    }
    writeln('<div class="method"><h4 id="${type.simpleName}">');

    if (includeSource) {
      writeln('<button class="show-code">Code</button>');
    }

    write('typedef ');
    annotateType(type, type.value, type.simpleName);

    write(''' <a class="anchor-link" href="#${type.simpleName}"
              title="Permalink to ${type.simpleName}">#</a>''');
    writeln('</h4>');

    writeln('<div class="doc">');
    docCode(type.location);
    writeln('</div>');

    writeln('</div>');
  }

  static const operatorOrder = const <String>[
      '[]', '[]=', // Indexing.
      '+', Mirror.UNARY_MINUS, '-', '*', '/', '~/', '%', // Arithmetic.
      '&', '|', '^', '~', // Bitwise.
      '<<', '>>', // Shift.
      '<', '<=', '>', '>=', // Relational.
      '==', // Equality.
  ];

  static final Map<String, int> operatorOrderMap = (){
    var map = new Map<String, int>();
    var index = 0;
    for (String operator in operatorOrder) {
      map[operator] = index++;
    }
    return map;
  }();

  void docExports(LibraryMirror library) {
    // TODO(nweiz): show `dart:` library exports.
    var exportLinks = _exports.transitiveExports(_libraryPath(library))
        .map((export) {
      var library = _librariesByPath[export.path];
      // TODO(nweiz): remove this check when issue 9645 is fixed.
      if (library == null) return null;
      // Only link to publically visible libraries.
      if (!shouldIncludeLibrary(library)) return null;

      var memberNames = export.show.isEmpty ? export.hide : export.show;
      var memberLinks = memberNames.map((name) {
        return md.renderToHtml([resolveNameReference(
            name, currentLibrary: library)]);
      }).join(', ');
      var combinator = '';
      if (!export.show.isEmpty) {
        combinator = ' show $memberLinks';
      } else if (!export.hide.isEmpty) {
        combinator = ' hide $memberLinks';
      }

      return '<ul>${a(libraryUrl(library), displayName(library))}'
        '$combinator</ul>';
    }).where((link) => link != null);

    if (!exportLinks.isEmpty) {
      writeln('<h3>Exports</h3>');
      writeln('<ul>');
      writeln(exportLinks.join('\n'));
      writeln('</ul>');
    }
  }

  void docMembers(ContainerMirror host) {
    // Collect the different kinds of members.
    final staticMethods = [];
    final staticGetters = new Map<String,MemberMirror>();
    final staticSetters = new Map<String,MemberMirror>();
    final memberMap = new Map<String,MemberMirror>();
    final instanceMethods = [];
    final instanceOperators = [];
    final instanceGetters = new Map<String,MemberMirror>();
    final instanceSetters = new Map<String,MemberMirror>();
    final constructors = [];

    var hostMembers = host is LibraryMirror ?
        _libraryMembers(host) : host.members.values;
    for (var member in hostMembers) {
      if (!showPrivate && member.isPrivate) continue;
      if (host is LibraryMirror || member.isStatic) {
        if (member is MethodMirror) {
          if (member.isGetter) {
            staticGetters[displayName(member)] = member;
          } else if (member.isSetter) {
            staticSetters[displayName(member)] = member;
          } else {
            staticMethods.add(member);
          }
        } else if (member is VariableMirror) {
          staticGetters[displayName(member)] = member;
        }
      }
    }

    if (host is ClassMirror) {
      var iterable = new HierarchyIterable(host, includeType: true);
      for (ClassMirror type in iterable) {
        if (!host.isObject && !inheritFromObject && type.isObject) continue;

        type.members.forEach((_, MemberMirror member) {
          if (member.isStatic) return;
          if (!showPrivate && member.isPrivate) return;

          bool inherit = true;
          if (type != host) {
            if (member.isPrivate) {
              // Don't inherit private members.
              inherit = false;
            }
            if (member.isConstructor) {
              // Don't inherit constructors.
              inherit = false;
            }
          }
          if (!inherit) return;

          if (member.isVariable) {
            // Fields override both getters and setters.
            memberMap.putIfAbsent(member.simpleName, () => member);
            memberMap.putIfAbsent('${member.simpleName}=', () => member);
          } else if (member.isConstructor) {
            constructors.add(member);
          } else {
            memberMap.putIfAbsent(member.simpleName, () => member);
          }
        });
      }
    }

    bool allMethodsInherited = true;
    bool allPropertiesInherited = true;
    bool allOperatorsInherited = true;
    memberMap.forEach((_, MemberMirror member) {
      if (member is MethodMirror) {
        if (member.isGetter) {
          instanceGetters[displayName(member)] = member;
          if (_ownerFor(member) == host) {
            allPropertiesInherited = false;
          }
        } else if (member.isSetter) {
          instanceSetters[displayName(member)] = member;
          if (_ownerFor(member) == host) {
            allPropertiesInherited = false;
          }
        } else if (member.isOperator) {
          instanceOperators.add(member);
          if (_ownerFor(member) == host) {
            allOperatorsInherited = false;
          }
        } else {
          instanceMethods.add(member);
          if (_ownerFor(member) == host) {
            allMethodsInherited = false;
          }
        }
      } else if (member is VariableMirror) {
        instanceGetters[displayName(member)] = member;
        if (_ownerFor(member) == host) {
          allPropertiesInherited = false;
        }
      }
    });

    instanceOperators.sort((MethodMirror a, MethodMirror b) {
      return operatorOrderMap[a.simpleName].compareTo(
          operatorOrderMap[b.simpleName]);
    });

    docProperties(host,
                  host is LibraryMirror ? 'Properties' : 'Static Properties',
                  staticGetters, staticSetters, allInherited: false);
    docMethods(host,
               host is LibraryMirror ? 'Functions' : 'Static Methods',
               staticMethods, allInherited: false);

    docMethods(host, 'Constructors', orderByName(constructors),
               allInherited: false);
    docProperties(host, 'Properties', instanceGetters, instanceSetters,
                  allInherited: allPropertiesInherited);
    docMethods(host, 'Operators', instanceOperators,
               allInherited: allOperatorsInherited);
    docMethods(host, 'Methods', orderByName(instanceMethods),
               allInherited: allMethodsInherited);
  }

  /**
   * Documents fields, getters, and setters as properties.
   */
  void docProperties(ContainerMirror host, String title,
                     Map<String,MemberMirror> getters,
                     Map<String,MemberMirror> setters,
                     {bool allInherited}) {
    if (getters.isEmpty && setters.isEmpty) return;

    var nameSet = new Set<String>.from(getters.keys);
    nameSet.addAll(setters.keys);
    var nameList = new List<String>.from(nameSet);
    nameList.sort((String a, String b) {
      return a.toLowerCase().compareTo(b.toLowerCase());
    });

    writeln('<div${allInherited ? ' class="inherited"' : ''}>');
    writeln('<h3>$title</h3>');
    for (String name in nameList) {
      MemberMirror getter = getters[name];
      MemberMirror setter = setters[name];
      if (setter == null) {
        if (getter is VariableMirror) {
          // We have a field.
          docField(host, getter);
        } else {
          // We only have a getter.
          assert(getter is MethodMirror);
          docProperty(host, getter, null);
        }
      } else if (getter == null) {
        // We only have a setter => Document as a method.
        assert(setter is MethodMirror);
        docMethod(host, setter);
      } else {
        DocComment getterComment = getMemberComment(getter);
        DocComment setterComment = getMemberComment(setter);
        if (_ownerFor(getter) != _ownerFor(setter) ||
            getterComment != null && setterComment != null) {
          // Both have comments or are not declared in the same class
          // => Documents separately.
          if (getter is VariableMirror) {
            // Document field as a getter (setter is inherited).
            docField(host, getter, asGetter: true);
          } else {
            docMethod(host, getter);
          }
          if (setter is VariableMirror) {
            // Document field as a setter (getter is inherited).
            docField(host, setter, asSetter: true);
          } else {
            docMethod(host, setter);
          }
        } else {
          // Document as field.
          docProperty(host, getter, setter);
        }
      }
    }
    writeln('</div>');
  }

  void docMethods(ContainerMirror host, String title, List<Mirror> methods,
                  {bool allInherited}) {
    if (methods.length > 0) {
      writeln('<div${allInherited ? ' class="inherited"' : ''}>');
      writeln('<h3>$title</h3>');
      for (MethodMirror method in methods) {
        docMethod(host, method);
      }
      writeln('</div>');
    }
  }

  /**
   * Documents the [member] declared in [host]. Handles all kinds of members
   * including getters, setters, and constructors. If [member] is a
   * [FieldMirror] it is documented as a getter or setter depending upon the
   * value of [asGetter].
   */
  void docMethod(ContainerMirror host, MemberMirror member,
                 {bool asGetter: false}) {
    _totalMembers++;
    _currentMember = member;

    bool isAbstract = false;
    String name = displayName(member);
    if (member is VariableMirror) {
      if (asGetter) {
        // Getter.
        name = 'get $name';
      } else {
        // Setter.
        name = 'set $name';
      }
    } else {
      assert(member is MethodMirror);
      isAbstract = member.isAbstract;
      if (member.isGetter) {
        // Getter.
        name = 'get $name';
      } else if (member.isSetter) {
        // Setter.
        name = 'set $name';
      }
    }

    bool showCode = includeSource && !isAbstract;
    bool inherited = host != member.owner && member.owner is! LibraryMirror;

    writeln('<div class="method${inherited ? ' inherited': ''}">'
            '<h4 id="${memberAnchor(member)}">');

    if (showCode) {
      writeln('<button class="show-code">Code</button>');
    }

    if (member is MethodMirror) {
      if (member.isConstructor) {
        if (member.isFactoryConstructor) {
          write('factory ');
        } else {
          write(member.isConstConstructor ? 'const ' : 'new ');
        }
      } else if (member.isAbstract) {
        write('abstract ');
      }

      if (!member.isConstructor) {
        annotateDynamicType(host, member.returnType);
      }
    } else {
      assert(member is VariableMirror);
      if (asGetter) {
        annotateDynamicType(host, member.type);
      } else {
        write('void ');
      }
    }

    write('<strong>$name</strong>');

    if (member is MethodMirror) {
      if (!member.isGetter) {
        docParamList(host, member.parameters);
      }
    } else {
      assert(member is VariableMirror);
      if (!asGetter) {
        write('(');
        annotateType(host, member.type);
        write(' value)');
      }
    }

    var prefix = host is LibraryMirror ? '' : '${typeName(host)}.';
    write(''' <a class="anchor-link" href="#${memberAnchor(member)}"
              title="Permalink to $prefix$name">#</a>''');
    writeln('</h4>');

    if (inherited) {
      write('<div class="inherited-from">inherited from ');
      annotateType(host, member.owner);
      write('</div>');
    }

    writeln('<div class="doc">');
    docComment(host, getMemberComment(member));
    if (showCode) {
      docCode(member.location);
    }
    writeln('</div>');

    writeln('</div>');
  }

  void docField(ContainerMirror host, VariableMirror field,
                {bool asGetter: false, bool asSetter: false}) {
    if (asGetter) {
      docMethod(host, field, asGetter: true);
    } else if (asSetter) {
      docMethod(host, field, asGetter: false);
    } else {
      docProperty(host, field, null);
    }
  }

  /**
   * Documents the property defined by [getter] and [setter] of declared in
   * [host]. If [getter] is a [FieldMirror], [setter] must be [:null:].
   * Otherwise, if [getter] is a [MethodMirror], the property is considered
   * final if [setter] is [:null:].
   */
  void docProperty(ContainerMirror host,
                   MemberMirror getter, MemberMirror setter) {
    assert(getter != null);
    _totalMembers++;
    _currentMember = getter;

    bool inherited = host != getter.owner && getter.owner is! LibraryMirror;

    writeln('<div class="field${inherited ? ' inherited' : ''}">'
            '<h4 id="${memberAnchor(getter)}">');

    if (includeSource) {
      writeln('<button class="show-code">Code</button>');
    }

    bool isConst = false;
    bool isFinal;
    TypeMirror type;
    if (getter is VariableMirror) {
      assert(setter == null);
      isConst = getter.isConst;
      isFinal = getter.isFinal;
      type = getter.type;
    } else {
      assert(getter is MethodMirror);
      isFinal = setter == null;
      type = getter.returnType;
    }

    if (isConst) {
      write('const ');
    } else if (isFinal) {
      write('final ');
    } else if (type.isDynamic) {
      write('var ');
    }

    annotateType(host, type);
    var prefix = host is LibraryMirror ? '' : '${typeName(host)}.';
    write(
        '''
        <strong>${getter.simpleName}</strong> <a class="anchor-link"
            href="#${memberAnchor(getter)}"
            title="Permalink to $prefix${getter.simpleName}">#</a>
        </h4>
        ''');

    if (inherited) {
      write('<div class="inherited-from">inherited from ');
      annotateType(host, getter.owner);
      write('</div>');
    }

    DocComment comment = getMemberComment(getter);
    if (comment == null && setter != null) {
      comment = getMemberComment(setter);
    }
    writeln('<div class="doc">');
    docComment(host, comment);
    docCode(getter.location);
    if (setter != null) {
      docCode(setter.location);
    }
    writeln('</div>');

    writeln('</div>');
  }

  void docParamList(ContainerMirror enclosingType,
                    List<ParameterMirror> parameters) {
    write('(');
    bool first = true;
    bool inOptionals = false;
    bool isNamed = false;
    for (final parameter in parameters) {
      if (!first) write(', ');

      if (!inOptionals && parameter.isOptional) {
        isNamed = parameter.isNamed;
        write(isNamed ? '{' : '[');
        inOptionals = true;
      }

      annotateType(enclosingType, parameter.type, parameter.simpleName);

      // Show the default value for named optional parameters.
      if (parameter.isOptional && parameter.hasDefaultValue) {
        write(isNamed ? ': ' : ' = ');
        write(parameter.defaultValue);
      }

      first = false;
    }

    if (inOptionals) {
      write(isNamed ? '}' : ']');
    }
    write(')');
  }

  void docComment(ContainerMirror host, DocComment comment) {
    if (comment != null) {
      var html = comment.html;

      if (comment.inheritedFrom != null) {
        writeln('<div class="inherited">');
        writeln(html);
        write('<div class="docs-inherited-from">docs inherited from ');
        annotateType(host, comment.inheritedFrom);
        write('</div>');
        writeln('</div>');
      } else {
        writeln(html);
      }
    }
  }

  /**
   * Documents the source code contained within [location].
   */
  void docCode(SourceLocation location) {
    if (includeSource) {
      writeln('<pre class="source">');
      writeln(md.escapeHtml(unindentCode(location)));
      writeln('</pre>');
    }
  }

  /** Get the doc comment associated with the given library. */
  DocComment getLibraryComment(LibraryMirror library) => getComment(library);

  /** Get the doc comment associated with the given type. */
  DocComment getTypeComment(TypeMirror type) => getComment(type);

  /**
   * Get the doc comment associated with the given member.
   *
   * If no comment was found on the member, the hierarchy is traversed to find
   * an inherited comment, favouring comments inherited from classes over
   * comments inherited from interfaces.
   */
  DocComment getMemberComment(MemberMirror member) => getComment(member);

  /**
   * Get the doc comment associated with the given declaration.
   *
   * If no comment was found on a member, the hierarchy is traversed to find
   * an inherited comment, favouring comments inherited from classes over
   * comments inherited from interfaces.
   */
  DocComment getComment(DeclarationMirror mirror) {
    String comment = computeComment(mirror);
    ClassMirror inheritedFrom = null;
    if (comment == null) {
      if (mirror.owner is ClassMirror) {
        var iterable =
            new HierarchyIterable(mirror.owner,
                                  includeType: false);
        for (ClassMirror type in iterable) {
          var inheritedMember = type.members[mirror.simpleName];
          if (inheritedMember is MemberMirror) {
            comment = computeComment(inheritedMember);
            if (comment != null) {
              inheritedFrom = type;
              break;
            }
          }
        }
      }
    }
    if (comment == null) return null;
    return new DocComment(comment, inheritedFrom, dartdocSyntaxes,
        dartdocResolver);
  }

  /**
   * Converts [fullPath] which is understood to be a full path from the root of
   * the generated docs to one relative to the current file.
   */
  String relativePath(String fullPath) {
    // Don't make it relative if it's an absolute path.
    if (isAbsolute(fullPath)) return fullPath;

    // TODO(rnystrom): Walks all the way up to root each time. Shouldn't do
    // this if the paths overlap.
    return '${repeat('../',
                     countOccurrences(_filePath.toString(), '/'))}$fullPath';
  }

  /** Gets whether or not the given URL is absolute or relative. */
  bool isAbsolute(String url) {
    // TODO(rnystrom): Why don't we have a nice type in the platform for this?
    // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks
    // a scheme to be relative.
    return new RegExp(r'^\w+:').hasMatch(url);
  }

  /** Gets the URL to the documentation for [library]. */
  String libraryUrl(LibraryMirror library) {
    return '${sanitize(displayName(library))}.html';
  }

  /** Gets the URL for the documentation for [type]. */
  String typeUrl(ContainerMirror type) {
    if (type is LibraryMirror) {
      return '${sanitize(type.simpleName)}.html';
    }
    if (type.library == null) {
      return '';
    }
    // Always get the generic type to strip off any type parameters or
    // arguments. If the type isn't generic, genericType returns `this`, so it
    // works for non-generic types too.
    return '${sanitize(displayName(_libraryFor(type)))}/'
           '${type.originalDeclaration.simpleName}.html';
  }

  /** Gets the URL for the documentation for [member]. */
  String memberUrl(MemberMirror member) {
    String url = typeUrl(_ownerFor(member));
    return '$url#${memberAnchor(member)}';
  }

  /** Gets the anchor id for the document for [member]. */
  String memberAnchor(MemberMirror member) {
    return member.simpleName;
  }

  /**
   * Creates a hyperlink. Handles turning the [href] into an appropriate
   * relative path from the current file.
   */
  String a(String href, String contents, [String css]) {
    // Mark outgoing external links, mainly so we can style them.
    final rel = isAbsolute(href) ? ' ref="external"' : '';
    final cssClass = css == null ? '' : ' class="$css"';
    return '<a href="${relativePath(href)}"$cssClass$rel>$contents</a>';
  }

  /**
   * Writes a type annotation, preferring to print dynamic.
   */
  annotateDynamicType(ContainerMirror enclosingType,
                      TypeMirror type) {
    annotateType(enclosingType, type, type.isDynamic ? 'dynamic ' : null);
  }

  /**
   * Writes a type annotation for the given type and (optional) parameter name.
   */
  annotateType(ContainerMirror enclosingType,
               TypeMirror type,
               [String paramName = null]) {
    // Don't bother explicitly displaying dynamic.
    if (type.isDynamic) {
      if (paramName != null) write(paramName);
      return;
    }

    // For parameters, handle non-typedefed function types.
    if (paramName != null && type is FunctionTypeMirror) {
      annotateType(enclosingType, type.returnType);
      write(paramName);

      docParamList(enclosingType, type.parameters);
      return;
    }

    linkToType(enclosingType, type);

    write(' ');
    if (paramName != null) write(paramName);
  }

  /** Writes a link to a human-friendly string representation for a type. */
  linkToType(ContainerMirror enclosingType, TypeMirror type) {
    if (type.isVoid) {
      // Do not generate links for void.
      // TODO(johnniwinter): Generate span for specific style?
      write('void');
      return;
    }
    if (type.isDynamic) {
      // Do not generate links for dynamic.
      write('dynamic');
      return;
    }

    if (type.isTypeVariable) {
      // If we're using a type parameter within the body of a generic class then
      // just link back up to the class.
      write(a(typeUrl(enclosingType), type.simpleName));
      return;
    }

    assert(type is ClassMirror);

    // Link to the type.
    var library = _libraryFor(type);
    if (shouldLinkToPublicApi(library)) {
      write('<a href="$API_LOCATION${typeUrl(type)}">${type.simpleName}</a>');
    } else if (shouldIncludeLibrary(library)) {
      write(a(typeUrl(type), type.simpleName));
    } else {
      write(type.simpleName);
    }

    if (type.isOriginalDeclaration) {
      // Avoid calling [:typeArguments():] on a declaration.
      return;
    }

    // See if it's an instantiation of a generic type.
    final typeArgs = type.typeArguments;
    if (typeArgs.length > 0) {
      write('&lt;');
      bool first = true;
      for (final arg in typeArgs) {
        if (!first) write(', ');
        first = false;
        linkToType(enclosingType, arg);
      }
      write('&gt;');
    }
  }

  /** Creates a linked cross reference to [type]. */
  typeReference(ClassMirror type) {
    // TODO(rnystrom): Do we need to handle ParameterTypes here like
    // annotation() does?
    return a(typeUrl(type), typeName(type), 'crossref');
  }

  /** Generates a human-friendly string representation for a type. */
  typeName(TypeMirror type, {bool showBounds: false}) {
    if (type.isVoid) {
      return 'void';
    }
    if (type.isDynamic) {
      return 'dynamic';
    }
    if (type is TypeVariableMirror) {
      return type.simpleName;
    }
    assert(type is ClassMirror);

    // See if it's a generic type.
    if (type.isOriginalDeclaration) {
      final typeParams = [];
      for (final typeParam in type.originalDeclaration.typeVariables) {
        if (showBounds &&
            (typeParam.upperBound != null) &&
            !typeParam.upperBound.isObject) {
          final bound = typeName(typeParam.upperBound, showBounds: true);
          typeParams.add('${typeParam.simpleName} extends $bound');
        } else {
          typeParams.add(typeParam.simpleName);
        }
      }
      if (typeParams.isEmpty) {
        return type.simpleName;
      }
      final params = typeParams.join(', ');
      return '${type.simpleName}&lt;$params&gt;';
    }

    // See if it's an instantiation of a generic type.
    final typeArgs = type.typeArguments;
    if (typeArgs.length > 0) {
      final args = typeArgs.map((arg) => typeName(arg)).join(', ');
      return '${type.originalDeclaration.simpleName}&lt;$args&gt;';
    }

    // Regular type.
    return type.simpleName;
  }

  /**
   * Remove leading indentation to line up with first line.
   */
  unindentCode(SourceLocation span) {
    final column = span.column;
    final lines = span.text.split('\n');
    // TODO(rnystrom): Dirty hack.
    for (var i = 1; i < lines.length; i++) {
      lines[i] = unindent(lines[i], column);
    }

    final code = lines.join('\n');
    return code;
  }

  /**
   * Takes a string of Dart code and turns it into sanitized HTML.
   */
  formatCode(SourceLocation span) {
    final code = unindentCode(span);

    // Syntax highlight.
    return classifySource(code);
  }

  /**
   * This will be called whenever a doc comment hits a `[name]` in square
   * brackets. It will try to figure out what the name refers to and link or
   * style it appropriately.
   */
  md.Node resolveNameReference(String name,
                               {MemberMirror currentMember,
                                ContainerMirror currentType,
                                LibraryMirror currentLibrary}) {
    makeLink(String href) {
      final anchor = new md.Element.text('a', name);
      anchor.attributes['href'] = relativePath(href);
      anchor.attributes['class'] = 'crossref';
      return anchor;
    }

    // See if it's a parameter of the current method.
    if (currentMember is MethodMirror) {
      for (final parameter in currentMember.parameters) {
        if (parameter.simpleName == name) {
          final element = new md.Element.text('span', name);
          element.attributes['class'] = 'param';
          return element;
        }
      }
    }

    // See if it's another member of the current type.
    if (currentType != null) {
      final foundMember = currentType.members[name];
      if (foundMember != null) {
        return makeLink(memberUrl(foundMember));
      }
    }

    // See if it's another type or a member of another type in the current
    // library.
    if (currentLibrary != null) {
      // See if it's a constructor
      final constructorLink = (() {
        final match =
            new RegExp(r'new ([\w$]+)(?:\.([\w$]+))?').firstMatch(name);
        if (match == null) return;
        String typeName = match[1];
        ClassMirror foundtype = currentLibrary.classes[typeName];
        if (foundtype == null) return;
        String constructorName =
            (match[2] == null) ? typeName : '$typeName.${match[2]}';
        final constructor =
            foundtype.constructors[constructorName];
        if (constructor == null) return;
        return makeLink(memberUrl(constructor));
      })();
      if (constructorLink != null) return constructorLink;

      // See if it's a member of another type
      final foreignMemberLink = (() {
        final match = new RegExp(r'([\w$]+)\.([\w$]+)').firstMatch(name);
        if (match == null) return;
        ClassMirror foundtype = currentLibrary.classes[match[1]];
        if (foundtype == null) return;
        MemberMirror foundMember = foundtype.members[match[2]];
        if (foundMember == null) return;
        return makeLink(memberUrl(foundMember));
      })();
      if (foreignMemberLink != null) return foreignMemberLink;

      ClassMirror foundType = currentLibrary.classes[name];
      if (foundType != null) {
        return makeLink(typeUrl(foundType));
      }

      // See if it's a top-level member in the current library.
      MemberMirror foundMember = currentLibrary.members[name];
      if (foundMember != null) {
        return makeLink(memberUrl(foundMember));
      }
    }

    // TODO(rnystrom): Should also consider:
    // * Names imported by libraries this library imports.
    // * Type parameters of the enclosing type.

    return new md.Element.text('code', name);
  }

  generateAppCacheManifest() {
    if (verbose) {
      print('Generating app cache manifest from output $outputDir');
    }
    startFile('appcache.manifest');
    write("CACHE MANIFEST\n\n");
    write("# VERSION: ${new DateTime.now()}\n\n");
    write("NETWORK:\n*\n\n");
    write("CACHE:\n");
    var toCache = new Directory.fromPath(outputDir);
    toCache.list(recursive: true).listen(
        (FileSystemEntity entity) {
          if (entity.isFile) {
            var filename = entity.path;
            if (filename.endsWith('appcache.manifest')) {
              return;
            }
            Path relativeFilePath = new Path(filename).relativeTo(outputDir);
            write("$relativeFilePath\n");
          }
        },
        onDone: () => endFile());
  }

  /**
   * Returns [:true:] if [type] should be regarded as an exception.
   */
  bool isException(TypeMirror type) {
    return type.simpleName.endsWith('Exception') ||
        type.simpleName.endsWith('Error');
  }

  /**
   * Returns the absolute path to [library] on the filesystem, or `null` if the
   * library doesn't exist on the local filesystem.
   */
  String _libraryPath(LibraryMirror library) =>
    importUriToPath(library.uri, packageRoot: _packageRoot);

  /**
   * Returns a list of classes in [library], including classes it exports from
   * hidden libraries.
   */
  List<ClassMirror> _libraryClasses(LibraryMirror library) =>
    _libraryContents(library, (lib) => lib.classes.values);

  /**
   * Returns a list of top-level members in [library], including members it
   * exports from hidden libraries.
   */
  List<MemberMirror> _libraryMembers(LibraryMirror library) =>
    _libraryContents(library, (lib) => lib.members.values);


  /**
   * Returns a list of elements in [library], including elements it exports from
   * hidden libraries. [fn] should return the element list for a single library,
   * which will then be merged across all exported libraries.
   */
  List<DeclarationMirror> _libraryContents(LibraryMirror library,
      List<DeclarationMirror> fn(LibraryMirror)) {
    var contents = fn(library).toList();
    var path = _libraryPath(library);
    if (path == null || _exports.exports[path] == null) return contents;


    contents.addAll(_exports.exports[path].expand((export) {
      var exportedLibrary = _librariesByPath[export.path];
      // TODO(nweiz): remove this check when issue 9645 is fixed.
      if (exportedLibrary == null) return [];
      if (shouldIncludeLibrary(exportedLibrary)) return [];
      return fn(exportedLibrary).where((declaration) =>
          export.isMemberVisible(displayName(declaration)));
    }));
    return contents;
  }

  /**
   * Returns the library in which [type] was defined. If [type] was defined in a
   * hidden library that was exported by another library, this returns the
   * exporter.
   */
  LibraryMirror _libraryFor(TypeMirror type) =>
    _visibleLibrary(type.library, displayName(type));

  /**
   * Returns the owner of [declaration]. If [declaration]'s owner is a hidden
   * library that was exported by another library, this returns the exporter.
   */
  DeclarationMirror _ownerFor(DeclarationMirror declaration) {
    var owner = declaration.owner;
    if (owner is! LibraryMirror) return owner;
    return _visibleLibrary(owner, displayName(declaration));
  }

  /**
   * Returns the best visible library that exports [name] from [library]. If
   * [library] is public, it will be returned.
   */
  LibraryMirror _visibleLibrary(LibraryMirror library, String name) {
    if (library == null) return null;

    var exports = _hiddenLibraryExports[_libraryPath(library)];
    if (exports == null) return library;

    var export = exports.firstWhere(
        (exp) => exp.isMemberVisible(name),
        orElse: () => null);
    if (export == null) return library;
    return _librariesByPath[export.exporter];
  }
}

/**
 * Used to report an unexpected error in the DartDoc tool or the
 * underlying data
 */
class InternalError {
  final String message;
  const InternalError(this.message);
  String toString() => "InternalError: '$message'";
}

/**
 * Computes the doc comment for the declaration mirror.
 *
 * Multiple comments are concatenated with newlines in between.
 */
String computeComment(DeclarationMirror mirror) {
  String text;
  for (InstanceMirror metadata in mirror.metadata) {
    if (metadata is CommentInstanceMirror) {
      CommentInstanceMirror comment = metadata;
      if (comment.isDocComment) {
        if (text == null) {
          text = comment.trimmedText;
        } else {
          text = '$text\n${comment.trimmedText}';
        }
      }
    }
  }
  return text;
}

/**
 * Computes the doc comment for the declaration mirror as a list.
 */
List<String> computeUntrimmedCommentAsList(DeclarationMirror mirror) {
  var text = <String>[];
  for (InstanceMirror metadata in mirror.metadata) {
    if (metadata is CommentInstanceMirror) {
      CommentInstanceMirror comment = metadata;
      if (comment.isDocComment) {
        text.add(comment.text);
      }
    }
  }
  return text;
}

class DocComment {
  final String text;
  md.Resolver dartdocResolver;
  List<md.InlineSyntax> dartdocSyntaxes;

  /**
   * Non-null if the comment is inherited from another declaration.
   */
  final ClassMirror inheritedFrom;

  DocComment(this.text, [this.inheritedFrom = null, this.dartdocSyntaxes,
      this.dartdocResolver]) {
    assert(text != null && !text.trim().isEmpty);
  }

  String toString() => text;

  String get html {
    return md.markdownToHtml(text,
        inlineSyntaxes: dartdocSyntaxes,
        linkResolver: dartdocResolver);
  }
}

class MdnComment implements DocComment {
  final String mdnComment;
  final String mdnUrl;

  MdnComment(String this.mdnComment, String this.mdnUrl);

  String get text => mdnComment;

  ClassMirror get inheritedFrom => null;

  String get html {
    // Wrap the mdn comment so we can highlight it and so we handle MDN scraped
    // content that lacks a top-level block tag.
   return '''
        <div class="mdn">
        $mdnComment
        <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div>
        </div>
        ''';
  }

  String toString() => mdnComment;
}
