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

library formatter_impl;

import 'dart:math';

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/services/writer.dart';

/// Formatter options.
class FormatterOptions {

  /// Create formatter options with defaults derived (where defined) from
  /// the style guide: <http://www.dartlang.org/articles/style-guide/>.
  const FormatterOptions({this.initialIndentationLevel: 0,
                 this.spacesPerIndent: 2,
                 this.lineSeparator: NEW_LINE,
                 this.pageWidth: 80,
                 this.tabsForIndent: false,
                 this.tabSize: 2,
                 this.codeTransforms: false});

  final String lineSeparator;
  final int initialIndentationLevel;
  final int spacesPerIndent;
  final int tabSize;
  final bool tabsForIndent;
  final int pageWidth;
  final bool codeTransforms;
}


/// Thrown when an error occurs in formatting.
class FormatterException implements Exception {

  /// A message describing the error.
  final String message;

  /// Creates a new FormatterException with an optional error [message].
  const FormatterException([this.message = 'FormatterException']);

  FormatterException.forError(List<AnalysisError> errors, [LineInfo line]) :
    message = _createMessage(errors);

  static String _createMessage(errors) {
    //TODO(pquitslund): consider a verbosity flag to add/suppress details
    var errorCode = errors[0].errorCode;
    var phase = errorCode is ParserErrorCode ? 'parsing' : 'scanning';
    return 'An error occured while $phase (${errorCode.name}).';
  }

  String toString() => '$message';
}

/// Specifies the kind of code snippet to format.
class CodeKind {
  final int ordinal;

  const CodeKind._(this.ordinal);

  /// A compilation unit snippet.
  static const COMPILATION_UNIT = const CodeKind._(0);

  /// A statement snippet.
  static const STATEMENT = const CodeKind._(1);

}

/// Dart source code formatter.
abstract class CodeFormatter {

  factory CodeFormatter([FormatterOptions options = const FormatterOptions()])
                        => new CodeFormatterImpl(options);

  /// Format the specified portion (from [offset] with [length]) of the given
  /// [source] string, optionally providing an [indentationLevel].
  FormattedSource format(CodeKind kind, String source, {int offset, int end,
    int indentationLevel: 0, Selection selection: null});

}

/// Source selection state information.
class Selection {

  /// The offset of the source selection.
  final int offset;

  /// The length of the selection.
  final int length;

  Selection(this.offset, this.length);

  String toString() => 'Selection (offset: $offset, length: $length)';
}

/// Formatted source.
class FormattedSource {

  /// Selection state or null if unspecified.
  Selection selection;

  /// Formatted source string.
  final String source;

  /// Create a formatted [source] result, with optional [selection] information.
  FormattedSource(this.source, [this.selection = null]);
}


class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener {

  final FormatterOptions options;
  final errors = <AnalysisError>[];
  final whitespace = new RegExp(r'[\s]+');

  LineInfo lineInfo;

  CodeFormatterImpl(this.options);

  FormattedSource format(CodeKind kind, String source, {int offset, int end,
      int indentationLevel: 0, Selection selection: null}) {

    var startToken = tokenize(source);
    checkForErrors();

    var node = parse(kind, startToken);
    checkForErrors();

    var formatter = new SourceVisitor(options, lineInfo, source, selection);
    node.accept(formatter);

    var formattedSource = formatter.writer.toString();

    checkTokenStreams(startToken, tokenize(formattedSource),
                      allowTransforms: options.codeTransforms);

    return new FormattedSource(formattedSource, formatter.selection);
  }

  checkTokenStreams(Token t1, Token t2, {allowTransforms: false}) =>
      new TokenStreamComparator(lineInfo, t1, t2, transforms: allowTransforms).
          verifyEquals();

  AstNode parse(CodeKind kind, Token start) {

    var parser = new Parser(null, this);

    switch (kind) {
      case CodeKind.COMPILATION_UNIT:
        return parser.parseCompilationUnit(start);
      case CodeKind.STATEMENT:
        return parser.parseStatement(start);
    }

    throw new FormatterException('Unsupported format kind: $kind');
  }

  checkForErrors() {
    if (errors.length > 0) {
      throw new FormatterException.forError(errors);
    }
  }

  onError(AnalysisError error) {
    errors.add(error);
  }

  Token tokenize(String source) {
    var reader = new CharSequenceReader(source);
    var scanner = new Scanner(null, reader, this);
    var token = scanner.tokenize();
    lineInfo = new LineInfo(scanner.lineStarts);
    return token;
  }

}


// Compares two token streams.  Used for sanity checking formatted results.
class TokenStreamComparator {

  final LineInfo lineInfo;
  Token token1, token2;
  bool allowTransforms;

  TokenStreamComparator(this.lineInfo, this.token1, this.token2,
      {transforms: false}) : this.allowTransforms = transforms;

  /// Verify that these two token streams are equal.
  verifyEquals() {
    while (!isEOF(token1)) {
      checkPrecedingComments();
      if (!checkTokens()) {
        throwNotEqualException(token1, token2);
      }
      advance();

    }
    // TODO(pquitslund): consider a better way to notice trailing synthetics
    if (!isEOF(token2) &&
        !(isCLOSE_CURLY_BRACKET(token2) && isEOF(token2.next))) {
      throw new FormatterException(
          'Expected "EOF" but got "$token2".');
    }
  }

  checkPrecedingComments() {
    var comment1 = token1.precedingComments;
    var comment2 = token2.precedingComments;
    while (comment1 != null) {
      if (comment2 == null) {
        throw new FormatterException(
            'Expected comment, "$comment1", at ${describeLocation(token1)}, '
            'but got none.');
      }
      if (!equivalentComments(comment1, comment2)) {
        throwNotEqualException(comment1, comment2);
      }
      comment1 = comment1.next;
      comment2 = comment2.next;
    }
    if (comment2 != null) {
      throw new FormatterException(
          'Unexpected comment, "$comment2", at ${describeLocation(token2)}.');
    }
  }

  bool equivalentComments(Token comment1, Token comment2) =>
      comment1.lexeme.trim() == comment2.lexeme.trim();

  throwNotEqualException(t1, t2) {
    throw new FormatterException(
        'Expected "$t1" but got "$t2", at ${describeLocation(t1)}.');
  }

  String describeLocation(Token token) => lineInfo == null ? '<unknown>' :
      'Line: ${lineInfo.getLocation(token.offset).lineNumber}, '
      'Column: ${lineInfo.getLocation(token.offset).columnNumber}';

  advance() {
    token1 = token1.next;
    token2 = token2.next;
  }

  bool checkTokens() {
    if (token1 == null || token2 == null) {
      return false;
    }
    if (token1 == token2 || token1.lexeme == token2.lexeme) {
      return true;
    }

    // '[' ']' => '[]'
    if (isOPEN_SQ_BRACKET(token1) && isCLOSE_SQUARE_BRACKET(token1.next)) {
      if (isINDEX(token2)) {
        token1 = token1.next;
        return true;
      }
    }
    // '>' '>' => '>>'
    if (isGT(token1) && isGT(token1.next)) {
      if (isGT_GT(token2)) {
        token1 = token1.next;
        return true;
      }
    }
    // Cons(){} => Cons();
    if (isOPEN_CURLY_BRACKET(token1) && isCLOSE_CURLY_BRACKET(token1.next)) {
      if (isSEMICOLON(token2)) {
        token1 = token1.next;
        advance();
        return true;
      }
    }

    // Transform-related special casing
    if (allowTransforms) {

      // Advance past empty statements
      if (isSEMICOLON(token1)) {
        // TODO whitelist
        token1 = token1.next;
        return checkTokens();
      }

      // Advance past synthetic { } tokens
      if (isOPEN_CURLY_BRACKET(token2) || isCLOSE_CURLY_BRACKET(token2)) {
        token2 = token2.next;
        return checkTokens();
      }

    }

    return false;
  }

}

/// Test for token type.
bool tokenIs(Token token, TokenType type) =>
    token != null && token.type == type;

/// Test if this token is an EOF token.
bool isEOF(Token token) => tokenIs(token, TokenType.EOF);

/// Test if this token is a GT token.
bool isGT(Token token) => tokenIs(token, TokenType.GT);

/// Test if this token is a GT_GT token.
bool isGT_GT(Token token) => tokenIs(token, TokenType.GT_GT);

/// Test if this token is an INDEX token.
bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX);

/// Test if this token is a OPEN_CURLY_BRACKET token.
bool isOPEN_CURLY_BRACKET(Token token) =>
    tokenIs(token, TokenType.OPEN_CURLY_BRACKET);

/// Test if this token is a CLOSE_CURLY_BRACKET token.
bool isCLOSE_CURLY_BRACKET(Token token) =>
    tokenIs(token, TokenType.CLOSE_CURLY_BRACKET);

/// Test if this token is a OPEN_SQUARE_BRACKET token.
bool isOPEN_SQ_BRACKET(Token token) =>
    tokenIs(token, TokenType.OPEN_SQUARE_BRACKET);

/// Test if this token is a CLOSE_SQUARE_BRACKET token.
bool isCLOSE_SQUARE_BRACKET(Token token) =>
    tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET);

/// Test if this token is a SEMICOLON token.
bool isSEMICOLON(Token token) =>
    tokenIs(token, TokenType.SEMICOLON);


/// An AST visitor that drives formatting heuristics.
class SourceVisitor implements AstVisitor {

  static final OPEN_CURLY = syntheticToken(TokenType.OPEN_CURLY_BRACKET, '{');
  static final CLOSE_CURLY = syntheticToken(TokenType.CLOSE_CURLY_BRACKET, '}');
  static final SEMI_COLON = syntheticToken(TokenType.SEMICOLON, ';');

  static const SYNTH_OFFSET = -13;

  static StringToken syntheticToken(TokenType type, String value) =>
      new StringToken(type, value, SYNTH_OFFSET);

  static bool isSynthetic(Token token) => token.offset == SYNTH_OFFSET;

  /// The writer to which the source is to be written.
  final SourceWriter writer;

  /// Cached line info for calculating blank lines.
  LineInfo lineInfo;

  /// Cached previous token for calculating preceding whitespace.
  Token previousToken;

  /// A flag to indicate that a newline should be emitted before the next token.
  bool needsNewline = false;

  /// A flag to indicate that user introduced newlines should be emitted before
  /// the next token.
  bool preserveNewlines = false;

  /// A counter for spaces that should be emitted preceding the next token.
  int leadingSpaces = 0;

  /// A flag to specify whether line-leading spaces should be preserved (and
  /// addded to the indent level).
  bool allowLineLeadingSpaces;

  /// A flag to specify whether zero-length spaces should be emmitted.
  bool emitEmptySpaces = false;

  /// Used for matching EOL comments
  final twoSlashes = new RegExp(r'//[^/]');

  /// A weight for potential breakpoints.
  int currentBreakWeight = DEFAULT_SPACE_WEIGHT;

  /// The last issued space weight.
  int lastSpaceWeight = 0;

  /// Original pre-format selection information (may be null).
  final Selection preSelection;

  final bool codeTransforms;


  /// The source being formatted (used in interpolation handling)
  final String source;

  /// Post format selection information.
  Selection selection;


  /// Initialize a newly created visitor to write source code representing
  /// the visited nodes to the given [writer].
  SourceVisitor(FormatterOptions options, this.lineInfo, this.source,
    this.preSelection)
      : writer = new SourceWriter(indentCount: options.initialIndentationLevel,
                                lineSeparator: options.lineSeparator,
                                maxLineLength: options.pageWidth,
                                useTabs: options.tabsForIndent,
                                spacesPerIndent: options.spacesPerIndent),
       codeTransforms = options.codeTransforms;

  visitAdjacentStrings(AdjacentStrings node) {
    visitNodes(node.strings, separatedBy: space);
  }

  visitAnnotation(Annotation node) {
    token(node.atSign);
    visit(node.name);
    token(node.period);
    visit(node.constructorName);
    visit(node.arguments);
  }

  visitArgumentList(ArgumentList node) {
    token(node.leftParenthesis);
    if (node.arguments.isNotEmpty) {
      int weight = lastSpaceWeight++;
      levelSpace(weight, 0);
      visitCommaSeparatedNodes(
          node.arguments,
          followedBy: () => levelSpace(weight));
    }
    token(node.rightParenthesis);
  }

  visitAsExpression(AsExpression node) {
    visit(node.expression);
    space();
    token(node.asOperator);
    space();
    visit(node.type);
  }

  visitAssertStatement(AssertStatement node) {
    token(node.keyword);
    token(node.leftParenthesis);
    visit(node.condition);
    token(node.rightParenthesis);
    token(node.semicolon);
  }

  visitAssignmentExpression(AssignmentExpression node) {
    visit(node.leftHandSide);
    space();
    token(node.operator);
    allowContinuedLines((){
      levelSpace(SINGLE_SPACE_WEIGHT);
      visit(node.rightHandSide);
    });
  }

  @override
  visitAwaitExpression(AwaitExpression node) {
    token(node.awaitKeyword);
    space();
    visit(node.expression);
  }

  visitBinaryExpression(BinaryExpression node) {
    Token operator = node.operator;
    TokenType operatorType = operator.type;
    int addOperands(List<Expression> operands, Expression e, int i) {
      if (e is BinaryExpression && e.operator.type == operatorType) {
        i = addOperands(operands, e.leftOperand, i);
        i = addOperands(operands, e.rightOperand, i);
      } else {
        operands.insert(i++, e);
      }
      return i;
    }
    List<Expression> operands = [];
    addOperands(operands, node.leftOperand, 0);
    addOperands(operands, node.rightOperand, operands.length);
    int weight = lastSpaceWeight++;
    for (int i = 0; i < operands.length; i++) {
      if (i != 0) {
        space();
        token(operator);
        levelSpace(weight);
      }
      visit(operands[i]);
    }
  }

  visitBlock(Block node) {
    token(node.leftBracket);
    indent();
    if (!node.statements.isEmpty) {
      visitNodes(node.statements, precededBy: newlines, separatedBy: newlines);
      newlines();
    } else {
      preserveLeadingNewlines();
    }
    token(node.rightBracket, precededBy: unindent);
  }

  visitBlockFunctionBody(BlockFunctionBody node) {
    token(node.keyword, followedBy: nonBreakingSpace);
    visit(node.block);
  }

  visitBooleanLiteral(BooleanLiteral node) {
    token(node.literal);
  }

  visitBreakStatement(BreakStatement node) {
    token(node.keyword);
    visitNode(node.label, precededBy: space);
    token(node.semicolon);
  }

  visitCascadeExpression(CascadeExpression node) {
    visit(node.target);
    indent(2);
    // Single cascades do not force a linebreak (dartbug.com/16384)
    if (node.cascadeSections.length > 1) {
      newlines();
    }
    visitNodes(node.cascadeSections, separatedBy: newlines);
    unindent(2);
  }

  visitCatchClause(CatchClause node) {

    token(node.onKeyword, followedBy: space);
    visit(node.exceptionType);

    if (node.catchKeyword != null) {
      if (node.exceptionType != null) {
        space();
      }
      token(node.catchKeyword);
      space();
      token(node.leftParenthesis);
      visit(node.exceptionParameter);
      token(node.comma, followedBy: space);
      visit(node.stackTraceParameter);
      token(node.rightParenthesis);
      space();
    } else {
      space();
    }
    visit(node.body);
  }

  visitClassDeclaration(ClassDeclaration node) {
    preserveLeadingNewlines();
    visitMemberMetadata(node.metadata);
    modifier(node.abstractKeyword);
    token(node.classKeyword);
    space();
    visit(node.name);
    allowContinuedLines((){
      visit(node.typeParameters);
      visitNode(node.extendsClause, precededBy: space);
      visitNode(node.withClause, precededBy: space);
      visitNode(node.implementsClause, precededBy: space);
      visitNode(node.nativeClause, precededBy: space);
      space();
    });
    token(node.leftBracket);
    indent();
    if (!node.members.isEmpty) {
      visitNodes(node.members, precededBy: newlines, separatedBy: newlines);
      newlines();
    } else {
      preserveLeadingNewlines();
    }
    token(node.rightBracket, precededBy: unindent);
  }

  visitClassTypeAlias(ClassTypeAlias node) {
    preserveLeadingNewlines();
    visitMemberMetadata(node.metadata);
    modifier(node.abstractKeyword);
    token(node.keyword);
    space();
    visit(node.name);
    visit(node.typeParameters);
    space();
    token(node.equals);
    space();
    visit(node.superclass);
    visitNode(node.withClause, precededBy: space);
    visitNode(node.implementsClause, precededBy: space);
    token(node.semicolon);
  }

  visitComment(Comment node) => null;

  visitCommentReference(CommentReference node) => null;

  visitCompilationUnit(CompilationUnit node) {

    // Cache EOF for leading whitespace calculation
    var start = node.beginToken.previous;
    if (start != null && start.type is TokenType_EOF) {
      previousToken = start;
    }

    var scriptTag = node.scriptTag;
    var directives = node.directives;
    visit(scriptTag);

    visitNodes(directives, separatedBy: newlines, followedBy: newlines);

    visitNodes(node.declarations, separatedBy: newlines);

    preserveLeadingNewlines();

    // Handle trailing whitespace
    token(node.endToken /* EOF */);

    // Be a good citizen, end with a NL
    ensureTrailingNewline();
  }

  visitConditionalExpression(ConditionalExpression node) {
    int weight = lastSpaceWeight++;
    visit(node.condition);
    space();
    token(node.question);
    allowContinuedLines((){
      levelSpace(weight);
      visit(node.thenExpression);
      space();
      token(node.colon);
      levelSpace(weight);
      visit(node.elseExpression);
    });
  }

  visitConstructorDeclaration(ConstructorDeclaration node) {
    visitMemberMetadata(node.metadata);
    modifier(node.externalKeyword);
    modifier(node.constKeyword);
    modifier(node.factoryKeyword);
    visit(node.returnType);
    token(node.period);
    visit(node.name);
    visit(node.parameters);

    // Check for redirects or initializer lists
    if (node.separator != null) {
      if (node.redirectedConstructor != null) {
        visitConstructorRedirects(node);
      } else {
        visitConstructorInitializers(node);
      }
    }

    var body = node.body;
    if (codeTransforms && body is BlockFunctionBody) {
      if (body.block.statements.isEmpty) {
        token(SEMI_COLON);
        newlines();
        return;
      }
    }

    visitPrefixedBody(space, body);
  }

  visitConstructorInitializers(ConstructorDeclaration node) {
    if (node.initializers.length > 1) {
      newlines();
    } else {
      preserveLeadingNewlines();
      levelSpace(lastSpaceWeight++);
    }
    indent(2);
    token(node.separator /* : */);
    space();
    for (var i = 0; i < node.initializers.length; i++) {
      if (i > 0) {
        // preceding comma
        token(node.initializers[i].beginToken.previous);
        newlines();
        space(n: 2, allowLineLeading: true);
      }
      node.initializers[i].accept(this);
    }
    unindent(2);
  }

  visitConstructorRedirects(ConstructorDeclaration node) {
    token(node.separator /* = */, precededBy: space, followedBy: space);
    visitCommaSeparatedNodes(node.initializers);
    visit(node.redirectedConstructor);
  }

  visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    token(node.keyword);
    token(node.period);
    visit(node.fieldName);
    space();
    token(node.equals);
    space();
    visit(node.expression);
  }

  visitConstructorName(ConstructorName node) {
    visit(node.type);
    token(node.period);
    visit(node.name);
  }

  visitContinueStatement(ContinueStatement node) {
    token(node.keyword);
    visitNode(node.label, precededBy: space);
    token(node.semicolon);
  }

  visitDeclaredIdentifier(DeclaredIdentifier node) {
    modifier(node.keyword);
    visitNode(node.type, followedBy: space);
    visit(node.identifier);
  }

  visitDefaultFormalParameter(DefaultFormalParameter node) {
    visit(node.parameter);
    if (node.separator != null) {
      // The '=' separator is preceded by a space
      if (node.separator.type == TokenType.EQ) {
        space();
      }
      token(node.separator);
      visitNode(node.defaultValue, precededBy: space);
    }
  }

  visitDoStatement(DoStatement node) {
    token(node.doKeyword);
    space();
    visit(node.body);
    space();
    token(node.whileKeyword);
    space();
    token(node.leftParenthesis);
    allowContinuedLines((){
      visit(node.condition);
      token(node.rightParenthesis);
    });
    token(node.semicolon);
  }

  visitDoubleLiteral(DoubleLiteral node) {
    token(node.literal);
  }

  visitEmptyFunctionBody(EmptyFunctionBody node) {
    token(node.semicolon);
  }

  visitEmptyStatement(EmptyStatement node) {
    if (!codeTransforms || node.parent is! Block) {
      token(node.semicolon);
    }
  }

  visitEnumConstantDeclaration(EnumConstantDeclaration node){
    visit(node.name);
  }

  visitEnumDeclaration(EnumDeclaration node){
    visitMemberMetadata(node.metadata);
    token(node.keyword);
    space();
    visit(node.name);
    space();
    token(node.leftBracket);
    newlines();
    indent();
    visitCommaSeparatedNodes(node.constants);
    newlines();
    token(node.rightBracket, precededBy: unindent);
  }

  visitExportDirective(ExportDirective node) {
    visitDirectiveMetadata(node.metadata);
    token(node.keyword);
    space();
    visit(node.uri);
    allowContinuedLines((){
      visitNodes(node.combinators, precededBy: space, separatedBy: space);
    });
    token(node.semicolon);
  }

  visitExpressionFunctionBody(ExpressionFunctionBody node) {
    int weight = lastSpaceWeight++;
    token(node.keyword, followedBy: nonBreakingSpace);
    token(node.functionDefinition);
    levelSpace(weight);
    visit(node.expression);
    token(node.semicolon);
  }

  visitExpressionStatement(ExpressionStatement node) {
    visit(node.expression);
    token(node.semicolon);
  }

  visitExtendsClause(ExtendsClause node) {
    token(node.keyword);
    space();
    visit(node.superclass);
  }

  visitFieldDeclaration(FieldDeclaration node) {
    visitMemberMetadata(node.metadata);
    modifier(node.staticKeyword);
    visit(node.fields);
    token(node.semicolon);
  }

  visitFieldFormalParameter(FieldFormalParameter node) {
    token(node.keyword, followedBy: space);
    visitNode(node.type, followedBy: space);
    token(node.thisToken);
    token(node.period);
    visit(node.identifier);
    visit(node.parameters);
  }

  visitForEachStatement(ForEachStatement node) {
    token(node.forKeyword);
    space();
    token(node.leftParenthesis);
    if (node.loopVariable != null) {
      visit(node.loopVariable);
    } else {
      visit(node.identifier);
    }
    space();
    token(node.inKeyword);
    space();
    visit(node.iterable);
    token(node.rightParenthesis);
    space();
    visit(node.body);
  }

  visitFormalParameterList(FormalParameterList node) {
    var groupEnd = null;
    token(node.leftParenthesis);
    var parameters = node.parameters;
    var size = parameters.length;
    for (var i = 0; i < size; i++) {
      var parameter = parameters[i];
      if (i > 0) {
        append(',');
        space();
      }
      if (groupEnd == null && parameter is DefaultFormalParameter) {
        if (identical(parameter.kind, ParameterKind.NAMED)) {
          groupEnd = '}';
          append('{');
        } else {
          groupEnd = ']';
          append('[');
        }
      }
      parameter.accept(this);
    }
    if (groupEnd != null) {
      append(groupEnd);
    }
    token(node.rightParenthesis);
  }

  visitForStatement(ForStatement node) {
    token(node.forKeyword);
    space();
    token(node.leftParenthesis);
    if (node.initialization != null) {
      visit(node.initialization);
    } else {
      if (node.variables == null) {
        space();
      } else {
        visit(node.variables);
      }
    }
    token(node.leftSeparator);
    space();
    visit(node.condition);
    token(node.rightSeparator);
    if (node.updaters != null) {
      space();
      visitCommaSeparatedNodes(node.updaters);
    }
    token(node.rightParenthesis);
    if (node.body is! EmptyStatement) {
      space();
    }
    visit(node.body);
  }

  visitFunctionDeclaration(FunctionDeclaration node) {
    preserveLeadingNewlines();
    visitMemberMetadata(node.metadata);
    modifier(node.externalKeyword);
    visitNode(node.returnType, followedBy: space);
    modifier(node.propertyKeyword);
    visit(node.name);
    visit(node.functionExpression);
  }

  visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
    visit(node.functionDeclaration);
  }

  visitFunctionExpression(FunctionExpression node) {
    visit(node.parameters);
    if (node.body is! EmptyFunctionBody) {
      space();
    }
    visit(node.body);
  }

  visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    visit(node.function);
    visit(node.argumentList);
  }

  visitFunctionTypeAlias(FunctionTypeAlias node) {
    visitMemberMetadata(node.metadata);
    token(node.keyword);
    space();
    visitNode(node.returnType, followedBy: space);
    visit(node.name);
    visit(node.typeParameters);
    visit(node.parameters);
    token(node.semicolon);
  }

  visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    visitNode(node.returnType, followedBy: space);
    visit(node.identifier);
    visit(node.parameters);
  }

  visitHideCombinator(HideCombinator node) {
    token(node.keyword);
    space();
    visitCommaSeparatedNodes(node.hiddenNames);
  }

  visitIfStatement(IfStatement node) {
    var hasElse = node.elseStatement != null;
    token(node.ifKeyword);
    allowContinuedLines((){
      space();
      token(node.leftParenthesis);
      visit(node.condition);
      token(node.rightParenthesis);
    });
    space();
    if (hasElse) {
      printAsBlock(node.thenStatement);
      space();
      token(node.elseKeyword);
      space();
      if (node.elseStatement is IfStatement) {
        visit(node.elseStatement);
      } else {
        printAsBlock(node.elseStatement);
      }
    } else {
      visit(node.thenStatement);
    }
  }

  visitImplementsClause(ImplementsClause node) {
    token(node.keyword);
    space();
    visitCommaSeparatedNodes(node.interfaces);
  }

  visitImportDirective(ImportDirective node) {
    visitDirectiveMetadata(node.metadata);
    token(node.keyword);
    nonBreakingSpace();
    visit(node.uri);
    token(node.deferredToken, precededBy: space);
    token(node.asToken, precededBy: space, followedBy: space);
    allowContinuedLines((){
      visit(node.prefix);
      visitNodes(node.combinators, precededBy: space, separatedBy: space);
    });
    token(node.semicolon);
  }

  visitIndexExpression(IndexExpression node) {
    if (node.isCascaded) {
      token(node.period);
    } else {
      visit(node.target);
    }
    token(node.leftBracket);
    visit(node.index);
    token(node.rightBracket);
  }

  visitInstanceCreationExpression(InstanceCreationExpression node) {
    token(node.keyword);
    nonBreakingSpace();
    visit(node.constructorName);
    visit(node.argumentList);
  }

  visitIntegerLiteral(IntegerLiteral node) {
    token(node.literal);
  }

  visitInterpolationExpression(InterpolationExpression node) {
    if (node.rightBracket != null) {
      token(node.leftBracket);
      visit(node.expression);
      token(node.rightBracket);
    } else {
      token(node.leftBracket);
      visit(node.expression);
    }
  }

  visitInterpolationString(InterpolationString node) {
    token(node.contents);
  }

  visitIsExpression(IsExpression node) {
    visit(node.expression);
    space();
    token(node.isOperator);
    token(node.notOperator);
    space();
    visit(node.type);
  }

  visitLabel(Label node) {
    visit(node.label);
    token(node.colon);
  }

  visitLabeledStatement(LabeledStatement node) {
    visitNodes(node.labels, separatedBy: space, followedBy: space);
    visit(node.statement);
  }

  visitLibraryDirective(LibraryDirective node) {
    visitDirectiveMetadata(node.metadata);
    token(node.keyword);
    space();
    visit(node.name);
    token(node.semicolon);
  }

  visitLibraryIdentifier(LibraryIdentifier node) {
    append(node.name);
  }

  visitListLiteral(ListLiteral node) {
    int weight = lastSpaceWeight++;
    modifier(node.constKeyword);
    visit(node.typeArguments);
    token(node.leftBracket);
    indent();
    levelSpace(weight, 0);
    visitCommaSeparatedNodes(
        node.elements,
        followedBy: () => levelSpace(weight));
    optionalTrailingComma(node.rightBracket);
    token(node.rightBracket, precededBy: unindent);
  }

  visitMapLiteral(MapLiteral node) {
    modifier(node.constKeyword);
    visitNode(node.typeArguments);
    token(node.leftBracket);
    if (!node.entries.isEmpty) {
      newlines();
      indent();
      visitCommaSeparatedNodes(node.entries, followedBy: newlines);
      optionalTrailingComma(node.rightBracket);
      unindent();
      newlines();
    }
    token(node.rightBracket);
  }

  visitMapLiteralEntry(MapLiteralEntry node) {
    visit(node.key);
    token(node.separator);
    space();
    visit(node.value);
  }

  visitMethodDeclaration(MethodDeclaration node) {
    visitMemberMetadata(node.metadata);
    modifier(node.externalKeyword);
    modifier(node.modifierKeyword);
    visitNode(node.returnType, followedBy: space);
    modifier(node.propertyKeyword);
    modifier(node.operatorKeyword);
    visit(node.name);
    if (!node.isGetter) {
      visit(node.parameters);
    }
    visitPrefixedBody(nonBreakingSpace, node.body);
  }

  visitMethodInvocation(MethodInvocation node) {
    visit(node.target);
    token(node.period);
    visit(node.methodName);
    visit(node.argumentList);
  }

  visitNamedExpression(NamedExpression node) {
    visit(node.name);
    visitNode(node.expression, precededBy: space);
  }

  visitNativeClause(NativeClause node) {
    token(node.keyword);
    space();
    visit(node.name);
  }

  visitNativeFunctionBody(NativeFunctionBody node) {
    token(node.nativeToken);
    space();
    visit(node.stringLiteral);
    token(node.semicolon);
  }

  visitNullLiteral(NullLiteral node) {
    token(node.literal);
  }

  visitParenthesizedExpression(ParenthesizedExpression node) {
    token(node.leftParenthesis);
    visit(node.expression);
    token(node.rightParenthesis);
  }

  visitPartDirective(PartDirective node) {
    token(node.keyword);
    space();
    visit(node.uri);
    token(node.semicolon);
  }

  visitPartOfDirective(PartOfDirective node) {
    token(node.keyword);
    space();
    token(node.ofToken);
    space();
    visit(node.libraryName);
    token(node.semicolon);
  }

  visitPostfixExpression(PostfixExpression node) {
    visit(node.operand);
    token(node.operator);
  }

  visitPrefixedIdentifier(PrefixedIdentifier node) {
    visit(node.prefix);
    token(node.period);
    visit(node.identifier);
  }

  visitPrefixExpression(PrefixExpression node) {
    token(node.operator);
    visit(node.operand);
  }

  visitPropertyAccess(PropertyAccess node) {
    if (node.isCascaded) {
      token(node.operator);
    } else {
      visit(node.target);
      token(node.operator);
    }
    visit(node.propertyName);
  }

  visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
    token(node.keyword);
    token(node.period);
    visit(node.constructorName);
    visit(node.argumentList);
  }

  visitRethrowExpression(RethrowExpression node) {
    token(node.keyword);
  }

  visitReturnStatement(ReturnStatement node) {
    var expression = node.expression;
    if (expression == null) {
      token(node.keyword);
      token(node.semicolon);
    } else {
      token(node.keyword);
      allowContinuedLines((){
        space();
        expression.accept(this);
        token(node.semicolon);
      });
    }
  }

  visitScriptTag(ScriptTag node) {
    token(node.scriptTag);
  }

  visitShowCombinator(ShowCombinator node) {
    token(node.keyword);
    space();
    visitCommaSeparatedNodes(node.shownNames);
  }

  visitSimpleFormalParameter(SimpleFormalParameter node) {
    visitMemberMetadata(node.metadata);
    modifier(node.keyword);
    visitNode(node.type, followedBy: nonBreakingSpace);
    visit(node.identifier);
  }

  visitSimpleIdentifier(SimpleIdentifier node) {
    token(node.token);
  }

  visitSimpleStringLiteral(SimpleStringLiteral node) {
    token(node.literal);
  }

  visitStringInterpolation(StringInterpolation node) {
    // Ensure that interpolated strings don't get broken up by treating them as
    // a single String token
    // Process token (for comments etc. but don't print the lexeme)
    token(node.beginToken, printToken: (tok) => null);
    var start = node.beginToken.offset;
    var end = node.endToken.end;
    String string = source.substring(start, end);
    append(string);
    //visitNodes(node.elements);
  }

  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    token(node.keyword);
    token(node.period);
    visit(node.constructorName);
    visit(node.argumentList);
  }

  visitSuperExpression(SuperExpression node) {
    token(node.keyword);
  }

  visitSwitchCase(SwitchCase node) {
    visitNodes(node.labels, separatedBy: space, followedBy: space);
    token(node.keyword);
    space();
    visit(node.expression);
    token(node.colon);
    newlines();
    indent();
    visitNodes(node.statements, separatedBy: newlines);
    unindent();
  }

  visitSwitchDefault(SwitchDefault node) {
    visitNodes(node.labels, separatedBy: space, followedBy: space);
    token(node.keyword);
    token(node.colon);
    newlines();
    indent();
    visitNodes(node.statements, separatedBy: newlines);
    unindent();
  }

  visitSwitchStatement(SwitchStatement node) {
    token(node.keyword);
    space();
    token(node.leftParenthesis);
    visit(node.expression);
    token(node.rightParenthesis);
    space();
    token(node.leftBracket);
    indent();
    newlines();
    visitNodes(node.members, separatedBy: newlines, followedBy: newlines);
    token(node.rightBracket, precededBy: unindent);

  }

  visitSymbolLiteral(SymbolLiteral node) {
    token(node.poundSign);
    var components = node.components;
    for (var component in components) {
      // The '.' separator
      if (component.previous.lexeme == '.') {
        token(component.previous);
      }
      token(component);
    }
  }

  visitThisExpression(ThisExpression node) {
    token(node.keyword);
  }

  visitThrowExpression(ThrowExpression node) {
    token(node.keyword);
    space();
    visit(node.expression);
  }

  visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    visit(node.variables);
    token(node.semicolon);
  }

  visitTryStatement(TryStatement node) {
    token(node.tryKeyword);
    space();
    visit(node.body);
    visitNodes(node.catchClauses, precededBy: space, separatedBy: space);
    token(node.finallyKeyword, precededBy: space, followedBy: space);
    visit(node.finallyBlock);
  }

  visitTypeArgumentList(TypeArgumentList node) {
    token(node.leftBracket);
    visitCommaSeparatedNodes(node.arguments);
    token(node.rightBracket);
  }

  visitTypeName(TypeName node) {
    visit(node.name);
    visit(node.typeArguments);
  }

  visitTypeParameter(TypeParameter node) {
    visitMemberMetadata(node.metadata);
    visit(node.name);
    token(node.keyword /* extends */, precededBy: space, followedBy: space);
    visit(node.bound);
  }

  visitTypeParameterList(TypeParameterList node) {
    token(node.leftBracket);
    visitCommaSeparatedNodes(node.typeParameters);
    token(node.rightBracket);
  }

  visitVariableDeclaration(VariableDeclaration node) {
    visit(node.name);
    if (node.initializer != null) {
      space();
      token(node.equals);
      var initializer = node.initializer;
      if (initializer is ListLiteral || initializer is MapLiteral) {
        space();
        visit(initializer);
      } else if (initializer is BinaryExpression) {
        allowContinuedLines(() {
          levelSpace(lastSpaceWeight);
          visit(initializer);
        });
      } else {
        allowContinuedLines(() {
          levelSpace(SINGLE_SPACE_WEIGHT);
          visit(initializer);
        });
      }
    }
  }

  visitVariableDeclarationList(VariableDeclarationList node) {
    visitMemberMetadata(node.metadata);
    modifier(node.keyword);
    visitNode(node.type, followedBy: space);

    var variables = node.variables;
    // Decls with initializers get their own lines (dartbug.com/16849)
    if (variables.any((v) => (v.initializer != null))) {
      var size = variables.length;
      if (size > 0) {
        var variable;
        for (var i = 0; i < size; i++) {
          variable = variables[i];
          if (i > 0) {
            var comma = variable.beginToken.previous;
            token(comma);
            newlines();
          }
          if (i == 1) {
            indent(2);
          }
          variable.accept(this);
        }
        if (size > 1) {
          unindent(2);
        }
      }
    } else {
      visitCommaSeparatedNodes(node.variables);
    }
  }

  visitVariableDeclarationStatement(VariableDeclarationStatement node) {
    visit(node.variables);
    token(node.semicolon);
  }

  visitWhileStatement(WhileStatement node) {
    token(node.keyword);
    space();
    token(node.leftParenthesis);
    allowContinuedLines((){
      visit(node.condition);
      token(node.rightParenthesis);
    });
    if (node.body is! EmptyStatement) {
      space();
    }
    visit(node.body);
  }

  visitWithClause(WithClause node) {
    token(node.withKeyword);
    space();
    visitCommaSeparatedNodes(node.mixinTypes);
  }

  @override
  visitYieldStatement(YieldStatement node) {
    token(node.yieldKeyword);
    token(node.star);
    space();
    visit(node.expression);
    token(node.semicolon);
  }

  /// Safely visit the given [node].
  visit(AstNode node) {
    if (node != null) {
      node.accept(this);
    }
  }

  /// Visit member metadata
  visitMemberMetadata(NodeList<Annotation> metadata) {
    visitNodes(metadata,
      separatedBy: () {
        space();
        preserveLeadingNewlines();
      },
      followedBy: space);
    if (metadata != null && metadata.length > 0) {
      preserveLeadingNewlines();
    }
  }

  /// Visit member metadata
  visitDirectiveMetadata(NodeList<Annotation> metadata) {
    visitNodes(metadata, separatedBy: newlines, followedBy: newlines);
  }

  /// Visit the given function [body], printing the [prefix] before if given
  /// body is not empty.
  visitPrefixedBody(prefix(), FunctionBody body) {
    if (body is! EmptyFunctionBody) {
      prefix();
    }
    visit(body);
  }

  /// Visit a list of [nodes] if not null, optionally separated and/or preceded
  /// and followed by the given functions.
  visitNodes(NodeList<AstNode> nodes, {precededBy(): null,
      separatedBy() : null, followedBy(): null}) {
    if (nodes != null) {
      var size = nodes.length;
      if (size > 0) {
        if (precededBy != null) {
          precededBy();
        }
        for (var i = 0; i < size; i++) {
          if (i > 0 && separatedBy != null) {
            separatedBy();
          }
          nodes[i].accept(this);
        }
        if (followedBy != null) {
          followedBy();
        }
      }
    }
  }

  /// Visit a comma-separated list of [nodes] if not null.
  visitCommaSeparatedNodes(NodeList<AstNode> nodes, {followedBy(): null}) {
    //TODO(pquitslund): handle this more neatly
    if (followedBy == null) {
      followedBy = space;
    }
    if (nodes != null) {
      var size = nodes.length;
      if (size > 0) {
        var node;
        for (var i = 0; i < size; i++) {
          node = nodes[i];
          if (i > 0) {
            var comma = node.beginToken.previous;
            token(comma);
            followedBy();
          }
          node.accept(this);
        }
      }
    }
  }


  /// Visit a [node], and if not null, optionally preceded or followed by the
  /// specified functions.
  visitNode(AstNode node, {precededBy(): null, followedBy(): null}) {
    if (node != null) {
      if (precededBy != null) {
        precededBy();
      }
      node.accept(this);
      if (followedBy != null) {
        followedBy();
      }
    }
  }

  /// Allow [code] to be continued across lines.
  allowContinuedLines(code()) {
    //TODO(pquitslund): add before
    code();
    //TODO(pquitslund): add after
  }

  /// Emit the given [modifier] if it's non null, followed by non-breaking
  /// whitespace.
  modifier(Token modifier) {
    token(modifier, followedBy: space);
  }

  /// Indicate that at least one newline should be emitted and possibly more
  /// if the source has them.
  newlines() {
    needsNewline = true;
  }

  /// Optionally emit a trailing comma.
  optionalTrailingComma(Token rightBracket) {
    if (rightBracket.previous.lexeme == ',') {
      token(rightBracket.previous);
    }
  }

  /// Indicate that user introduced newlines should be emitted before the next
  /// token.
  preserveLeadingNewlines() {
    preserveNewlines = true;
  }

  token(Token token, {precededBy(), followedBy(), printToken(tok),
      int minNewlines: 0}) {
    if (token != null) {
      if (needsNewline) {
        minNewlines = max(1, minNewlines);
      }
      var emitted = emitPrecedingCommentsAndNewlines(token, min: minNewlines);
      if (emitted > 0) {
        needsNewline = false;
      }
      if (precededBy != null) {
        precededBy();
      }
      checkForSelectionUpdate(token);
      if (printToken == null) {
        append(token.lexeme);
      } else {
        printToken(token);
      }
      if (followedBy != null) {
        followedBy();
      }
      previousToken = token;
    }
  }

  emitSpaces() {
    if (leadingSpaces > 0 || emitEmptySpaces) {
      if (allowLineLeadingSpaces || !writer.currentLine.isWhitespace()) {
        writer.spaces(leadingSpaces, breakWeight: currentBreakWeight);
      }
      leadingSpaces = 0;
      allowLineLeadingSpaces = false;
      emitEmptySpaces = false;
      currentBreakWeight = DEFAULT_SPACE_WEIGHT;
    }
  }

  checkForSelectionUpdate(Token token) {
    // Cache the first token on or AFTER the selection offset
    if (preSelection != null && selection == null) {
      // Check for overshots
      var overshot = token.offset - preSelection.offset;
      if (overshot >= 0) {
        //TODO(pquitslund): update length (may need truncating)
        selection = new Selection(
            writer.toString().length + leadingSpaces - overshot,
            preSelection.length);
      }
    }
  }

  /// Emit a breakable 'non' (zero-length) space
  breakableNonSpace() {
    space(n: 0);
    emitEmptySpaces = true;
  }

  /// Emit level spaces, even if empty (works as a break point).
  levelSpace(int weight, [int n = 1]) {
    space(n: n, breakWeight: weight);
    emitEmptySpaces = true;
  }

  /// Emit a non-breakable space.
  nonBreakingSpace() {
    space(breakWeight: UNBREAKABLE_SPACE_WEIGHT);
  }

  /// Emit a space. If [allowLineLeading] is specified, spaces
  /// will be preserved at the start of a line (in addition to the
  /// indent-level), otherwise line-leading spaces will be ignored.
  space({n: 1, allowLineLeading: false, breakWeight: DEFAULT_SPACE_WEIGHT}) {
    //TODO(pquitslund): replace with a proper space token
    leadingSpaces += n;
    allowLineLeadingSpaces = allowLineLeading;
    currentBreakWeight = breakWeight;
  }

  /// Append the given [string] to the source writer if it's non-null.
  append(String string) {
    if (string != null && !string.isEmpty) {
      emitSpaces();
      writer.write(string);
    }
  }

  /// Indent.
  indent([n = 1]) {
    while (n-- > 0) {
      writer.indent();
    }
  }

  /// Unindent
  unindent([n = 1]) {
    while (n-- > 0) {
      writer.unindent();
    }
  }

  /// Print this statement as if it were a block (e.g., surrounded by braces).
  printAsBlock(Statement statement) {
    if (codeTransforms && statement is! Block) {
      token(OPEN_CURLY);
      indent();
      newlines();
      visit(statement);
      newlines();
      token(CLOSE_CURLY, precededBy: unindent);
    } else {
      visit(statement);
    }
  }

  /// Emit any detected comments and newlines or a minimum as specified
  /// by [min].
  int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) {

    var comment = token.precedingComments;
    var currentToken = comment != null ? comment : token;

    //Handle EOLs before newlines
    if (isAtEOL(comment)) {
      emitComment(comment, previousToken);
      comment = comment.next;
      currentToken = comment != null ? comment : token;
      // Ensure EOL comments force a linebreak
      needsNewline = true;
    }

    var lines = 0;
    if (needsNewline || preserveNewlines) {
      lines = max(min, countNewlinesBetween(previousToken, currentToken));
      preserveNewlines = false;
    }

    emitNewlines(lines);

    previousToken =
        currentToken.previous != null ? currentToken.previous : token.previous;

    while (comment != null) {

      emitComment(comment, previousToken);

      var nextToken = comment.next != null ? comment.next : token;
      var newlines = calculateNewlinesBetweenComments(comment, nextToken);
      if (newlines > 0) {
        emitNewlines(newlines);
        lines += newlines;
      } else {
        var spaces = countSpacesBetween(comment, nextToken);
        if (spaces > 0) {
          space();
        }
      }

      previousToken = comment;
      comment = comment.next;
    }

    previousToken = token;
    return lines;
  }

  void emitNewlines(lines) {
    writer.newlines(lines);
  }

  ensureTrailingNewline() {
    if (writer.lastToken is! NewlineToken) {
      writer.newline();
    }
  }


  /// Test if this EOL [comment] is at the beginning of a line.
  bool isAtBOL(Token comment) =>
      lineInfo.getLocation(comment.offset).columnNumber == 1;

  /// Test if this [comment] is at the end of a line.
  bool isAtEOL(Token comment) =>
      comment != null && comment.toString().trim().startsWith(twoSlashes) &&
      sameLine(comment, previousToken);

  /// Emit this [comment], inserting leading whitespace if appropriate.
  emitComment(Token comment, Token previousToken) {
    if (!writer.currentLine.isWhitespace() && previousToken != null) {
      var ws = countSpacesBetween(previousToken, comment);
      // Preserve one space but no more
      if (ws > 0 && leadingSpaces == 0) {
        space();
      }
    }

    // Don't indent commented-out lines
    if (isAtBOL(comment)) {
      writer.currentLine.clear();
    }

    append(comment.toString().trim());
  }

  /// Count spaces between these tokens.  Tokens on different lines return 0.
  int countSpacesBetween(Token last, Token current) => isEOF(last) ||
      countNewlinesBetween(last, current) > 0 ? 0 : current.offset - last.end;

  /// Count the blanks between these two nodes.
  int countBlankLinesBetween(AstNode lastNode, AstNode currentNode) =>
      countNewlinesBetween(lastNode.endToken, currentNode.beginToken);

  /// Count newlines preceeding this [node].
  int countPrecedingNewlines(AstNode node) =>
      countNewlinesBetween(node.beginToken.previous, node.beginToken);

  /// Count newlines succeeding this [node].
  int countSucceedingNewlines(AstNode node) => node == null ? 0 :
      countNewlinesBetween(node.endToken, node.endToken.next);

  /// Count the blanks between these two tokens.
  int countNewlinesBetween(Token last, Token current) {
    if (last == null || current == null || isSynthetic(last)) {
      return 0;
    }

    return linesBetween(last.end - 1, current.offset);
  }

  /// Calculate the newlines that should separate these comments.
  int calculateNewlinesBetweenComments(Token last, Token current) {
    // Insist on a newline after doc comments or single line comments
    // (NOTE that EOL comments have already been processed).
    if (isOldSingleLineDocComment(last) || isSingleLineComment(last)) {
      return max(1, countNewlinesBetween(last, current));
    } else {
      return countNewlinesBetween(last, current);
    }
  }

  /// Single line multi-line comments (e.g., '/** like this */').
  bool isOldSingleLineDocComment(Token comment) =>
      comment.lexeme.startsWith(r'/**') && singleLine(comment);

  /// Test if this [token] spans just one line.
  bool singleLine(Token token) => linesBetween(token.offset, token.end) < 1;

  /// Test if token [first] is on the same line as [second].
  bool sameLine(Token first, Token second) =>
      countNewlinesBetween(first, second) == 0;

  /// Test if this is a multi-line [comment] (e.g., '/* ...' or '/** ...')
  bool isMultiLineComment(Token comment) =>
      comment.type == TokenType.MULTI_LINE_COMMENT;

  /// Test if this is a single-line [comment] (e.g., '// ...')
  bool isSingleLineComment(Token comment) =>
      comment.type == TokenType.SINGLE_LINE_COMMENT;

  /// Test if this [comment] is a block comment (e.g., '/* like this */')..
  bool isBlock(Token comment) =>
      isMultiLineComment(comment) && singleLine(comment);

  /// Count the lines between two offsets.
  int linesBetween(int lastOffset, int currentOffset) {
    var lastLine =
        lineInfo.getLocation(lastOffset).lineNumber;
    var currentLine =
        lineInfo.getLocation(currentOffset).lineNumber;
    return currentLine - lastLine;
  }

  String toString() => writer.toString();
}
