// 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:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';

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

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.
String get scriptDir => path.dirname(Platform.script);

/**
 * Deletes and recreates the output directory at [path] if it exists.
 */
void cleanOutputDirectory(String path) {
  final outputDir = new Directory(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 DirectoryException 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(String from, String to) {
  print('Copying static files...');
  final completer = new Completer();
  final fromDir = new Directory(from);
  var futureList = [];
  fromDir.list(recursive: false).listen(
      (FileSystemEntity entity) {
        if (entity is File) {
          final name = path.basename(entity.path);
          // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store.
          if (name.startsWith('.')) return;

          File fromFile = entity;
          File toFile = new File(path.join(to, 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, String outputDir, String libPath, String tmpPath) {
  print('Compiling client JavaScript...');
  var clientScript = (mode == MODE_STATIC) ?  'static' : 'live-nav';
  var dartdocLibPath = path.join(libPath, 'lib', '_internal', 'dartdoc', 'lib');
  var dartPath = mode == MODE_STATIC ?
    path.join(tmpPath, 'client.dart') :
    path.join(dartdocLibPath, 'src', 'client', 'client-live-nav.dart');

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

  // dart2js takes a String, but it expects that to be a Uri, not a file
  // system path.
  libPath = path.toUri(libPath).toString();
  dartPath = path.toUri(dartPath).toString();

  return dart2js.compile(
      dartPath, libPath,
      options: const <String>['--categories=Client,Server', '--minify'])
  .then((jsCode) {
    if (jsCode == null) throw new StateError("No javascript was generated.");
    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. */
  String dartdocPath;

  /** Path to generate HTML files into. */
  String outputDir = '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]. */
  String _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, String libPath,
      String packageRoot) {
    _packageRoot = packageRoot;
    _exports = new ExportMap.parse(libraryList, packageRoot);
    var librariesToAnalyze = _exports.allExportedFiles.toList();
    librariesToAnalyze.addAll(libraryList.map((uri) => uri.toString()));

    // dart2js takes a String, but it expects that to be a Uri, not a file
    // system path.
    libPath = path.toUri(libPath).toString();

    if (packageRoot != null) {
      packageRoot = path.toUri(packageRoot).toString();
    }

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

  void _document(MirrorSystem mirrors) {
    _started = true;


    // Remove duplicated libraries. This is a hack because libraries can
    // get picked up multiple times (dartbug.com/11826) which will go away
    // with the new docgen. The reason we hit this issue is that we attempt
    // to dart2js.analyze all packages in the repo together, which results
    // in packages getting referenced with different URI's (../../pkg versus
    // ../../out/ReleaseIA32/packages versus package:).
    _sortedLibraries = new Map.fromIterable(
        mirrors.libraries.values.where(shouldIncludeLibrary),
        key: displayName).values.toList();

    // Sort the libraries by name (not key).
    _sortedLibraries.sort((x, y) {
      return displayName(x).toUpperCase().compareTo(
          displayName(y).toUpperCase());
    });

    _librariesByPath = <String, LibraryMirror>{};
    for (var library in mirrors.libraries.values) {
      var libraryPath = _libraryPath(library);
      if (libraryPath == null) continue;
      libraryPath = path.normalize(path.absolute(libraryPath));
      _librariesByPath[libraryPath] = 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 = path;
    _file = new StringBuffer();
  }

  void endFile() {
    final outPath = path.join(outputDir, _filePath);
    final dir = new Directory(path.dirname(outPath));
    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 DirectoryException catch (e) {
        // Ignore.
      }
    }

    writeString(new File(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.encode(createNavigationInfo()));
    endFile();
  }
  /// Whether dartdoc is running from within the Dart SDK or the
  /// Dart source repository.
  bool get runningFromSdk =>
    path.extension(Platform.script) == '.snapshot';

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

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

  void docNavigationDart() {
    var tmpDir = new Directory(tmpPath);
    if (!tmpDir.existsSync()) {
        tmpDir.createSync();
    }
    String jsonString = JSON.encode(createNavigationInfo());
    String dartString = jsonString.replaceAll(r"$", r"\$");
    var filePath = path.join(tmpPath, 'client.dart');

    var clientDir = path.join(normalizedDartdocPath,'lib', 'src', 'client');

    writeString(new File(filePath),
        '''library client;
        import 'dart:html';
        import 'dart:json';
        import r'${path.toUri(path.join(clientDir, 'client-shared.dart'))}';
        import r'${path.toUri(path.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;

    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);
    }

    _currentLibrary = null;
  }

  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();

    _currentType = null;
  }

  /** 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>');

    _currentMember = null;
  }

  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>');

    _currentMember = null;
  }

  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;
    }

    DeclarationMirror declaration = currentMember;
    if (declaration == null) declaration = currentType;
    if (declaration == null) declaration = currentLibrary;
    if (declaration != null) {
      declaration = lookupQualifiedInScope(declaration, name);
    }

    if (declaration != null) {
      if (declaration is TypeVariableMirror) {
        return makeLink(typeUrl(declaration.owner));
      } if (declaration is TypeMirror) {
        return makeLink(typeUrl(declaration));
      } else if (declaration is MethodMirror) {
        return makeLink(memberUrl(declaration));
      }
    }

    // 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(outputDir);
    toCache.list(recursive: true).listen(
        (FileSystemEntity entity) {
          if (entity is File) {
            var filename = entity.path;
            if (filename.endsWith('appcache.manifest')) {
              return;
            }
            String relativeFilePath = path.relative(filename, from: 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;
}
