// 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.

/**
 * **docgen** is a tool for creating machine readable representations of Dart
 * code metadata, including: classes, members, comments and annotations.
 *
 * docgen is run on a `.dart` file or a directory containing `.dart` files.
 *
 *      $ dart docgen.dart [OPTIONS] [FILE/DIR]
 *
 * This creates files called `docs/<library_name>.yaml` in your current
 * working directory.
 */
library docgen;

import 'dart:io';
import 'dart:json';
import 'dart:async';

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

import 'dart2yaml.dart';
import 'src/io.dart';
import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart'
    as dart2js;
import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
import '../../../sdk/lib/_internal/libraries.dart';

var logger = new Logger('Docgen');

const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';

/// Current library being documented to be used for comment links.
LibraryMirror _currentLibrary;

/// Current class being documented to be used for comment links.
ClassMirror _currentClass;

/// Current member being documented to be used for comment links.
MemberMirror _currentMember;

/// Resolves reference links in doc comments.
markdown.Resolver linkResolver;

/// Index of all indexable items. This also ensures that no class is 
/// created more than once. 
Map<String, Indexable> entityMap = new Map<String, Indexable>();

/// This is set from the command line arguments flag --include-private 
bool _includePrivate = false;

/**
 * Docgen constructor initializes the link resolver for markdown parsing.
 * Also initializes the command line arguments.
 *
 * [packageRoot] is the packages directory of the directory being analyzed.
 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will
 * also be documented.
 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented.
 * This option is useful when only the SDK libraries are needed.
 *
 * Returns `true` if docgen sucessfuly completes.
 */
Future<bool> docgen(List<String> files, {String packageRoot,
    bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false,
    bool parseSdk: false, bool append: false}) {
  _includePrivate = includePrivate;
  if (!append) {
    var dir = new Directory('docs');
    if (dir.existsSync()) dir.deleteSync(recursive: true);
  }
  
  if (packageRoot == null && !parseSdk) {
    var type = FileSystemEntity.typeSync(files.first);
    if (type == FileSystemEntityType.DIRECTORY) {
      packageRoot = _findPackageRoot(files.first);
    } else if (type == FileSystemEntityType.FILE) {
      logger.warning('WARNING: No package root defined. If Docgen fails, try '
          'again by setting the --package-root option.');
    }
  }
  logger.info('Package Root: ${packageRoot}');

  linkResolver = (name) =>
      fixReference(name, _currentLibrary, _currentClass, _currentMember);

  return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk)
    .then((MirrorSystem mirrorSystem) {
      if (mirrorSystem.libraries.isEmpty) {
        throw new StateError('No library mirrors were created.');
      }
      _documentLibraries(mirrorSystem.libraries.values,
          includeSdk: includeSdk, outputToYaml: outputToYaml, append: append);

      return true;
    });
}

List<String> _listLibraries(List<String> args) {
  if (args.length != 1) throw new UnsupportedError(USAGE);
  var libraries = new List<String>();
  var type = FileSystemEntity.typeSync(args[0]);

  if (type == FileSystemEntityType.FILE) {
    libraries.add(path.absolute(args[0]));
    logger.info('Added to libraries: ${libraries.last}');
  } else {
    libraries.addAll(_listDartFromDir(args[0]));
  }
  return libraries;
}

List<String> _listDartFromDir(String args) {
  var files = listDir(args, recursive: true);
  // To avoid anaylzing package files twice, only files with paths not
  // containing '/packages' will be added. The only exception is if the file to
  // analyze already has a '/package' in its path.
  return files.where((f) => f.endsWith('.dart') &&
      (!f.contains('${path.separator}packages') || 
          args.contains('${path.separator}packages'))).toList()
      ..forEach((lib) => logger.info('Added to libraries: $lib'));
}

String _findPackageRoot(String directory) {
  var files = listDir(directory, recursive: true);
  // Return '' means that there was no pubspec.yaml and therefor no packageRoot.
  String packageRoot = files.firstWhere((f) =>
      f.endsWith('${path.separator}pubspec.yaml'), orElse: () => '');
  if (packageRoot != '') {
    packageRoot = path.join(path.dirname(packageRoot), 'packages');
  }
  return packageRoot;
}

List<String> _listSdk() {
  var sdk = new List<String>();
  LIBRARIES.forEach((String name, LibraryInfo info) {
    if (info.documented) {
      sdk.add('dart:$name');
      logger.info('Add to SDK: ${sdk.last}');
    }
  });
  return sdk;
}

/**
 * Analyzes set of libraries by getting a mirror system and triggers the
 * documentation of the libraries.
 */
Future<MirrorSystem> getMirrorSystem(List<String> args, {String packageRoot,
    bool parseSdk: false}) {
  var libraries = !parseSdk ? _listLibraries(args) : _listSdk();
  if (libraries.isEmpty) throw new StateError('No Libraries.');
  // Finds the root of SDK library based off the location of docgen.
  var sdkRoot = path.join(path.dirname(path.dirname(path.dirname(path.dirname(
        path.absolute(new Options().script))))), 'sdk');
  logger.info('SDK Root: ${sdkRoot}');
  return _analyzeLibraries(libraries, sdkRoot, packageRoot: packageRoot);
}

/**
 * Analyzes set of libraries and provides a mirror system which can be used
 * for static inspection of the source code.
 */
Future<MirrorSystem> _analyzeLibraries(List<String> libraries,
      String libraryRoot, {String packageRoot}) {
  SourceFileProvider provider = new SourceFileProvider();
  api.DiagnosticHandler diagnosticHandler =
        new FormattingDiagnosticHandler(provider).diagnosticHandler;
  Uri libraryUri = new Uri(scheme: 'file', path: appendSlash(libraryRoot));
  Uri packageUri = null;
  if (packageRoot != null) {
    packageUri = new Uri(scheme: 'file', path: appendSlash(packageRoot)); 
  }
  List<Uri> librariesUri = <Uri>[];
  libraries.forEach((library) {
    librariesUri.add(currentDirectory.resolve(library));
  });
  return dart2js.analyze(librariesUri, libraryUri, packageUri,
      provider.readStringFromUri, diagnosticHandler,
      ['--preserve-comments', '--categories=Client,Server'])
      ..catchError((error) {
        logger.severe('Error: Failed to create mirror system. ');
        // TODO(janicejl): Use the stack trace package when bug is resolved.
        // Currently, a string is thrown when it fails to create a mirror
        // system, and it is not possible to use the stack trace. BUG(#11622)
        // To avoid printing the stack trace.
        exit(1);
      });
}

/**
 * Creates documentation for filtered libraries.
 */
void _documentLibraries(List<LibraryMirror> libs,
    {bool includeSdk: false, bool outputToYaml: true, bool append: false}) {
  libs.forEach((lib) {
    // Files belonging to the SDK have a uri that begins with 'dart:'.
    if (includeSdk || !lib.uri.toString().startsWith('dart:')) {
      var library = generateLibrary(lib);
      entityMap[library.qualifiedName] = library;
    }
  });
  // After everything is created, do a pass through all classes to make sure no
  // intermediate classes created by mixins are included. 
  entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid());
  // Everything is a subclass of Object, therefore empty the list to avoid a
  // giant list of subclasses to be printed out. 
  entityMap['dart.core.Object'].subclasses.clear();
  
  var filteredEntities = entityMap.values.where(_isVisible);
  // Output libraries and classes to file after all information is generated.
  filteredEntities.where((e) => e is Class || e is Library).forEach((output) {
    _writeIndexableToFile(output, outputToYaml);
  });
  // Outputs a text file with a list of libraries available after creating all
  // the libraries. This will help the viewer know what libraries are available
  // to read in.
  _writeToFile(filteredEntities.where((e) => e is Library)
      .map((e) => e.qualifiedName).join('\n'), 'library_list.txt', 
      append: append);
  // Outputs all the qualified names documented. This will help generate search
  // results. 
  _writeToFile(filteredEntities.map((e) => e.qualifiedName).join('\n'), 
      'index.txt', append: append);
}

Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
  _currentLibrary = library;
  var result = new Library(library.qualifiedName, _commentToHtml(library),
      _variables(library.variables),
      _methods(library.functions),
      _classes(library.classes), _isPrivate(library));
  logger.fine('Generated library for ${result.name}');
  return result;
}

void _writeIndexableToFile(Indexable result, bool outputToYaml) {
  if (outputToYaml) {
    _writeToFile(getYamlString(result.toMap()), '${result.qualifiedName}.yaml');
  } else {
    _writeToFile(stringify(result.toMap()), '${result.qualifiedName}.json');
  }
}

/**
 * Returns true if a library name starts with an underscore, and false 
 * otherwise.
 * 
 * An example that starts with _ is _js_helper.
 * An example that contains ._ is dart._collection.dev
 */
// This is because LibraryMirror.isPrivate returns `false` all the time. 
bool _isLibraryPrivate(LibraryMirror mirror) {
  if (mirror.simpleName.startsWith('_') || mirror.simpleName.contains('._')) {
    return true;
  }
  return false;
}

/**
 * A declaration is private if itself is private, or the owner is private. 
 */
bool _isPrivate(DeclarationMirror mirror) {
  if (mirror is LibraryMirror) {
    return _isLibraryPrivate(mirror);
  } else if (mirror.owner is LibraryMirror) {
    return (mirror.isPrivate || _isLibraryPrivate(mirror.owner));
  } else { 
    return (mirror.isPrivate || _isPrivate(mirror.owner));
  }
}

bool _isVisible(Indexable item) {
  return _includePrivate || !item.isPrivate;
}

/**
 * Returns a list of meta annotations assocated with a mirror.
 */
List<String> _annotations(DeclarationMirror mirror) {
  var annotations = mirror.metadata.where((e) =>
      e is dart2js.Dart2JsConstructedConstantMirror);
  return annotations.map((e) => e.type.qualifiedName).toList();
}

/**
 * Returns any documentation comments associated with a mirror with
 * simple markdown converted to html.
 */
String _commentToHtml(DeclarationMirror mirror) {
  String commentText;
  mirror.metadata.forEach((metadata) {
    if (metadata is CommentInstanceMirror) {
      CommentInstanceMirror comment = metadata;
      if (comment.isDocComment) {
        if (commentText == null) {
          commentText = comment.trimmedText;
        } else {
          commentText = '$commentText ${comment.trimmedText}';
        }
      }
    }
  });
  
  commentText = commentText == null ? '' : 
      markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver);
  return commentText;
}

/**
 * Converts all [foo] references in comments to <a>libraryName.foo</a>.
 */
markdown.Node fixReference(String name, LibraryMirror currentLibrary,
    ClassMirror currentClass, MemberMirror currentMember) {
  var reference;
  var memberScope = currentMember == null ?
      null : currentMember.lookupInScope(name);
  if (memberScope != null) reference = memberScope.qualifiedName;
  else {
    var classScope = currentClass == null ?
        null : currentClass.lookupInScope(name);
    reference = classScope != null ? classScope.qualifiedName : name;
  }
  return new markdown.Element.text('a', reference);
}

/**
 * Returns a map of [Variable] objects constructed from [mirrorMap].
 */
Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) {
  var data = {};
  // TODO(janicejl): When map to map feature is created, replace the below with
  // a filter. Issue(#9590).
  mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
    _currentMember = mirror;
    if (_includePrivate || !_isPrivate(mirror)) {
      entityMap[mirror.qualifiedName] = new Variable(mirrorName, mirror.isFinal,
         mirror.isStatic, mirror.isConst, _type(mirror.type),
         _commentToHtml(mirror), _annotations(mirror), mirror.qualifiedName,
         _isPrivate(mirror), mirror.owner.qualifiedName);
      data[mirrorName] = entityMap[mirror.qualifiedName];
    }
  });
  return data;
}

/**
 * Returns a map of [Method] objects constructed from [mirrorMap].
 */
MethodGroup _methods(Map<String, MethodMirror> mirrorMap) {
  var group = new MethodGroup();
  mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
    if (_includePrivate || !_isPrivate(mirror)) {
      group.addMethod(mirror);
    }
  });
  return group;
} 

/**
 * Returns the [Class] for the given [mirror] has already been created, and if 
 * it does not exist, creates it.
 */
Class _class(ClassMirror mirror) {
  var clazz = entityMap[mirror.qualifiedName];
  if (clazz == null) {
    var superclass = mirror.superclass != null ? 
        _class(mirror.superclass) : null;
    var interfaces = 
        mirror.superinterfaces.map((interface) => _class(interface));
    clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), 
        interfaces.toList(), _variables(mirror.variables),
        _methods(mirror.methods), _annotations(mirror), _generics(mirror), 
        mirror.qualifiedName, _isPrivate(mirror), mirror.owner.qualifiedName);
    entityMap[mirror.qualifiedName] = clazz;
  }
  return clazz;
}

/**
 * Returns a map of [Class] objects constructed from [mirrorMap].
 */
ClassGroup _classes(Map<String, ClassMirror> mirrorMap) {
  var group = new ClassGroup();
  mirrorMap.forEach((String mirrorName, ClassMirror mirror) {    
      group.addClass(mirror);
  });
  return group;
}

/**
 * Returns a map of [Parameter] objects constructed from [mirrorList].
 */
Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) {
  var data = {};
  mirrorList.forEach((ParameterMirror mirror) {
    _currentMember = mirror;
    data[mirror.simpleName] = new Parameter(mirror.simpleName, 
        mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, 
        _type(mirror.type), mirror.defaultValue, 
        _annotations(mirror));
  });
  return data;
}

/**
 * Returns a map of [Generic] objects constructed from the class mirror. 
 */
Map<String, Generic> _generics(ClassMirror mirror) {
  return new Map.fromIterable(mirror.typeVariables, 
      key: (e) => e.toString(), 
      value: (e) => new Generic(e.toString(), e.upperBound.qualifiedName));
}

/**
 * Returns a single [Type] object constructed from the Method.returnType 
 * Type mirror. 
 */
Type _type(TypeMirror mirror) {
  return new Type(mirror.qualifiedName, _typeGenerics(mirror));
}

/**
 * Returns a list of [Type] objects constructed from TypeMirrors. 
 */
List<Type> _typeGenerics(TypeMirror mirror) {
  if (mirror is ClassMirror && !mirror.isTypedef) {
    var innerList = [];
    mirror.typeArguments.forEach((e) {
      innerList.add(new Type(e.qualifiedName, _typeGenerics(e)));
    });
    return innerList;
  }
  return [];
}

/**
 * Writes text to a file in the 'docs' directory.
 */
void _writeToFile(String text, String filename, {bool append: false}) {
  Directory dir = new Directory('docs');
  if (!dir.existsSync()) {
    dir.createSync();
  }
  File file = new File('docs/$filename');
  if (!file.existsSync()) {
    file.createSync();
  }
  file.writeAsString(text, mode: append ? FileMode.APPEND : FileMode.WRITE);
}

/**
 * Transforms the map by calling toMap on each value in it.
 */
Map recurseMap(Map inputMap) {
  var outputMap = {};
  inputMap.forEach((key, value) {
    if (value is Map) {
      outputMap[key] = recurseMap(value);
    } else {
      outputMap[key] = value.toMap();
    }
  });
  return outputMap;
}

bool isError(String qualifiedName) {
  return qualifiedName.toLowerCase().contains('error') || 
      qualifiedName.toLowerCase().contains('exception');
}

/**
 * A class representing all programming constructs, like library or class. 
 */
class Indexable {
  String name;
  String qualifiedName;
  bool isPrivate;
  
  /// Documentation comment with converted markdown.
  String comment;
  
  /// Qualified Name of the owner of this Indexable Item.
  /// For Library, owner will be ""; 
  String owner;
  
  Indexable(this.name, this.comment, this.qualifiedName, this.isPrivate,
      this.owner);
}

/**
 * A class containing contents of a Dart library.
 */
class Library extends Indexable {

  /// Top-level variables in the library.
  Map<String, Variable> variables;

  /// Top-level functions in the library.
  MethodGroup functions;
  
  /// Classes defined within the library
  ClassGroup classes;

  Library(String name, String comment, this.variables,
      this.functions, this.classes, bool isPrivate) : super(name, comment, 
          name, isPrivate, "") {}

  /// Generates a map describing the [Library] object.
  Map toMap() => {
    'name': name,
    'qualifiedname': qualifiedName,
    'comment': comment,
    'variables': recurseMap(variables),
    'functions': functions.toMap(),
    'classes': classes.toMap()
  };
}

/**
 * A class containing contents of a Dart class.
 */
class Class extends Indexable {

  /// List of the names of interfaces that this class implements.
  List<Class> interfaces = [];
  
  /// Names of classes that extends or implements this class. 
  Set<String> subclasses = new Set<String>();

  /// Top-level variables in the class.
  Map<String, Variable> variables;
  
  /// Inherited variables in the class.
  Map<String, Variable> inheritedVariables = {};

  /// Methods in the class.
  MethodGroup methods;
  
  /// Inherited methods in the class.
  MethodGroup inheritedMethods = new MethodGroup();
  
  /// Generic infomation about the class. 
  Map<String, Generic> generics;
  
  Class superclass;

  /// List of the meta annotations on the class.
  List<String> annotations;
  
  Class(String name, this.superclass, String comment, this.interfaces, 
      this.variables, this.methods, this.annotations, this.generics,
      String qualifiedName, bool isPrivate, String owner) : super(name, comment,
          qualifiedName, isPrivate, owner) {}

  /**
   * Returns a list of all the parent classes. 
   */
  List<Class> parent() {
    var parent = superclass == null ? [] : [superclass];
    parent.addAll(interfaces);
    return parent;
  }
  
  /**
   * Add all inherited variables and methods from the provided superclass.
   * If [_includePrivate] is true, it also adds the variables and methods from 
   * the superclass. 
   */
  void addInherited(Class superclass) {
    inheritedVariables.addAll(superclass.inheritedVariables);
    if (_isVisible(superclass)) {
      inheritedVariables.addAll(superclass.variables);
    }
    inheritedMethods.addInherited(superclass);
  }
  
  /**
   * Add the subclass to the class. 
   * 
   * If [this] is private, it will add the subclass to the list of subclasses in
   * the superclasses. 
   */
  void addSubclass(Class subclass) {
    if (!_includePrivate && isPrivate) {
      if (superclass != null) superclass.addSubclass(subclass);
      interfaces.forEach((interface) {
        interface.addSubclass(subclass);
      });
    } else {
      subclasses.add(subclass.qualifiedName);
    }
  }
  
  /**
   * Check that the class exists in the owner library.
   *  
   * If it does not exist in the owner library, it is a mixin applciation and 
   * should be removed. 
   */
  void makeValid() {
    var library = entityMap[owner];
    if (!library.classes.containsKey(name)) {
      this.isPrivate = true;
      // Since we are now making the mixin a private class, make all elements 
      // with the mixin as an owner private too. 
      entityMap.values.where((e) => e.owner == qualifiedName)
        .forEach((element) => element.isPrivate = true);
      // Move the subclass up to the next public superclass
      subclasses.forEach((subclass) => addSubclass(entityMap[subclass]));
    }
  }
  
  /** 
   * If a class extends a private superclass, find the closest public superclass
   * of the private superclass. 
   */
  String validSuperclass() {
    if (superclass == null) return 'dart.core.Object';
    if (_isVisible(superclass)) return superclass.qualifiedName;
    return superclass.validSuperclass();
  }
  
  /// Generates a map describing the [Class] object.
  Map toMap() => {
    'name': name,
    'qualifiedname': qualifiedName,
    'comment': comment,
    'superclass': validSuperclass(),
    'implements': new List.from(interfaces.where(_isVisible)
        .map((e) => e.qualifiedName)),
    'subclass': new List.from(subclasses),
    'variables': recurseMap(variables),
    'inheritedvariables': recurseMap(inheritedVariables),
    'methods': methods.toMap(),
    'inheritedmethods': inheritedMethods.toMap(),
    'annotations': new List.from(annotations),
    'generics': recurseMap(generics)
  };
}

/**
 * A container to categorize classes into the following groups: abstract 
 * classes, regular classes, typedefs, and errors. 
 */
class ClassGroup {
  Map<String, Class> abstractClasses = {};
  Map<String, Class> regularClasses = {};
  Map<String, Typedef> typedefs = {};
  Map<String, Class> errors = {};
  
  void addClass(ClassMirror mirror) {
    _currentClass = mirror;
    var clazz = _class(mirror);
   
    // Adding inherited parent variables and methods. 
    clazz.parent().forEach((parent) {
      if (_isVisible(clazz)) {
        parent.addSubclass(clazz);
      }
      clazz.addInherited(parent);
    });
    
    if (isError(mirror.qualifiedName)) {
      errors[mirror.simpleName] = clazz;
    } else if (mirror.isTypedef) {
      if (_includePrivate || !mirror.isPrivate) {
        entityMap[mirror.qualifiedName] = new Typedef(mirror.simpleName, 
            mirror.value.returnType.qualifiedName, _commentToHtml(mirror), 
            _generics(mirror), _parameters(mirror.value.parameters),
            _annotations(mirror), mirror.qualifiedName,  _isPrivate(mirror), 
            mirror.owner.qualifiedName);
        typedefs[mirror.simpleName] = entityMap[mirror.qualifiedName];
      }
    } else if (mirror.isAbstract) {
      abstractClasses[mirror.simpleName] = clazz;
    } else if (mirror.isClass) {
      regularClasses[mirror.simpleName] = clazz;
    } else {
      throw new ArgumentError('${mirror.simpleName} - no class type match. ');
    }
  }
  
  /**
   * Checks if the given name is a key for any of the Class Maps. 
   */
  bool containsKey(String name) {
    return abstractClasses.containsKey(name) ||
        regularClasses.containsKey(name) ||
        errors.containsKey(name);
  }
  
  Map toMap() => {
    'abstract': new List.from(abstractClasses.values
        .where(_isVisible).map((e) => e.qualifiedName)),
    'class': new List.from(regularClasses.values
        .where(_isVisible).map((e) => e.qualifiedName)),
    'typedef': recurseMap(typedefs),
    'error': new List.from(errors.values
        .where(_isVisible).map((e) => e.qualifiedName))
  };
}

class Typedef extends Indexable {
  String returnType;
  
  Map<String, Parameter> parameters;
  
  /// Generic information about the typedef. 
  Map<String, Generic> generics;
  
  /// List of the meta annotations on the typedef. 
  List<String> annotations;
  
  Typedef(String name, this.returnType, String comment, this.generics, 
      this.parameters, this.annotations,
      String qualifiedName, bool isPrivate, String owner) : super(name, comment,
          qualifiedName, isPrivate, owner) {}
  
  Map toMap() => {
    'name': name,
    'qualifiedname': qualifiedName,
    'comment': comment,
    'return': returnType,
    'parameters': recurseMap(parameters),
    'annotations': new List.from(annotations),
    'generics': recurseMap(generics)
  };
}

/**
 * A class containing properties of a Dart variable.
 */
class Variable extends Indexable {

  bool isFinal;
  bool isStatic;
  bool isConst;
  Type type;

  /// List of the meta annotations on the variable.
  List<String> annotations;
  
  Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, 
      String comment, this.annotations, String qualifiedName, bool isPrivate,
      String owner) : super(name, comment, qualifiedName, isPrivate, owner);
  
  /// Generates a map describing the [Variable] object.
  Map toMap() => {
    'name': name,
    'qualifiedname': qualifiedName,
    'comment': comment,
    'final': isFinal.toString(),
    'static': isStatic.toString(),
    'constant': isConst.toString(),
    'type': new List.filled(1, type.toMap()),
    'annotations': new List.from(annotations)
  };
}

/**
 * A class containing properties of a Dart method.
 */
class Method extends Indexable {

  /// Parameters for this method.
  Map<String, Parameter> parameters;

  bool isStatic;
  bool isAbstract;
  bool isConst;
  Type returnType;
  
  /// List of the meta annotations on the method.
  List<String> annotations;
  
  Method(String name, this.isStatic, this.isAbstract, this.isConst, 
      this.returnType, String comment, this.parameters, this.annotations,
      String qualifiedName, bool isPrivate, String owner) : super(name, comment,
          qualifiedName, isPrivate, owner);
  
  /// Generates a map describing the [Method] object.
  Map toMap() => {
    'name': name,
    'qualifiedname': qualifiedName,
    'comment': comment,
    'static': isStatic.toString(),
    'abstract': isAbstract.toString(),
    'constant': isConst.toString(),
    'return': new List.filled(1, returnType.toMap()),
    'parameters': recurseMap(parameters),
    'annotations': new List.from(annotations)
  };
}

/**
 * A container to categorize methods into the following groups: setters, 
 * getters, constructors, operators, regular methods. 
 */
class MethodGroup {
  Map<String, Method> setters = {};
  Map<String, Method> getters = {};
  Map<String, Method> constructors = {};
  Map<String, Method> operators = {};
  Map<String, Method> regularMethods = {};
  
  void addMethod(MethodMirror mirror) {
    var method = new Method(mirror.simpleName, mirror.isStatic, 
        mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), 
        _commentToHtml(mirror), _parameters(mirror.parameters), 
        _annotations(mirror), mirror.qualifiedName, _isPrivate(mirror),
        mirror.owner.qualifiedName);
    entityMap[mirror.qualifiedName] = method;
    _currentMember = mirror;
    if (mirror.isSetter) {
      setters[mirror.simpleName] = method;
    } else if (mirror.isGetter) {
      getters[mirror.simpleName] = method;
    } else if (mirror.isConstructor) {
      constructors[mirror.simpleName] = method;
    } else if (mirror.isOperator) {
      operators[mirror.simpleName] = method;
    } else if (mirror.isRegularMethod) {
      regularMethods[mirror.simpleName] = method;
    } else {
      throw new ArgumentError('${mirror.simpleName} - no method type match');
    }
  }
  
  void addInherited(Class parent) {
    setters.addAll(parent.inheritedMethods.setters);
    getters.addAll(parent.inheritedMethods.getters);
    operators.addAll(parent.inheritedMethods.operators);
    regularMethods.addAll(parent.inheritedMethods.regularMethods);
    if (_isVisible(parent)) {
      setters.addAll(parent.methods.setters);
      getters.addAll(parent.methods.getters);
      operators.addAll(parent.methods.operators);
      regularMethods.addAll(parent.methods.regularMethods);
    }
  }
  
  Map toMap() => {
    'setters': recurseMap(setters),
    'getters': recurseMap(getters),
    'constructors': recurseMap(constructors),
    'operators': recurseMap(operators),
    'methods': recurseMap(regularMethods)
  };
}

/**
 * A class containing properties of a Dart method/function parameter.
 */
class Parameter {

  String name;
  bool isOptional;
  bool isNamed;
  bool hasDefaultValue;
  Type type;
  String defaultValue;

  /// List of the meta annotations on the parameter.
  List<String> annotations;
  
  Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, 
      this.type, this.defaultValue, this.annotations);
  
  /// Generates a map describing the [Parameter] object.
  Map toMap() => {
    'name': name,
    'optional': isOptional.toString(),
    'named': isNamed.toString(),
    'default': hasDefaultValue.toString(),
    'type': new List.filled(1, type.toMap()),
    'value': defaultValue,
    'annotations': new List.from(annotations)
  };
}

/**
 * A class containing properties of a Generic. 
 */
class Generic {
  String name;
  String type;
  
  Generic(this.name, this.type);
  
  Map toMap() => {
    'name': name,
    'type': type
  };
}

/**
 * Holds the name of a return type, and its generic type parameters.
 * 
 * Return types are of a form [outer]<[inner]>.
 * If there is no [inner] part, [inner] will be an empty list. 
 * 
 * For example:
 *        int size()  
 *          "return" : 
 *            - "outer" : "dart.core.int"
 *              "inner" :
 * 
 *        List<String> toList()
 *          "return" :
 *            - "outer" : "dart.core.List"
 *              "inner" : 
 *                - "outer" : "dart.core.String"
 *                  "inner" :
 *        
 *        Map<String, List<int>>
 *          "return" : 
 *            - "outer" : "dart.core.Map"
 *              "inner" :
 *                - "outer" : "dart.core.String"
 *                  "inner" :
 *                - "outer" : "dart.core.List"
 *                  "inner" :
 *                    - "outer" : "dart.core.int"
 *                      "inner" :
 */
class Type {
  String outer;
  List<Type> inner;
  
  Type(this.outer, this.inner);
  
  Map toMap() => {
    'outer': outer,
    'inner': new List.from(inner.map((e) => e.toMap()))
  };
}