// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library analysis_server.src.status.get_handler;

import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/domain_diagnostic.dart';
import 'package:analysis_server/src/domain_execution.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/operation/operation_analysis.dart';
import 'package:analysis_server/src/operation/operation_queue.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/socket_server.dart';
import 'package:analysis_server/src/status/ast_writer.dart';
import 'package:analysis_server/src/status/element_writer.dart';
import 'package:analysis_server/src/status/validator.dart';
import 'package:analysis_server/src/utilities/average.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/driver.dart';
import 'package:analyzer/src/task/html.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/html.dart';
import 'package:analyzer/task/model.dart';
import 'package:plugin/plugin.dart';

/**
 * A function that can be used to generate HTML output into the given [buffer].
 * The HTML that is generated must be valid (special characters must already be
 * encoded).
 */
typedef void HtmlGenerator(StringBuffer buffer);

class ElementCounter extends RecursiveElementVisitor {
  Map<Type, int> counts = new HashMap<Type, int>();
  int elementsWithDocs = 0;
  int totalDocSpan = 0;

  void visit(Element element) {
    String comment = element.documentationComment;
    if (comment != null) {
      ++elementsWithDocs;
      totalDocSpan += comment.length;
    }

    Type type = element.runtimeType;
    if (counts[type] == null) {
      counts[type] = 1;
    } else {
      counts[type]++;
    }
  }

  @override
  visitClassElement(ClassElement element) {
    visit(element);
    super.visitClassElement(element);
  }

  @override
  visitCompilationUnitElement(CompilationUnitElement element) {
    visit(element);
    super.visitCompilationUnitElement(element);
  }

  @override
  visitConstructorElement(ConstructorElement element) {
    visit(element);
    super.visitConstructorElement(element);
  }

  @override
  visitExportElement(ExportElement element) {
    visit(element);
    super.visitExportElement(element);
  }

  @override
  visitFieldElement(FieldElement element) {
    visit(element);
    super.visitFieldElement(element);
  }

  @override
  visitFieldFormalParameterElement(FieldFormalParameterElement element) {
    visit(element);
    super.visitFieldFormalParameterElement(element);
  }

  @override
  visitFunctionElement(FunctionElement element) {
    visit(element);
    super.visitFunctionElement(element);
  }

  @override
  visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
    visit(element);
    super.visitFunctionTypeAliasElement(element);
  }

  @override
  visitImportElement(ImportElement element) {
    visit(element);
    super.visitImportElement(element);
  }

  @override
  visitLabelElement(LabelElement element) {
    visit(element);
    super.visitLabelElement(element);
  }

  @override
  visitLibraryElement(LibraryElement element) {
    visit(element);
    super.visitLibraryElement(element);
  }

  @override
  visitLocalVariableElement(LocalVariableElement element) {
    visit(element);
    super.visitLocalVariableElement(element);
  }

  @override
  visitMethodElement(MethodElement element) {
    visit(element);
    super.visitMethodElement(element);
  }

  @override
  visitMultiplyDefinedElement(MultiplyDefinedElement element) {
    visit(element);
    super.visitMultiplyDefinedElement(element);
  }

  @override
  visitParameterElement(ParameterElement element) {
    visit(element);
    super.visitParameterElement(element);
  }

  @override
  visitPrefixElement(PrefixElement element) {
    visit(element);
    super.visitPrefixElement(element);
  }

  @override
  visitPropertyAccessorElement(PropertyAccessorElement element) {
    visit(element);
    super.visitPropertyAccessorElement(element);
  }

  @override
  visitTopLevelVariableElement(TopLevelVariableElement element) {
    visit(element);
    super.visitTopLevelVariableElement(element);
  }

  @override
  visitTypeParameterElement(TypeParameterElement element) {
    visit(element);
    super.visitTypeParameterElement(element);
  }
}

/**
 * Instances of the class [GetHandler] handle GET requests.
 */
class GetHandler {
  /**
   * The path used to request overall performance information.
   */
  static const String ANALYSIS_PERFORMANCE_PATH = '/perf/analysis';

  /**
   * The path used to request information about a element model.
   */
  static const String AST_PATH = '/ast';

  /**
   * The path used to request information about the cache entry corresponding
   * to a single file.
   */
  static const String CACHE_ENTRY_PATH = '/cache_entry';

  /**
   * The path used to request the list of source files in a certain cache
   * state.
   */
  static const String CACHE_STATE_PATH = '/cache_state';

  /**
   * The path used to request code completion information.
   */
  static const String COMPLETION_PATH = '/completion';

  /**
   * The path used to request communication performance information.
   */
  static const String COMMUNICATION_PERFORMANCE_PATH = '/perf/communication';

  /**
   * The path used to request diagnostic information for a single context.
   */
  static const String CONTEXT_DIAGNOSTICS_PATH = '/diagnostic/context';

  /**
   * The path used to request running a validation report for a single context.
   */
  static const String CONTEXT_VALIDATION_DIAGNOSTICS_PATH =
      '/diagnostic/contextValidation';

  /**
   * The path used to request information about a specific context.
   */
  static const String CONTEXT_PATH = '/context';

  /**
   * The path used to request diagnostic information.
   */
  static const String DIAGNOSTIC_PATH = '/diagnostic';

  /**
   * The path used to request information about a element model.
   */
  static const String ELEMENT_PATH = '/element';

  /**
   * The path used to request an overlay contents.
   */
  static const String OVERLAY_PATH = '/overlay';

  /**
   * The path used to request overlays information.
   */
  static const String OVERLAYS_PATH = '/overlays';

  /**
   * The path used to request the status of the analysis server as a whole.
   */
  static const String STATUS_PATH = '/status';

  /**
   * Query parameter used to represent the context to search for, when
   * accessing [CACHE_ENTRY_PATH] or [CACHE_STATE_PATH].
   */
  static const String CONTEXT_QUERY_PARAM = 'context';

  /**
   * Query parameter used to represent the descriptor to search for, when
   * accessing [CACHE_STATE_PATH].
   */
  static const String DESCRIPTOR_QUERY_PARAM = 'descriptor';

  /**
   * Query parameter used to represent the name of elements to search for, when
   * accessing [INDEX_ELEMENT_BY_NAME].
   */
  static const String INDEX_ELEMENT_NAME = 'name';

  /**
   * Query parameter used to represent the path of an overlayed file.
   */
  static const String PATH_PARAM = 'path';

  /**
   * Query parameter used to represent the source to search for, when accessing
   * [CACHE_ENTRY_PATH].
   */
  static const String SOURCE_QUERY_PARAM = 'entry';

  /**
   * Query parameter used to represent the cache state to search for, when
   * accessing [CACHE_STATE_PATH].
   */
  static const String STATE_QUERY_PARAM = 'state';

  static final ContentType _htmlContent =
      new ContentType("text", "html", charset: "utf-8");

  /**
   * Rolling average of calls to get diagnostics.
   */
  Average _diagnosticCallAverage = new Average();

  /**
   * The socket server whose status is to be reported on.
   */
  SocketServer _server;

  /**
   * Buffer containing strings printed by the analysis server.
   */
  List<String> _printBuffer;

  /**
   * Contents of overlay files.
   */
  final Map<String, String> _overlayContents = <String, String>{};

  /**
   * Handler for diagnostics requests.
   */
  DiagnosticDomainHandler _diagnosticHandler;

  /**
   * Initialize a newly created handler for GET requests.
   */
  GetHandler(this._server, this._printBuffer);

  DiagnosticDomainHandler get diagnosticHandler {
    if (_diagnosticHandler == null) {
      _diagnosticHandler = new DiagnosticDomainHandler(_server.analysisServer);
    }
    return _diagnosticHandler;
  }

  /**
   * Return the active [CompletionDomainHandler]
   * or `null` if either analysis server is not running
   * or there is no completion domain handler.
   */
  CompletionDomainHandler get _completionDomainHandler {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return null;
    }
    return analysisServer.handlers
        .firstWhere((h) => h is CompletionDomainHandler, orElse: () => null);
  }

  /**
   * Handle a GET request received by the HTTP server.
   */
  void handleGetRequest(HttpRequest request) {
    String path = request.uri.path;
    if (path == '/' || path == STATUS_PATH) {
      _returnServerStatus(request);
    } else if (path == ANALYSIS_PERFORMANCE_PATH) {
      _returnAnalysisPerformance(request);
    } else if (path == AST_PATH) {
      _returnAst(request);
    } else if (path == CACHE_STATE_PATH) {
      _returnCacheState(request);
    } else if (path == CACHE_ENTRY_PATH) {
      _returnCacheEntry(request);
    } else if (path == COMPLETION_PATH) {
      _returnCompletionInfo(request);
    } else if (path == COMMUNICATION_PERFORMANCE_PATH) {
      _returnCommunicationPerformance(request);
    } else if (path == CONTEXT_DIAGNOSTICS_PATH) {
      _returnContextDiagnostics(request);
    } else if (path == CONTEXT_VALIDATION_DIAGNOSTICS_PATH) {
      _returnContextValidationDiagnostics(request);
    } else if (path == CONTEXT_PATH) {
      _returnContextInfo(request);
    } else if (path == DIAGNOSTIC_PATH) {
      _returnDiagnosticInfo(request);
    } else if (path == ELEMENT_PATH) {
      _returnElement(request);
    } else if (path == OVERLAY_PATH) {
      _returnOverlayContents(request);
    } else if (path == OVERLAYS_PATH) {
      _returnOverlaysInfo(request);
    } else {
      _returnUnknownRequest(request);
    }
  }

  /**
   * Return the folder being managed by the given [analysisServer] that matches
   * the given [contextFilter], or `null` if there is none.
   */
  Folder _findFolder(AnalysisServer analysisServer, String contextFilter) {
    return analysisServer.folderMap.keys.firstWhere(
        (Folder folder) => folder.path == contextFilter,
        orElse: () => null);
  }

  /**
   * Return any AST structure stored in the given [entry].
   */
  CompilationUnit _getAnyAst(CacheEntry entry) {
    CompilationUnit unit = entry.getValue(PARSED_UNIT);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT1);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT2);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT3);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT4);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT5);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT6);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT7);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT8);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT9);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT10);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT11);
    if (unit != null) {
      return unit;
    }
    unit = entry.getValue(RESOLVED_UNIT12);
    if (unit != null) {
      return unit;
    }
    return entry.getValue(RESOLVED_UNIT);
  }

  /**
   * Return a list of the result descriptors whose state should be displayed for
   * the given cache [entry].
   */
  List<ResultDescriptor> _getExpectedResults(CacheEntry entry) {
    AnalysisTarget target = entry.target;
    Set<ResultDescriptor> results = entry.nonInvalidResults.toSet();
    if (target is Source) {
      String name = target.shortName;
      results.add(CONTENT);
      results.add(LINE_INFO);
      results.add(MODIFICATION_TIME);
      if (AnalysisEngine.isDartFileName(name)) {
        results.add(BUILD_DIRECTIVES_ERRORS);
        results.add(BUILD_LIBRARY_ERRORS);
        results.add(CONTAINING_LIBRARIES);
        results.add(DART_ERRORS);
        results.add(EXPLICITLY_IMPORTED_LIBRARIES);
        results.add(EXPORT_SOURCE_CLOSURE);
        results.add(EXPORTED_LIBRARIES);
        results.add(IMPORTED_LIBRARIES);
        results.add(INCLUDED_PARTS);
        results.add(IS_LAUNCHABLE);
        results.add(LIBRARY_ELEMENT1);
        results.add(LIBRARY_ELEMENT2);
        results.add(LIBRARY_ELEMENT3);
        results.add(LIBRARY_ELEMENT4);
        results.add(LIBRARY_ELEMENT5);
        results.add(LIBRARY_ELEMENT);
        results.add(LIBRARY_ERRORS_READY);
        results.add(PARSE_ERRORS);
        results.add(PARSED_UNIT);
        results.add(REFERENCED_NAMES);
        results.add(SCAN_ERRORS);
        results.add(SOURCE_KIND);
        results.add(TOKEN_STREAM);
        results.add(UNITS);
      } else if (AnalysisEngine.isHtmlFileName(name)) {
        results.add(DART_SCRIPTS);
        results.add(HTML_DOCUMENT);
        results.add(HTML_DOCUMENT_ERRORS);
        results.add(HTML_ERRORS);
        results.add(REFERENCED_LIBRARIES);
      } else if (AnalysisEngine.isAnalysisOptionsFileName(name)) {
        results.add(ANALYSIS_OPTIONS_ERRORS);
      }
    } else if (target is LibrarySpecificUnit) {
      results.add(COMPILATION_UNIT_CONSTANTS);
      results.add(COMPILATION_UNIT_ELEMENT);
      results.add(HINTS);
      results.add(LINTS);
      results.add(INFERABLE_STATIC_VARIABLES_IN_UNIT);
      results.add(LIBRARY_UNIT_ERRORS);
      results.add(RESOLVE_TYPE_NAMES_ERRORS);
      results.add(RESOLVE_UNIT_ERRORS);
      results.add(RESOLVED_UNIT1);
      results.add(RESOLVED_UNIT2);
      results.add(RESOLVED_UNIT3);
      results.add(RESOLVED_UNIT4);
      results.add(RESOLVED_UNIT5);
      results.add(RESOLVED_UNIT6);
      results.add(RESOLVED_UNIT7);
      results.add(RESOLVED_UNIT8);
      results.add(RESOLVED_UNIT9);
      results.add(RESOLVED_UNIT10);
      results.add(RESOLVED_UNIT11);
      results.add(RESOLVED_UNIT12);
      results.add(RESOLVED_UNIT);
      results.add(STRONG_MODE_ERRORS);
      results.add(USED_IMPORTED_ELEMENTS);
      results.add(USED_LOCAL_ELEMENTS);
      results.add(VARIABLE_REFERENCE_ERRORS);
      results.add(VERIFY_ERRORS);
    } else if (target is ConstantEvaluationTarget) {
      results.add(CONSTANT_DEPENDENCIES);
      results.add(CONSTANT_VALUE);
      if (target is VariableElement) {
        results.add(INFERABLE_STATIC_VARIABLE_DEPENDENCIES);
        results.add(INFERRED_STATIC_VARIABLE);
      }
    } else if (target is AnalysisContextTarget) {
      results.add(TYPE_PROVIDER);
    }
    return results.toList();
  }

  /**
   * Return `true` if the given analysis [context] has at least one entry with
   * an exception.
   */
  bool _hasException(InternalAnalysisContext context) {
    MapIterator<AnalysisTarget, CacheEntry> iterator =
        context.analysisCache.iterator();
    while (iterator.moveNext()) {
      CacheEntry entry = iterator.value;
      if (entry == null || entry.exception != null) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return the folder in the [folderMap] with which the given [context] is
   * associated.
   */
  Folder _keyForValue(
      Map<Folder, AnalysisContext> folderMap, AnalysisContext context) {
    for (Folder folder in folderMap.keys) {
      if (folderMap[folder] == context) {
        return folder;
      }
    }
    return null;
  }

  /**
   * Return a response displaying overall performance information.
   */
  void _returnAnalysisPerformance(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server is not running');
    }
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Analysis Performance', [],
          (StringBuffer buffer) {
        buffer.write('<h3>Analysis Performance</h3>');
        _writeTwoColumns(buffer, (StringBuffer buffer) {
          //
          // Write performance tags.
          //
          buffer.write('<p><b>Performance tag data</b></p>');
          buffer.write(
              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
          _writeRow(buffer, ['Time (in ms)', 'Percent', 'Tag name'],
              header: true);
          // prepare sorted tags
          List<PerformanceTag> tags = PerformanceTag.all.toList();
          tags.remove(ServerPerformanceStatistics.idle);
          tags.sort((a, b) => b.elapsedMs - a.elapsedMs);
          // prepare total time
          int totalTagTime = 0;
          tags.forEach((PerformanceTag tag) {
            totalTagTime += tag.elapsedMs;
          });
          // write rows
          void writeRow(PerformanceTag tag) {
            double percent = (tag.elapsedMs * 100) / totalTagTime;
            String percentStr = '${percent.toStringAsFixed(2)}%';
            _writeRow(buffer, [tag.elapsedMs, percentStr, tag.label],
                classes: ["right", "right", null]);
          }
          tags.forEach(writeRow);
          buffer.write('</table>');
          //
          // Write target counts.
          //
          void incrementCount(Map<String, int> counts, String key) {
            int count = counts[key];
            if (count == null) {
              count = 1;
            } else {
              count++;
            }
            counts[key] = count;
          }
          Set<AnalysisTarget> countedTargets = new HashSet<AnalysisTarget>();
          Map<String, int> sourceTypeCounts = new HashMap<String, int>();
          Map<String, int> typeCounts = new HashMap<String, int>();
          int explicitSourceCount = 0;
          int explicitLineInfoCount = 0;
          int explicitLineCount = 0;
          int implicitSourceCount = 0;
          int implicitLineInfoCount = 0;
          int implicitLineCount = 0;
          for (InternalAnalysisContext context
              in analysisServer.analysisContexts) {
            Set<Source> explicitSources = new HashSet<Source>();
            Set<Source> implicitSources = new HashSet<Source>();
            AnalysisCache cache = context.analysisCache;
            MapIterator<AnalysisTarget, CacheEntry> iterator = cache.iterator();
            while (iterator.moveNext()) {
              AnalysisTarget target = iterator.key;
              if (countedTargets.add(target)) {
                if (target is Source) {
                  String name = target.fullName;
                  String sourceName;
                  if (AnalysisEngine.isDartFileName(name)) {
                    if (iterator.value.explicitlyAdded) {
                      explicitSources.add(target);
                      sourceName = 'Dart file (explicit)';
                    } else {
                      implicitSources.add(target);
                      sourceName = 'Dart file (implicit)';
                    }
                  } else if (AnalysisEngine.isHtmlFileName(name)) {
                    if (iterator.value.explicitlyAdded) {
                      sourceName = 'Html file (explicit)';
                    } else {
                      sourceName = 'Html file (implicit)';
                    }
                  } else {
                    if (iterator.value.explicitlyAdded) {
                      sourceName = 'Unknown file (explicit)';
                    } else {
                      sourceName = 'Unknown file (implicit)';
                    }
                  }
                  incrementCount(sourceTypeCounts, sourceName);
                } else if (target is ConstantEvaluationTarget) {
                  incrementCount(typeCounts, 'ConstantEvaluationTarget');
                } else {
                  String typeName = target.runtimeType.toString();
                  incrementCount(typeCounts, typeName);
                }
              }
            }

            int lineCount(Set<Source> sources, bool explicit) {
              return sources.fold(0, (int previousTotal, Source source) {
                LineInfo lineInfo = context.getLineInfo(source);
                if (lineInfo is LineInfoWithCount) {
                  if (explicit) {
                    explicitLineInfoCount++;
                  } else {
                    implicitLineInfoCount++;
                  }
                  return previousTotal + lineInfo.lineCount;
                } else {
                  return previousTotal;
                }
              });
            }
            explicitSourceCount += explicitSources.length;
            explicitLineCount += lineCount(explicitSources, true);
            implicitSourceCount += implicitSources.length;
            implicitLineCount += lineCount(implicitSources, false);
          }
          List<String> sourceTypeNames = sourceTypeCounts.keys.toList();
          sourceTypeNames.sort();
          List<String> typeNames = typeCounts.keys.toList();
          typeNames.sort();

          buffer.write('<p><b>Target counts</b></p>');
          buffer.write(
              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
          _writeRow(buffer, ['Target', 'Count'], header: true);
          for (String sourceTypeName in sourceTypeNames) {
            _writeRow(
                buffer, [sourceTypeName, sourceTypeCounts[sourceTypeName]],
                classes: [null, "right"]);
          }
          for (String typeName in typeNames) {
            _writeRow(buffer, [typeName, typeCounts[typeName]],
                classes: [null, "right"]);
          }
          buffer.write('</table>');

          buffer.write('<p><b>Line counts</b></p>');
          buffer.write(
              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
          _writeRow(buffer, ['Kind', 'Lines of Code', 'Source Counts'],
              header: true);
          _writeRow(buffer, [
            'Explicit',
            explicitLineCount.toString(),
            '$explicitLineInfoCount / $explicitSourceCount'
          ], classes: [
            null,
            "right"
          ]);
          _writeRow(buffer, [
            'Implicit',
            implicitLineCount.toString(),
            '$implicitLineInfoCount / $implicitSourceCount'
          ], classes: [
            null,
            "right"
          ]);
          _writeRow(buffer, [
            'Total',
            (explicitLineCount + implicitLineCount).toString(),
            '${explicitLineInfoCount + implicitLineInfoCount} / ${explicitSourceCount + implicitSourceCount}'
          ], classes: [
            null,
            "right"
          ]);
          buffer.write('</table>');
        }, (StringBuffer buffer) {
          //
          // Write task model timing information.
          //
          buffer.write('<p><b>Task performance data</b></p>');
          buffer.write(
              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
          _writeRow(
              buffer,
              [
                'Task Name',
                'Count',
                'Total Time (in ms)',
                'Average Time (in ms)'
              ],
              header: true);

          Map<Type, int> countMap = AnalysisTask.countMap;
          Map<Type, Stopwatch> stopwatchMap = AnalysisTask.stopwatchMap;
          List<Type> taskClasses = stopwatchMap.keys.toList();
          taskClasses.sort((Type first, Type second) =>
              first.toString().compareTo(second.toString()));
          int totalTaskTime = 0;
          taskClasses.forEach((Type taskClass) {
            int count = countMap[taskClass];
            if (count == null) {
              count = 0;
            }
            int taskTime = stopwatchMap[taskClass].elapsedMilliseconds;
            totalTaskTime += taskTime;
            _writeRow(buffer, [
              taskClass.toString(),
              count,
              taskTime,
              count <= 0 ? '-' : (taskTime / count).toStringAsFixed(3)
            ], classes: [
              null,
              "right",
              "right",
              "right"
            ]);
          });
          _writeRow(buffer, ['Total', '-', totalTaskTime, '-'],
              classes: [null, "right", "right", "right"]);
          buffer.write('</table>');
        });
      });
    });
  }

  /**
   * Return a response containing information about an AST structure.
   */
  void _returnAst(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }
    String sourceUri = request.uri.queryParameters[SOURCE_QUERY_PARAM];
    if (sourceUri == null) {
      return _returnFailure(
          request, 'Query parameter $SOURCE_QUERY_PARAM required');
    }

    InternalAnalysisContext context = analysisServer.folderMap[folder];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - AST Structure',
          ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
        Source source = context.sourceFactory.forUri(sourceUri);
        if (source == null) {
          buffer.write('<p>Not found.</p>');
          return;
        }
        List<Source> libraries = context.getLibrariesContaining(source);
        for (Source library in libraries) {
          AnalysisTarget target = new LibrarySpecificUnit(library, source);
          CacheEntry entry = context.analysisCache.get(target);
          buffer.write('<b>$target</b><br>');
          if (entry == null) {
            buffer.write('<p>Not found.</p>');
            continue;
          }
          CompilationUnit ast = _getAnyAst(entry);
          if (ast == null) {
            buffer.write('<p>null</p>');
            continue;
          }
          AstWriter writer = new AstWriter(buffer);
          ast.accept(writer);
          if (writer.exceptions.isNotEmpty) {
            buffer.write('<h3>Exceptions while creating page</h3>');
            for (CaughtException exception in writer.exceptions) {
              _writeException(buffer, exception);
            }
          }
        }
      });
    });
  }

  /**
   * Return a response containing information about a single source file in the
   * cache.
   */
  void _returnCacheEntry(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }
    String sourceUri = request.uri.queryParameters[SOURCE_QUERY_PARAM];
    if (sourceUri == null) {
      return _returnFailure(
          request, 'Query parameter $SOURCE_QUERY_PARAM required');
    }

    List<Folder> allContexts = <Folder>[];
    Map<Folder, List<CacheEntry>> entryMap =
        new HashMap<Folder, List<CacheEntry>>();
    StringBuffer invalidKeysBuffer = new StringBuffer();
    analysisServer.folderMap.forEach((Folder folder, AnalysisContext context) {
      Source source = context.sourceFactory.forUri(sourceUri);
      if (source != null) {
        MapIterator<AnalysisTarget, CacheEntry> iterator =
            (context as InternalAnalysisContext).analysisCache.iterator();
        while (iterator.moveNext()) {
          if (source == iterator.key.source) {
            if (!allContexts.contains(folder)) {
              allContexts.add(folder);
            }
            List<CacheEntry> entries = entryMap[folder];
            if (entries == null) {
              entries = <CacheEntry>[];
              entryMap[folder] = entries;
            }
            CacheEntry value = iterator.value;
            if (value == null) {
              if (invalidKeysBuffer.isNotEmpty) {
                invalidKeysBuffer.write(', ');
              }
              invalidKeysBuffer.write(iterator.key.toString());
            } else {
              entries.add(value);
            }
          }
        }
      }
    });
    allContexts.sort((Folder firstFolder, Folder secondFolder) =>
        firstFolder.path.compareTo(secondFolder.path));
    InternalAnalysisContext context = analysisServer.folderMap[folder];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Cache Entry',
          ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
        if (invalidKeysBuffer.isNotEmpty) {
          buffer.write('<h3>Targets with null Entries</h3><p>');
          buffer.write(invalidKeysBuffer.toString());
          buffer.write('</p>');
        }
        List<CacheEntry> entries = entryMap[folder];
        buffer.write('<h3>Analyzing Contexts</h3><p>');
        bool first = true;
        allContexts.forEach((Folder folder) {
          if (first) {
            first = false;
          } else {
            buffer.write('<br>');
          }
          InternalAnalysisContext analyzingContext =
              analysisServer.folderMap[folder];
          if (analyzingContext == context) {
            buffer.write(folder.path);
          } else {
            buffer.write(makeLink(
                CACHE_ENTRY_PATH,
                {
                  CONTEXT_QUERY_PARAM: folder.path,
                  SOURCE_QUERY_PARAM: sourceUri
                },
                HTML_ESCAPE.convert(folder.path)));
          }
          if (entries == null) {
            buffer.write(' (file does not exist)');
          } else {
            CacheEntry sourceEntry = entries
                .firstWhere((CacheEntry entry) => entry.target is Source);
            if (sourceEntry == null) {
              buffer.write(' (missing source entry)');
            } else if (sourceEntry.explicitlyAdded) {
              buffer.write(' (explicit)');
            } else {
              buffer.write(' (implicit)');
            }
          }
        });
        buffer.write('</p>');

        if (entries == null) {
          buffer.write('<p>Not being analyzed in this context.</p>');
          return;
        }
        for (CacheEntry entry in entries) {
          Map<String, String> linkParameters = <String, String>{
            CONTEXT_QUERY_PARAM: folder.path,
            SOURCE_QUERY_PARAM: sourceUri
          };
          List<ResultDescriptor> results = _getExpectedResults(entry);
          results.sort((ResultDescriptor first, ResultDescriptor second) =>
              first.toString().compareTo(second.toString()));

          buffer.write('<h3>');
          buffer.write(HTML_ESCAPE.convert(entry.target.toString()));
          buffer.write('</h3>');
          buffer.write('<p>time</p><blockquote><p>Value</p><blockquote>');
          buffer.write(entry.modificationTime);
          buffer.write('</blockquote></blockquote>');
          for (ResultDescriptor result in results) {
            ResultData data = entry.getResultData(result);
            CacheState state = entry.getState(result);
            String descriptorName = HTML_ESCAPE.convert(result.toString());
            String descriptorState = HTML_ESCAPE.convert(state.toString());
            buffer
                .write('<p>$descriptorName ($descriptorState)</p><blockquote>');
            if (state == CacheState.VALID) {
              buffer.write('<p>Value</p><blockquote>');
              try {
                _writeValueAsHtml(
                    buffer, entry.getValue(result), linkParameters);
              } catch (exception) {
                buffer.write('(${HTML_ESCAPE.convert(exception.toString())})');
              }
              buffer.write('</blockquote>');
            }
            _writeTargetedResults(buffer, 'Depends on', data.dependedOnResults);
            _writeTargetedResults(
                buffer, 'Depended on by', data.dependentResults);
            buffer.write('</blockquote>');
          }
          if (entry.exception != null) {
            buffer.write('<dt>exception</dt><dd>');
            _writeException(buffer, entry.exception);
            buffer.write('</dd>');
          }
        }
      });
    });
  }

  /**
   * Return a response indicating the set of source files in a certain cache
   * state.
   */
  void _returnCacheState(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server not running');
    }
    // Figure out which context is being searched within.
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    // Figure out what CacheState is being searched for.
    String stateQueryParam = request.uri.queryParameters[STATE_QUERY_PARAM];
    if (stateQueryParam == null) {
      return _returnFailure(
          request, 'Query parameter $STATE_QUERY_PARAM required');
    }
    CacheState stateFilter = null;
    for (CacheState value in CacheState.values) {
      if (value.toString() == stateQueryParam) {
        stateFilter = value;
      }
    }
    if (stateFilter == null) {
      return _returnFailure(
          request, 'Query parameter $STATE_QUERY_PARAM is invalid');
    }
    // Figure out which descriptor is being searched for.
    String descriptorFilter =
        request.uri.queryParameters[DESCRIPTOR_QUERY_PARAM];
    if (descriptorFilter == null) {
      return _returnFailure(
          request, 'Query parameter $DESCRIPTOR_QUERY_PARAM required');
    }

    // TODO(brianwilkerson) Figure out how to convert the 'descriptorFilter' to
    // a ResultDescriptor so that we can query the state, then uncomment the
    // code below that computes and prints the list of links.
//    Folder folder = _findFolder(analysisServer, contextFilter);
//    InternalAnalysisContext context = analysisServer.folderMap[folder];
//    List<String> links = <String>[];
//    MapIterator<AnalysisTarget, CacheEntry> iterator = context.analysisCache.iterator();
//    while (iterator.moveNext()) {
//      Source source = iterator.key.source;
//      if (source != null) {
//        CacheEntry entry = iterator.value;
//        if (entry.getState(result) == stateFilter) {
//          String link = makeLink(CACHE_ENTRY_PATH, {
//            CONTEXT_QUERY_PARAM: folder.path,
//            SOURCE_QUERY_PARAM: source.uri.toString()
//          }, HTML_ESCAPE.convert(source.fullName));
//          links.add(link);
//        }
//      }
//    }

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Cache Search', [
        'Context: $contextFilter',
        'Descriptor: ${HTML_ESCAPE.convert(descriptorFilter)}',
        'State: ${HTML_ESCAPE.convert(stateQueryParam)}'
      ], (StringBuffer buffer) {
        buffer.write('<p>Cache search is not yet implemented.</p>');
//        buffer.write('<p>${links.length} files found</p>');
//        buffer.write('<ul>');
//        links.forEach((String link) {
//          buffer.write('<li>$link</li>');
//        });
//        buffer.write('</ul>');
      });
    });
  }

  /**
   * Return a response displaying overall performance information.
   */
  void _returnCommunicationPerformance(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server is not running');
    }
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Communication Performance', [],
          (StringBuffer buffer) {
        buffer.write('<h3>Communication Performance</h3>');
        _writeTwoColumns(buffer, (StringBuffer buffer) {
          ServerPerformance perf = analysisServer.performanceDuringStartup;
          int requestCount = perf.requestCount;
          num averageLatency = requestCount > 0
              ? (perf.requestLatency / requestCount).round()
              : 0;
          int maximumLatency = perf.maxLatency;
          num slowRequestPercent = requestCount > 0
              ? (perf.slowRequestCount * 100 / requestCount).round()
              : 0;
          buffer.write('<h4>Startup</h4>');
          buffer.write('<table>');
          _writeRow(buffer, [requestCount, 'requests'],
              classes: ["right", null]);
          _writeRow(buffer, [averageLatency, 'ms average latency'],
              classes: ["right", null]);
          _writeRow(buffer, [maximumLatency, 'ms maximum latency'],
              classes: ["right", null]);
          _writeRow(buffer, [slowRequestPercent, '% > 150 ms latency'],
              classes: ["right", null]);
          if (analysisServer.performanceAfterStartup != null) {
            int startupTime = analysisServer.performanceAfterStartup.startTime -
                perf.startTime;
            _writeRow(
                buffer, [startupTime, 'ms for initial analysis to complete']);
          }
          buffer.write('</table>');
        }, (StringBuffer buffer) {
          ServerPerformance perf = analysisServer.performanceAfterStartup;
          if (perf == null) {
            return;
          }
          int requestCount = perf.requestCount;
          num averageLatency = requestCount > 0
              ? (perf.requestLatency * 10 / requestCount).round() / 10
              : 0;
          int maximumLatency = perf.maxLatency;
          num slowRequestPercent = requestCount > 0
              ? (perf.slowRequestCount * 100 / requestCount).round()
              : 0;
          buffer.write('<h4>Current</h4>');
          buffer.write('<table>');
          _writeRow(buffer, [requestCount, 'requests'],
              classes: ["right", null]);
          _writeRow(buffer, [averageLatency, 'ms average latency'],
              classes: ["right", null]);
          _writeRow(buffer, [maximumLatency, 'ms maximum latency'],
              classes: ["right", null]);
          _writeRow(buffer, [slowRequestPercent, '% > 150 ms latency'],
              classes: ["right", null]);
          buffer.write('</table>');
        });
      });
    });
  }

  /**
   * Return a response displaying code completion information.
   */
  void _returnCompletionInfo(HttpRequest request) {
    String value = request.requestedUri.queryParameters['index'];
    int index = value != null ? int.parse(value, onError: (_) => 0) : 0;
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Completion Stats', [],
          (StringBuffer buffer) {
        _writeCompletionPerformanceDetail(buffer, index);
        _writeCompletionPerformanceList(buffer);
      });
    });
  }

  /**
   * Return a response displaying diagnostic information for a single context.
   */
  void _returnContextDiagnostics(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server is not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }

    InternalAnalysisContext context = analysisServer.folderMap[folder];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Context Diagnostics',
          ['Context: $contextFilter'], (StringBuffer buffer) {
        _writeContextDiagnostics(buffer, context);
      });
    });
  }

  /**
   * Return a response containing information about a single source file in the
   * cache.
   */
  void _returnContextInfo(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }

    List<String> priorityNames = <String>[];
    List<String> explicitNames = <String>[];
    List<String> implicitNames = <String>[];
    Map<String, String> links = new HashMap<String, String>();
    List<CaughtException> exceptions = <CaughtException>[];
    InternalAnalysisContext context = analysisServer.folderMap[folder];
    context.prioritySources.forEach((Source source) {
      priorityNames.add(source.fullName);
    });
    MapIterator<AnalysisTarget, CacheEntry> iterator =
        context.analysisCache.iterator(context: context);
    while (iterator.moveNext()) {
      AnalysisTarget target = iterator.key;
      if (target is Source) {
        CacheEntry entry = iterator.value;
        String sourceName = target.fullName;
        if (!links.containsKey(sourceName)) {
          CaughtException exception = entry.exception;
          if (exception != null) {
            exceptions.add(exception);
          }
          String link = makeLink(
              CACHE_ENTRY_PATH,
              {
                CONTEXT_QUERY_PARAM: folder.path,
                SOURCE_QUERY_PARAM: target.uri.toString()
              },
              sourceName,
              exception != null);
          if (entry.explicitlyAdded) {
            explicitNames.add(sourceName);
          } else {
            implicitNames.add(sourceName);
          }
          links[sourceName] = link;
        }
      }
    }
    explicitNames.sort();
    implicitNames.sort();

    _overlayContents.clear();
    context.visitContentCache((String fullName, int stamp, String contents) {
      _overlayContents[fullName] = contents;
    });

    void _writeFiles(
        StringBuffer buffer, String title, List<String> fileNames) {
      buffer.write('<h3>$title</h3>');
      if (fileNames == null || fileNames.isEmpty) {
        buffer.write('<p>None</p>');
      } else {
        buffer.write('<p><table style="width: 100%">');
        for (String fileName in fileNames) {
          buffer.write('<tr><td>');
          buffer.write(links[fileName]);
          buffer.write('</td><td>');
          if (_overlayContents.containsKey(fileName)) {
            buffer.write(
                makeLink(OVERLAY_PATH, {PATH_PARAM: fileName}, 'overlay'));
          }
          buffer.write('</td></tr>');
        }
        buffer.write('</table></p>');
      }
    }
    void writeOptions(StringBuffer buffer, AnalysisOptionsImpl options) {
      if (options == null) {
        buffer.write('<p>No option information available.</p>');
        return;
      }
      buffer.write('<p>');
      _writeOption(
          buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
      _writeOption(buffer, 'Cache size', options.cacheSize);
      _writeOption(buffer, 'Enable async support', options.enableAsync);
      _writeOption(
          buffer, 'Enable generic methods', options.enableGenericMethods);
      _writeOption(
          buffer, 'Enable strict call checks', options.enableStrictCallChecks);
      _writeOption(buffer, 'Enable super mixins', options.enableSuperMixins);
      _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
      _writeOption(buffer, 'Generate errors in implicit files',
          options.generateImplicitErrors);
      _writeOption(
          buffer, 'Generate errors in SDK files', options.generateSdkErrors);
      _writeOption(buffer, 'Generate hints', options.hint);
      _writeOption(buffer, 'Incremental resolution', options.incremental);
      _writeOption(buffer, 'Incremental resolution with API changes',
          options.incrementalApi);
      _writeOption(buffer, 'Preserve comments', options.preserveComments);
      _writeOption(buffer, 'Strong mode', options.strongMode);
      _writeOption(buffer, 'Strong mode hints', options.strongModeHints,
          last: true);
      buffer.write('</p>');
    }

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(
          buffer, 'Analysis Server - Context', ['Context: $contextFilter'],
          (StringBuffer buffer) {
        buffer.write('<h3>Configuration</h3>');

        _writeColumns(buffer, <HtmlGenerator>[
          (StringBuffer buffer) {
            buffer.write('<p><b>Context Options</b></p>');
            writeOptions(buffer, context.analysisOptions);
          },
          (StringBuffer buffer) {
            buffer.write('<p><b>SDK Context Options</b></p>');
            writeOptions(buffer,
                context?.sourceFactory?.dartSdk?.context?.analysisOptions);
          },
          (StringBuffer buffer) {
            List<Linter> lints =
                context.getConfigurationData(CONFIGURED_LINTS_KEY);
            buffer.write('<p><b>Lints</b></p>');
            if (lints.isEmpty) {
              buffer.write('<p>none</p>');
            } else {
              for (Linter lint in lints) {
                buffer.write('<p>');
                buffer.write(lint.runtimeType);
                buffer.write('</p>');
              }
            }

            List<ErrorProcessor> errorProcessors =
                context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
            int processorCount = errorProcessors?.length ?? 0;
            buffer
                .write('<p><b>Error Processor count</b>: $processorCount</p>');
          }
        ]);

        SourceFactory sourceFactory = context.sourceFactory;
        if (sourceFactory is SourceFactoryImpl) {
          buffer.write('<h3>Resolvers</h3>');
          for (UriResolver resolver in sourceFactory.resolvers) {
            buffer.write('<p>');
            buffer.write(resolver.runtimeType);
            buffer.write('</p>');
          }
        }

        _writeFiles(
            buffer, 'Priority Files (${priorityNames.length})', priorityNames);
        _writeFiles(
            buffer,
            'Explicitly Analyzed Files (${explicitNames.length})',
            explicitNames);
        _writeFiles(
            buffer,
            'Implicitly Analyzed Files (${implicitNames.length})',
            implicitNames);

        buffer.write('<h3>Exceptions</h3>');
        if (exceptions.isEmpty) {
          buffer.write('<p>none</p>');
        } else {
          exceptions.forEach((CaughtException exception) {
            _writeException(buffer, exception);
          });
        }

        buffer.write('<h3>Targets Without Entries</h3>');
        bool foundEntry = false;
        MapIterator<AnalysisTarget, CacheEntry> iterator =
            context.analysisCache.iterator(context: context);
        while (iterator.moveNext()) {
          if (iterator.value == null) {
            foundEntry = true;
            buffer.write('<p>');
            buffer.write(iterator.key.toString());
            buffer.write(' (');
            buffer.write(iterator.key.runtimeType.toString());
            buffer.write(')</p>');
          }
        }
        if (!foundEntry) {
          buffer.write('<p>none</p>');
        }
      });
    });
  }

  /**
   * Return a response displaying the results of running a validation report on
   * a single context.
   */
  void _returnContextValidationDiagnostics(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server is not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }

    InternalAnalysisContext context = analysisServer.folderMap[folder];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Context Validation Diagnostics',
          ['Context: $contextFilter'], (StringBuffer buffer) {
        _writeContextValidationDiagnostics(buffer, context);
      });
    });
  }

  /**
   * Return a response displaying diagnostic information.
   */
  void _returnDiagnosticInfo(HttpRequest request) {
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Diagnostic info', [],
          (StringBuffer buffer) {
        _writeDiagnosticStatus(buffer);
      });
    });
  }

  /**
   * Return a response containing information about an element structure.
   */
  void _returnElement(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server not running');
    }
    String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
    if (contextFilter == null) {
      return _returnFailure(
          request, 'Query parameter $CONTEXT_QUERY_PARAM required');
    }
    Folder folder = _findFolder(analysisServer, contextFilter);
    if (folder == null) {
      return _returnFailure(request, 'Invalid context: $contextFilter');
    }
    String sourceUri = request.uri.queryParameters[SOURCE_QUERY_PARAM];
    if (sourceUri == null) {
      return _returnFailure(
          request, 'Query parameter $SOURCE_QUERY_PARAM required');
    }

    InternalAnalysisContext context = analysisServer.folderMap[folder];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Element Model', [
        'Context: $contextFilter',
        'File: $sourceUri'
      ], (StringBuffer buffer) {
        Source source = context.sourceFactory.forUri(sourceUri);
        if (source == null) {
          buffer.write('<p>Not found.</p>');
          return;
        }
        CacheEntry entry = context.analysisCache.get(source);
        if (entry == null) {
          buffer.write('<p>Not found.</p>');
          return;
        }
        LibraryElement element = entry.getValue(LIBRARY_ELEMENT);
        if (element == null) {
          buffer.write('<p>null</p>');
          return;
        }
        element.accept(new ElementWriter(buffer));
      });
    });
  }

  void _returnFailure(HttpRequest request, String message) {
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Failure', [],
          (StringBuffer buffer) {
        buffer.write(HTML_ESCAPE.convert(message));
      });
    });
  }

  void _returnOverlayContents(HttpRequest request) {
    String path = request.requestedUri.queryParameters[PATH_PARAM];
    if (path == null) {
      return _returnFailure(request, 'Query parameter $PATH_PARAM required');
    }
    String contents = _overlayContents[path];

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Overlay', [],
          (StringBuffer buffer) {
        buffer.write('<pre>${HTML_ESCAPE.convert(contents)}</pre>');
      });
    });
  }

  /**
   * Return a response displaying overlays information.
   */
  void _returnOverlaysInfo(HttpRequest request) {
    AnalysisServer analysisServer = _server.analysisServer;
    if (analysisServer == null) {
      return _returnFailure(request, 'Analysis server is not running');
    }

    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Overlays', [],
          (StringBuffer buffer) {
        buffer.write('<table border="1">');
        _overlayContents.clear();
        ContentCache overlayState = analysisServer.overlayState;
        overlayState.accept((String fullName, int stamp, String contents) {
          buffer.write('<tr>');
          String link =
              makeLink(OVERLAY_PATH, {PATH_PARAM: fullName}, fullName);
          DateTime time = new DateTime.fromMillisecondsSinceEpoch(stamp);
          _writeRow(buffer, [link, time]);
          _overlayContents[fullName] = contents;
        });
        int count = _overlayContents.length;
        buffer.write('<tr><td colspan="2">Total: $count entries.</td></tr>');
        buffer.write('</table>');
      });
    });
  }

  /**
   * Return a response indicating the status of the analysis server.
   */
  void _returnServerStatus(HttpRequest request) {
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server - Status', [], (StringBuffer buffer) {
        if (_writeServerStatus(buffer)) {
          _writeAnalysisStatus(buffer);
          _writeEditStatus(buffer);
          _writeExecutionStatus(buffer);
          _writePluginStatus(buffer);
          _writeRecentOutput(buffer);
        }
      });
    });
  }

  /**
   * Return an error in response to an unrecognized request received by the HTTP
   * server.
   */
  void _returnUnknownRequest(HttpRequest request) {
    _writeResponse(request, (StringBuffer buffer) {
      _writePage(buffer, 'Analysis Server', [], (StringBuffer buffer) {
        buffer.write('<h3>Unknown page: ');
        buffer.write(request.uri.path);
        buffer.write('</h3>');
        buffer.write('''
        <p>
        You have reached an un-recognized page. If you reached this page by
        following a link from a status page, please report the broken link to
        the Dart analyzer team:
        <a>https://github.com/dart-lang/sdk/issues/new</a>.
        </p><p>
        If you mistyped the URL, you can correct it or return to
        ${makeLink(STATUS_PATH, {}, 'the main status page')}.
        </p>''');
      });
    });
  }

  /**
   * Return a two digit decimal representation of the given non-negative integer
   * [value].
   */
  String _twoDigit(int value) {
    if (value < 10) {
      return '0$value';
    }
    return value.toString();
  }

  /**
   * Write the status of the analysis domain (on the main status page) to the
   * given [buffer] object.
   */
  void _writeAnalysisStatus(StringBuffer buffer) {
    AnalysisServer analysisServer = _server.analysisServer;
    Map<Folder, AnalysisContext> folderMap = analysisServer.folderMap;
    List<Folder> folders = folderMap.keys.toList();
    folders.sort((Folder first, Folder second) =>
        first.shortName.compareTo(second.shortName));
    ServerOperationQueue operationQueue = analysisServer.operationQueue;

    buffer.write('<h3>Analysis Domain</h3>');
    _writeTwoColumns(buffer, (StringBuffer buffer) {
      if (operationQueue.isEmpty) {
        buffer.write('<p>Status: Done analyzing</p>');
      } else {
        ServerOperation operation = operationQueue.peek();
        if (operation is PerformAnalysisOperation) {
          Folder folder = _keyForValue(folderMap, operation.context);
          if (folder == null) {
            buffer.write('<p>Status: Analyzing in unmapped context</p>');
          } else {
            buffer.write('<p>Status: Analyzing in ${folder.path}</p>');
          }
        } else {
          buffer.write('<p>Status: Analyzing</p>');
        }
      }
      buffer.write('<p>Using package resolver provider: ');
      buffer.write(_server.packageResolverProvider != null);
      buffer.write('</p>');
      buffer.write('<p>');
      buffer.write(makeLink(OVERLAYS_PATH, {}, 'All overlay information'));
      buffer.write('</p>');

      buffer.write('<p><b>Analysis Contexts</b></p>');
      buffer.write('<p>');
      bool first = true;
      folders.forEach((Folder folder) {
        if (first) {
          first = false;
        } else {
          buffer.write('<br>');
        }
        String key = folder.shortName;
        buffer.write(makeLink(CONTEXT_PATH, {CONTEXT_QUERY_PARAM: folder.path},
            key, _hasException(folderMap[folder])));
        buffer.write(' <small><b>[');
        buffer.write(makeLink(CONTEXT_DIAGNOSTICS_PATH,
            {CONTEXT_QUERY_PARAM: folder.path}, 'diagnostics'));
        buffer.write(']</b></small>');
        if (!folder.getChild('.packages').exists) {
          buffer.write(' <small>[no .packages file]</small>');
        }
      });
      // TODO(brianwilkerson) Add items for the SDK contexts (currently only one).
      buffer.write('</p>');

      int freq = AnalysisServer.performOperationDelayFrequency;
      String delay = freq > 0 ? '1 ms every $freq ms' : 'off';

      buffer.write('<p><b>Performance Data</b></p>');
      buffer.write('<p>Perform operation delay: $delay</p>');
      buffer.write('<p>');
      buffer.write(makeLink(ANALYSIS_PERFORMANCE_PATH, {}, 'Task data'));
      buffer.write('</p>');
    }, (StringBuffer buffer) {
      _writeSubscriptionMap(
          buffer, AnalysisService.VALUES, analysisServer.analysisServices);
    });
  }

  /**
   * Write multiple columns of information to the given [buffer], where the list
   * of [columns] functions are used to generate the content of those columns.
   */
  void _writeColumns(StringBuffer buffer, List<HtmlGenerator> columns) {
    buffer
        .write('<table class="column"><tr class="column"><td class="column">');
    int count = columns.length;
    for (int i = 0; i < count; i++) {
      if (i > 0) {
        buffer.write('</td><td class="column">');
      }
      columns[i](buffer);
    }
    buffer.write('</td></tr></table>');
  }

  /**
   * Write performance information about a specific completion request
   * to the given [buffer] object.
   */
  void _writeCompletionPerformanceDetail(StringBuffer buffer, int index) {
    CompletionDomainHandler handler = _completionDomainHandler;
    CompletionPerformance performance;
    if (handler != null) {
      List<CompletionPerformance> list = handler.performanceList;
      if (list != null && list.isNotEmpty) {
        performance = list[max(0, min(list.length - 1, index))];
      }
    }
    if (performance == null) {
      buffer.write('<h3>Completion Performance Detail</h3>');
      buffer.write('<p>No completions yet</p>');
      return;
    }
    buffer.write('<h3>Completion Performance Detail</h3>');
    buffer.write('<p>${performance.startTimeAndMs} for ${performance.source}');
    buffer.write('<table>');
    _writeRow(buffer, ['Elapsed', '', 'Operation'], header: true);
    performance.operations.forEach((OperationPerformance op) {
      String elapsed = op.elapsed != null ? op.elapsed.toString() : '???';
      _writeRow(buffer, [elapsed, '&nbsp;&nbsp;', op.name]);
    });
    buffer.write('</table>');
    buffer.write('<p><b>Compute Cache Performance</b>: ');
    if (handler.computeCachePerformance == null) {
      buffer.write('none');
    } else {
      int elapsed = handler.computeCachePerformance.elapsedInMilliseconds;
      Source source = handler.computeCachePerformance.source;
      buffer.write(' $elapsed ms for $source');
    }
    buffer.write('</p>');
  }

  /**
   * Write a table showing summary information for the last several
   * completion requests to the given [buffer] object.
   */
  void _writeCompletionPerformanceList(StringBuffer buffer) {
    CompletionDomainHandler handler = _completionDomainHandler;
    buffer.write('<h3>Completion Performance List</h3>');
    if (handler == null) {
      return;
    }
    buffer.write('<table>');
    _writeRow(
        buffer,
        [
          'Start Time',
          '',
          'First (ms)',
          '',
          'Complete (ms)',
          '',
          '# Notifications',
          '',
          '# Suggestions',
          '',
          'Snippet'
        ],
        header: true);
    int index = 0;
    for (CompletionPerformance performance in handler.performanceList) {
      String link = makeLink(COMPLETION_PATH, {'index': '$index'},
          '${performance.startTimeAndMs}');
      _writeRow(buffer, [
        link,
        '&nbsp;&nbsp;',
        performance.firstNotificationInMilliseconds,
        '&nbsp;&nbsp;',
        performance.elapsedInMilliseconds,
        '&nbsp;&nbsp;',
        performance.notificationCount,
        '&nbsp;&nbsp;',
        performance.suggestionCount,
        '&nbsp;&nbsp;',
        HTML_ESCAPE.convert(performance.snippet)
      ]);
      ++index;
    }

    buffer.write('</table>');
    buffer.write('''
      <p><strong>First (ms)</strong> - the number of milliseconds
        from when completion received the request until the first notification
        with completion results was queued for sending back to the client.
      <p><strong>Complete (ms)</strong> - the number of milliseconds
        from when completion received the request until the final notification
        with completion results was queued for sending back to the client.
      <p><strong># Notifications</strong> - the total number of notifications
        sent to the client with completion results for this request.
      <p><strong># Suggestions</strong> - the number of suggestions
        sent to the client in the first notification, followed by a comma,
        followed by the number of suggestions send to the client
        in the last notification. If there is only one notification,
        then there will be only one number in this column.''');
  }

  /**
   * Write diagnostic information about the given [context] to the given
   * [buffer].
   */
  void _writeContextDiagnostics(
      StringBuffer buffer, InternalAnalysisContext context) {
    AnalysisDriver driver = (context as AnalysisContextImpl).driver;
    List<WorkItem> workItems = driver.currentWorkOrder?.workItems;

    buffer.write('<p>');
    buffer.write(makeLink(CONTEXT_VALIDATION_DIAGNOSTICS_PATH,
        {CONTEXT_QUERY_PARAM: context.name}, 'Run validation'));
    buffer.write('</p>');

    buffer.write('<h3>Most Recently Perfomed Tasks</h3>');
    AnalysisTask.LAST_TASKS.forEach((String description) {
      buffer.write('<p>');
      buffer.write(description);
      buffer.write('</p>');
    });

    void writeWorkItem(StringBuffer buffer, WorkItem item) {
      if (item == null) {
        buffer.write('none');
      } else {
        buffer.write(item.descriptor?.name);
        buffer.write(' computing ');
        buffer.write(item.spawningResult?.name);
        buffer.write(' for ');
        buffer.write(item.target);
      }
    }

    buffer.write('<h3>Work Items</h3>');
    buffer.write('<p><b>Current:</b> ');
    writeWorkItem(buffer, driver.currentWorkOrder?.current);
    buffer.write('</p>');
    if (workItems != null) {
      workItems.reversed.forEach((WorkItem item) {
        buffer.write('<p>');
        writeWorkItem(buffer, item);
        buffer.write('</p>');
      });
    }
  }

  /**
   * Write diagnostic information about the given [context] to the given
   * [buffer].
   */
  void _writeContextValidationDiagnostics(
      StringBuffer buffer, InternalAnalysisContext context) {
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.start();
    ValidationResults results = new ValidationResults(context);
    stopwatch.stop();

    buffer.write('<h3>Validation Results</h3>');
    buffer.write('<p>Re-analysis took ');
    buffer.write(stopwatch.elapsedMilliseconds);
    buffer.write(' ms</p>');
    results.writeOn(buffer);
  }

  /**
   * Write the status of the diagnostic domain to the given [buffer].
   */
  void _writeDiagnosticStatus(StringBuffer buffer) {
    var request = new DiagnosticGetDiagnosticsParams().toRequest('0');

    var stopwatch = new Stopwatch();
    stopwatch.start();
    var response = diagnosticHandler.handleRequest(request);
    stopwatch.stop();

    int elapsedMs = stopwatch.elapsedMilliseconds;
    _diagnosticCallAverage.addSample(elapsedMs);

    buffer.write('<h3>Timing</h3>');

    buffer.write('<p>getDiagnostic (last call): ');
    buffer.write(elapsedMs);
    buffer.write(' (ms)</p>');
    buffer.write('<p>getDiagnostic (rolling average): ');
    buffer.write(_diagnosticCallAverage.value);
    buffer.write(' (ms)</p>&nbsp;');

    Map json = response.toJson()[Response.RESULT];
    List contexts = json['contexts'];
    contexts.sort((first, second) => first['name'].compareTo(second['name']));

    // Track visited libraries.
    Set<LibraryElement> libraries = new HashSet<LibraryElement>();

    // Count SDK elements separately.
    ElementCounter sdkCounter = new ElementCounter();

    for (var context in contexts) {
      buffer.write('<p><h3>');
      buffer.write(context['name']);
      buffer.write('</h3></p>');
      buffer.write('<p>explicitFileCount: ');
      buffer.write(context['explicitFileCount']);
      buffer.write('</p>');
      buffer.write('<p>implicitFileCount: ');
      buffer.write(context['implicitFileCount']);
      buffer.write('</p>');
      buffer.write('<p>workItemQueueLength: ');
      buffer.write(context['workItemQueueLength']);
      buffer.write('</p>');

      AnalysisServer server = _server.analysisServer;

      if (server != null) {
        Folder folder = _findFolder(server, context['name']);
        InternalAnalysisContext ac = _server.analysisServer.folderMap[folder];
        ElementCounter counter = new ElementCounter();

        for (Source source in ac.librarySources) {
          LibraryElement libraryElement = ac.getLibraryElement(source);
          if (libraries.add(libraryElement)) {
            if (libraryElement != null) {
              if (libraryElement.isInSdk) {
                libraryElement.accept(sdkCounter);
              } else {
                libraryElement.accept(counter);
              }
            }
          }
        }
        buffer.write('<p>element count: ');
        buffer.write(
            counter.counts.values.fold(0, (prev, element) => prev + element));
        buffer.write('</p>');
        buffer.write('<p>  (w/docs): ');
        buffer.write(counter.elementsWithDocs);
        buffer.write('</p>');
        buffer.write('<p>total doc span: ');
        buffer.write(counter.totalDocSpan);
        buffer.write('</p>');
      }
    }

    buffer.write('<p><h3>');
    buffer.write('SDK');
    buffer.write('</h3></p>');
    buffer.write('<p>element count: ');
    buffer.write(
        sdkCounter.counts.values.fold(0, (prev, element) => prev + element));
    buffer.write('</p>');
    buffer.write('<p>  (w/docs): ');
    buffer.write(sdkCounter.elementsWithDocs);
    buffer.write('</p>');
    buffer.write('<p>total doc span: ');
    buffer.write(sdkCounter.totalDocSpan);
    buffer.write('</p>');
  }

  /**
   * Write the status of the edit domain (on the main status page) to the given
   * [buffer].
   */
  void _writeEditStatus(StringBuffer buffer) {
    buffer.write('<h3>Edit Domain</h3>');
    _writeTwoColumns(buffer, (StringBuffer buffer) {
      buffer.write('<p><b>Performance Data</b></p>');
      buffer.write('<p>');
      buffer.write(makeLink(COMPLETION_PATH, {}, 'Completion data'));
      buffer.write('</p>');
    }, (StringBuffer buffer) {});
  }

  /**
   * Write a representation of the given [caughtException] to the given
   * [buffer]. If [isCause] is `true`, then the exception was a cause for
   * another exception.
   */
  void _writeException(StringBuffer buffer, CaughtException caughtException,
      {bool isCause: false}) {
    Object exception = caughtException.exception;

    if (exception is AnalysisException) {
      buffer.write('<p>');
      if (isCause) {
        buffer.write('Caused by ');
      }
      buffer.write(exception.message);
      buffer.write('</p>');
      _writeStackTrace(buffer, caughtException.stackTrace);
      CaughtException cause = exception.cause;
      if (cause != null) {
        buffer.write('<blockquote>');
        _writeException(buffer, cause, isCause: true);
        buffer.write('</blockquote>');
      }
    } else {
      buffer.write('<p>');
      if (isCause) {
        buffer.write('Caused by ');
      }
      buffer.write(exception.toString());
      buffer.write('<p>');
      _writeStackTrace(buffer, caughtException.stackTrace);
    }
  }

  /**
   * Write the status of the execution domain (on the main status page) to the
   * given [buffer].
   */
  void _writeExecutionStatus(StringBuffer buffer) {
    AnalysisServer analysisServer = _server.analysisServer;
    ExecutionDomainHandler handler = analysisServer.handlers.firstWhere(
        (RequestHandler handler) => handler is ExecutionDomainHandler,
        orElse: () => null);
    Set<ExecutionService> services = new Set<ExecutionService>();
    if (handler.onFileAnalyzed != null) {
      services.add(ExecutionService.LAUNCH_DATA);
    }

    if (handler != null) {
      buffer.write('<h3>Execution Domain</h3>');
      _writeTwoColumns(buffer, (StringBuffer buffer) {
        _writeSubscriptionList(buffer, ExecutionService.VALUES, services);
      }, (StringBuffer buffer) {});
    }
  }

  void _writeListItem(StringBuffer buffer, writer()) {
    buffer.write('<li>');
    writer();
    buffer.write('</li>');
  }

  void _writeListOfStrings(
      StringBuffer buffer, String listName, Iterable<String> items) {
    List<String> itemList = items.toList();
    itemList.sort((String a, String b) {
      a = a.toLowerCase();
      b = b.toLowerCase();
      return a.compareTo(b);
    });
    buffer.write('List "$listName" containing ${itemList.length} entries:');
    buffer.write('<ul>');
    for (String member in itemList) {
      _writeListItem(buffer, () {
        buffer.write(member);
      });
    }
    buffer.write('</ul>');
  }

  /**
   * Write a representation of an analysis option with the given [name] and
   * [value] to the given [buffer]. The option should be separated from other
   * options unless the [last] flag is true, indicating that this is the last
   * option in the list of options.
   */
  void _writeOption(StringBuffer buffer, String name, Object value,
      {bool last: false}) {
    buffer.write(name);
    buffer.write(' = ');
    buffer.write(value.toString());
    if (!last) {
      buffer.write('<br>');
    }
  }

  /**
   * Write a standard HTML page to the given [buffer]. The page will have the
   * given [title] and a body that is generated by the given [body] generator.
   */
  void _writePage(StringBuffer buffer, String title, List<String> subtitles,
      HtmlGenerator body) {
    DateTime now = new DateTime.now();
    String date = "${now.month}/${now.day}/${now.year}";
    String time =
        "${now.hour}:${_twoDigit(now.minute)}:${_twoDigit(now.second)}.${now.millisecond}";

    buffer.write('<!DOCTYPE html>');
    buffer.write('<html>');
    buffer.write('<head>');
    buffer.write('<meta charset="utf-8">');
    buffer.write(
        '<meta name="viewport" content="width=device-width, initial-scale=1.0">');
    buffer.write('<title>$title</title>');
    buffer.write('<style>');
    buffer.write('a {color: #0000DD; text-decoration: none;}');
    buffer.write('a:link.error {background-color: #FFEEEE;}');
    buffer.write('a:visited.error {background-color: #FFEEEE;}');
    buffer.write('a:hover.error {background-color: #FFEEEE;}');
    buffer.write('a:active.error {background-color: #FFEEEE;}');
    buffer.write(
        'h3 {background-color: #DDDDDD; margin-top: 0em; margin-bottom: 0em;}');
    buffer.write('p {margin-top: 0.5em; margin-bottom: 0.5em;}');
    buffer.write(
        'p.commentary {margin-top: 1em; margin-bottom: 1em; margin-left: 2em; font-style: italic;}');
//    response.write('span.error {text-decoration-line: underline; text-decoration-color: red; text-decoration-style: wavy;}');
    buffer.write(
        'table.column {border: 0px solid black; width: 100%; table-layout: fixed;}');
    buffer.write('td.column {vertical-align: top; width: 50%;}');
    buffer.write('td.right {text-align: right;}');
    buffer.write('</style>');
    buffer.write('</head>');

    buffer.write('<body>');
    buffer.write(
        '<h2>$title <small><small>(as of $time on $date)</small></small></h2>');
    if (subtitles != null && subtitles.isNotEmpty) {
      buffer.write('<blockquote>');
      bool first = true;
      for (String subtitle in subtitles) {
        if (first) {
          first = false;
        } else {
          buffer.write('<br>');
        }
        buffer.write('<b>');
        buffer.write(subtitle);
        buffer.write('</b>');
      }
      buffer.write('</blockquote>');
    }
    try {
      body(buffer);
    } catch (exception, stackTrace) {
      buffer.write('<h3>Exception while creating page</h3>');
      _writeException(buffer, new CaughtException(exception, stackTrace));
    }
    buffer.write('</body>');
    buffer.write('</html>');
  }

  /**
   * Write the recent output section (on the main status page) to the given
   * [buffer] object.
   */
  void _writePluginStatus(StringBuffer buffer) {
    void writePlugin(Plugin plugin) {
      buffer.write(plugin.uniqueIdentifier);
      buffer.write(' (');
      buffer.write(plugin.runtimeType);
      buffer.write(')<br>');
    }
    buffer.write('<h3>Plugin Status</h3><p>');
    writePlugin(AnalysisEngine.instance.enginePlugin);
    writePlugin(_server.serverPlugin);
    for (Plugin plugin in _server.analysisServer.userDefinedPlugins) {
      writePlugin(plugin);
    }
    buffer.write('<p>');
  }

  /**
   * Write the recent output section (on the main status page) to the given
   * [buffer] object.
   */
  void _writeRecentOutput(StringBuffer buffer) {
    buffer.write('<h3>Recent Output</h3>');
    String output = HTML_ESCAPE.convert(_printBuffer.join('\n'));
    if (output.isEmpty) {
      buffer.write('<i>none</i>');
    } else {
      buffer.write('<pre>');
      buffer.write(output);
      buffer.write('</pre>');
    }
  }

  void _writeResponse(HttpRequest request, HtmlGenerator writePage) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.OK;
    response.headers.contentType = _htmlContent;
    try {
      StringBuffer buffer = new StringBuffer();
      try {
        writePage(buffer);
      } catch (exception, stackTrace) {
        buffer.clear();
        _writePage(buffer, 'Internal Exception', [], (StringBuffer buffer) {
          _writeException(buffer, new CaughtException(exception, stackTrace));
        });
      }
      response.write(buffer.toString());
    } finally {
      response.close();
    }
  }

  /**
   * Write a single row within a table to the given [buffer]. The row will have
   * one cell for each of the [columns], and will be a header row if [header] is
   * `true`.
   */
  void _writeRow(StringBuffer buffer, List<Object> columns,
      {bool header: false, List<String> classes}) {
    buffer.write('<tr>');
    int count = columns.length;
    int maxClassIndex = classes == null ? 0 : classes.length - 1;
    for (int i = 0; i < count; i++) {
      String classAttribute = '';
      if (classes != null) {
        String className = classes[min(i, maxClassIndex)];
        if (className != null) {
          classAttribute = ' class="$className"';
        }
      }
      if (header) {
        buffer.write('<th$classAttribute>');
      } else {
        buffer.write('<td$classAttribute>');
      }
      buffer.write(columns[i]);
      if (header) {
        buffer.write('</th>');
      } else {
        buffer.write('</td>');
      }
    }
    buffer.write('</tr>');
  }

  /**
   * Write the status of the service domain (on the main status page) to the
   * given [response] object.
   */
  bool _writeServerStatus(StringBuffer buffer) {
    AnalysisServer analysisServer = _server.analysisServer;
    Set<ServerService> services = analysisServer.serverServices;

    buffer.write('<h3>Server Domain</h3>');
    _writeTwoColumns(buffer, (StringBuffer buffer) {
      if (analysisServer == null) {
        buffer.write('Status: <span style="color:red">Not running</span>');
        return;
      }
      buffer.write('<p>');
      buffer.write('Status: Running<br>');
      buffer.write('Instrumentation: ');
      if (AnalysisEngine.instance.instrumentationService.isActive) {
        buffer.write('<span style="color:red">Active</span>');
      } else {
        buffer.write('Inactive');
      }
      buffer.write('<br>');
      buffer.write('Version: ');
      buffer.write(AnalysisServer.VERSION);
      buffer.write('<br>');
      buffer.write('Process ID: ');
      buffer.write(pid);
      buffer.write('</p>');

      buffer.write('<p><b>Performance Data</b></p>');
      buffer.write('<p>');
      buffer.write(makeLink(
          COMMUNICATION_PERFORMANCE_PATH, {}, 'Communication performance'));
      buffer.write('</p>');
      buffer.write('<p>');
      buffer.write(makeLink(DIAGNOSTIC_PATH, {}, 'General diagnostics'));
      buffer.write('</p>');
    }, (StringBuffer buffer) {
      _writeSubscriptionList(buffer, ServerService.VALUES, services);
    });
    return analysisServer != null;
  }

  /**
   * Write a representation of the given [stackTrace] to the given [buffer].
   */
  void _writeStackTrace(StringBuffer buffer, StackTrace stackTrace) {
    if (stackTrace != null) {
      String trace = stackTrace.toString().replaceAll('#', '<br>#');
      if (trace.startsWith('<br>#')) {
        trace = trace.substring(4);
      }
      buffer.write('<p>');
      buffer.write(trace);
      buffer.write('</p>');
    }
  }

  /**
   * Given a [service] that could be subscribed to and a set of the services
   * that are actually subscribed to ([subscribedServices]), write a
   * representation of the service to the given [buffer].
   */
  void _writeSubscriptionInList(
      StringBuffer buffer, Enum service, Set<Enum> subscribedServices) {
    if (subscribedServices.contains(service)) {
      buffer.write('<code>+ </code>');
    } else {
      buffer.write('<code>- </code>');
    }
    buffer.write(service.name);
    buffer.write('<br>');
  }

  /**
   * Given a [service] that could be subscribed to and a set of paths that are
   * subscribed to the services ([subscribedPaths]), write a representation of
   * the service to the given [buffer].
   */
  void _writeSubscriptionInMap(
      StringBuffer buffer, Enum service, Set<String> subscribedPaths) {
    buffer.write('<p>');
    buffer.write(service.name);
    buffer.write('</p>');
    if (subscribedPaths == null || subscribedPaths.isEmpty) {
      buffer.write('none');
    } else {
      List<String> paths = subscribedPaths.toList();
      paths.sort();
      for (String path in paths) {
        buffer.write('<p>');
        buffer.write(path);
        buffer.write('</p>');
      }
    }
  }

  /**
   * Given a list containing all of the services that can be subscribed to in a
   * single domain ([allServices]) and a set of the services that are actually
   * subscribed to ([subscribedServices]), write a representation of the
   * subscriptions to the given [buffer].
   */
  void _writeSubscriptionList(StringBuffer buffer, List<Enum> allServices,
      Set<Enum> subscribedServices) {
    buffer.write('<p><b>Subscriptions</b></p>');
    buffer.write('<p>');
    for (Enum service in allServices) {
      _writeSubscriptionInList(buffer, service, subscribedServices);
    }
    buffer.write('</p>');
  }

  /**
   * Given a list containing all of the services that can be subscribed to in a
   * single domain ([allServices]) and a set of the services that are actually
   * subscribed to ([subscribedServices]), write a representation of the
   * subscriptions to the given [buffer].
   */
  void _writeSubscriptionMap(StringBuffer buffer, List<Enum> allServices,
      Map<Enum, Set<String>> subscribedServices) {
    buffer.write('<p><b>Subscriptions</b></p>');
    for (Enum service in allServices) {
      _writeSubscriptionInMap(buffer, service, subscribedServices[service]);
    }
  }

  /**
   * Write the targeted results returned by iterating over the [results] to the
   * given [buffer]. The list will have the given [title] written before it.
   */
  void _writeTargetedResults(
      StringBuffer buffer, String title, Iterable<TargetedResult> results) {
    List<TargetedResult> sortedResults = results.toList();
    sortedResults.sort((TargetedResult first, TargetedResult second) {
      int nameOrder =
          first.result.toString().compareTo(second.result.toString());
      if (nameOrder != 0) {
        return nameOrder;
      }
      return first.target.toString().compareTo(second.target.toString());
    });

    buffer.write('<p>');
    buffer.write(title);
    buffer.write('</p><blockquote>');
    if (results.isEmpty) {
      buffer.write('nothing');
    } else {
      for (TargetedResult result in sortedResults) {
        buffer.write('<p>');
        buffer.write(result.result.toString());
        buffer.write(' of ');
        buffer.write(result.target.toString());
        buffer.write('<p>');
      }
    }
    buffer.write('</blockquote>');
  }

  /**
   * Write two columns of information to the given [buffer], where the
   * [leftColumn] and [rightColumn] functions are used to generate the content
   * of those columns.
   */
  void _writeTwoColumns(StringBuffer buffer, HtmlGenerator leftColumn,
      HtmlGenerator rightColumn) {
    buffer
        .write('<table class="column"><tr class="column"><td class="column">');
    leftColumn(buffer);
    buffer.write('</td><td class="column">');
    rightColumn(buffer);
    buffer.write('</td></tr></table>');
  }

  /**
   * Render the given [value] as HTML and append it to the given [buffer]. The
   * [linkParameters] will be used if the value is too large to be displayed on
   * the current page and needs to be linked to a separate page.
   */
  void _writeValueAsHtml(
      StringBuffer buffer, Object value, Map<String, String> linkParameters) {
    if (value == null) {
      buffer.write('<i>null</i>');
    } else if (value is String) {
      buffer.write('<pre>${HTML_ESCAPE.convert(value)}</pre>');
    } else if (value is List) {
      buffer.write('List containing ${value.length} entries');
      buffer.write('<ul>');
      for (var entry in value) {
        _writeListItem(buffer, () {
          _writeValueAsHtml(buffer, entry, linkParameters);
        });
      }
      buffer.write('</ul>');
    } else if (value is AstNode) {
      String link =
          makeLink(AST_PATH, linkParameters, value.runtimeType.toString());
      buffer.write('<i>$link</i>');
    } else if (value is Element) {
      String link =
          makeLink(ELEMENT_PATH, linkParameters, value.runtimeType.toString());
      buffer.write('<i>$link</i>');
    } else if (value is UsedLocalElements) {
      buffer.write('<ul>');
      _writeListItem(buffer, () {
        HashSet<Element> elements = value.elements;
        buffer.write('List "elements" containing ${elements.length} entries');
        buffer.write('<ul>');
        for (Element element in elements) {
          _writeListItem(buffer, () {
            String elementStr = HTML_ESCAPE.convert(element.toString());
            buffer.write('<i>${element.runtimeType}</i>  $elementStr');
          });
        }
        buffer.write('</ul>');
      });
      _writeListItem(buffer, () {
        _writeListOfStrings(buffer, 'members', value.members);
      });
      _writeListItem(buffer, () {
        _writeListOfStrings(buffer, 'readMembers', value.readMembers);
      });
      buffer.write('</ul>');
    } else {
      buffer.write(HTML_ESCAPE.convert(value.toString()));
      buffer.write(' <i>(${value.runtimeType.toString()})</i>');
    }
  }

  /**
   * Create a link to [path] with query parameters [params], with inner HTML
   * [innerHtml]. If [hasError] is `true`, then the link will have the class
   * 'error'.
   */
  static String makeLink(
      String path, Map<String, String> params, String innerHtml,
      [bool hasError = false]) {
    Uri uri = new Uri(path: path, queryParameters: params);
    String href = HTML_ESCAPE.convert(uri.toString());
    String classAttribute = hasError ? ' class="error"' : '';
    return '<a href="$href"$classAttribute>$innerHtml</a>';
  }
}
