// 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);
  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));
          fromFile.openRead().pipe(toFile.openWrite());
        }
      },
      onDone: () => 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) {
  print('Compiling client JavaScript...');

  // TODO(nweiz): don't run this in an isolate when issue 9815 is fixed.
  return spawnFunction(_compileScript).call({
    'mode': mode,
    'outputDir': outputDir.toNativePath(),
    'libPath': libPath.toNativePath()
  }).then((result) {
    if (result.first == 'success') return;
    throw result[1] + (result[2] == null ? '' : '\n' + result[2]);
  });
}

void _compileScript() {
  port.receive((message, replyTo) {
    new Future.sync(() {
      var clientScript = (message['mode'] == MODE_STATIC) ?
          'static' : 'live-nav';
      var dartPath = pathos.join(message['libPath'], 'lib', '_internal',
          'dartdoc', 'lib', 'src', 'client', 'client-$clientScript.dart');
      var jsPath = pathos.join(message['outputDir'], 'client-$clientScript.js');

      return dart2js.compile(
          new Path(dartPath), new Path(message['libPath']),
          options: const <String>['--categories=Client,Server', '--minify'])
      .then((jsCode) {
        writeString(new File(jsPath), jsCode);
      });
    }).then((_) {
      replyTo.send(['success']);
    }).catchError((error) {
      var trace = getAttachedStackTrace(error);
      var traceString = trace == null ? null : trace.toString();
      replyTo.send(['error', error.toString(), traceString]);
    });
  });
}

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

  /**
   * 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() {
    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();
  }

  void docNavigationDart() {
    final dir = new Directory.fromPath(tmpPath);
    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.
      }
    }
    String jsonString = json.stringify(createNavigationInfo());
    String dartString = jsonString.replaceAll(r"$", r"\$");
    final filePath = tmpPath.append('nav.dart');
    writeString(new File.fromPath(filePath),
        '''part of client;
           get json => $dartString;''');
  }

  Path get tmpPath => dartdocPath.append('tmp');

  void cleanup() {
    final dir = new Directory.fromPath(tmpPath);
    if (dir.existsSync()) {
      dir.deleteSync(recursive: true);
    }
  }

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