// Copyright (c) 2012, 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 js_ast.printer;

import 'characters.dart' as char_codes;
import 'nodes.dart';
import 'precedence.dart';
import 'strings.dart';

class JavaScriptPrintingOptions {
  final bool utf8;
  final bool shouldCompressOutput;
  final bool minifyLocalVariables;
  final bool preferSemicolonToNewlineInMinifiedOutput;

  const JavaScriptPrintingOptions({
    this.utf8 = false,
    this.shouldCompressOutput = false,
    this.minifyLocalVariables = false,
    this.preferSemicolonToNewlineInMinifiedOutput = false,
  });
}

/// An environment in which JavaScript printing is done.  Provides emitting of
/// text and pre- and post-visit callbacks.
abstract class JavaScriptPrintingContext {
  /// Signals an error.  This should happen only for serious internal errors.
  void error(String message) {
    throw message;
  }

  /// Adds [string] to the output.
  void emit(String string);

  /// Callback for the start of printing of [node]. [startPosition] is the
  /// position of the first non-whitespace character of [node].
  ///
  /// [enterNode] is called in pre-traversal order.
  void enterNode(Node node, int startPosition) {}

  /// Callback for the end of printing of [node]. [startPosition] is the
  /// position of the first non-whitespace character of [node] (also provided
  /// in the [enterNode] callback), [endPosition] is the position immediately
  /// following the last character of [node]. [closingPosition] is the
  /// position of the ending delimiter of [node]. This is only provided for
  /// [Fun] nodes and is `null` otherwise.
  ///
  /// [enterNode] is called in post-traversal order.
  void exitNode(
      Node node, int startPosition, int endPosition, int? closingPosition) {}

  /// Should return `true` if the printing tolerates unfinalized deferred AST
  /// nodes.
  bool get isDebugContext => false;
}

/// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
  final StringBuffer buffer = StringBuffer();

  @override
  void emit(String string) {
    buffer.write(string);
  }

  String getText() => buffer.toString();
}

class _DebugJavaScriptPrintingContext extends SimpleJavaScriptPrintingContext {
  @override
  bool get isDebugContext => true;
}

String DebugPrint(Node node, {bool utf8 = false}) {
  JavaScriptPrintingOptions options = JavaScriptPrintingOptions(utf8: utf8);
  SimpleJavaScriptPrintingContext context = _DebugJavaScriptPrintingContext();
  Printer printer = Printer(options, context);
  printer.visit(node);
  return context.getText();
}

class Printer implements NodeVisitor<void> {
  final JavaScriptPrintingOptions options;
  final JavaScriptPrintingContext context;
  final bool shouldCompressOutput;
  final DanglingElseVisitor danglingElseVisitor;
  final LocalNamer localNamer;
  final bool isDebugContext;

  int _charCount = 0;
  bool inForInit = false;
  bool atStatementBegin = false;

  // The JavaScript grammar has two sets of related productions for property
  // accesses - for MemberExpression and CallExpression.  A subset of
  // productions that illustrate the two sets:
  //
  //     MemberExpression :
  //         PrimaryExpression
  //         MemberExpression . IdentifierName
  //         new MemberExpression Arguments
  //         ...
  //
  //     CallExpression :
  //         MemberExpression Arguments
  //         CallExpression Arguments
  //         CallExpression . IdentifierName
  //         ...
  //
  // This means that a call can be in the 'function' part of another call, but
  // not in the 'function' part of a `new` expression. When printing a `new`
  // expression, a call in the 'function' part needs to be in parentheses to
  // ensure that the arguments of the call are not mistaken for the arguments of
  // the enclosing `new` expression.
  //
  // We handle the difference in required parenthesization by making the
  // required precedence of the receiver of an access be context-dependent.
  // Both "MemberExpression . IdentifierName" and "CallExpression
  // . IdentifierName" are represented as a PropertyAccess AST node. The context
  // is tracked by [inNewTarget], which is true only during the printing of
  // the 'function' part of a NewExpression.
  bool inNewTarget = false;

  bool pendingSemicolon = false;
  bool pendingSpace = false;

  // The current indentation level.
  int _indentLevel = 0;
  // A cache of all indentation strings used so far.
  final List<String> _indentList = [''];

  static final identifierCharacterRegExp = RegExp(r'^[a-zA-Z_0-9$]');
  static final expressionContinuationRegExp = RegExp(r'^[-+([]');

  Printer(this.options, this.context)
      : isDebugContext = context.isDebugContext,
        shouldCompressOutput = options.shouldCompressOutput,
        danglingElseVisitor = DanglingElseVisitor(context),
        localNamer = determineRenamer(
            options.shouldCompressOutput, options.minifyLocalVariables);

  static LocalNamer determineRenamer(
      bool shouldCompressOutput, bool allowVariableMinification) {
    return (shouldCompressOutput && allowVariableMinification)
        ? MinifyRenamer()
        : IdentityNamer();
  }

  // The current indentation string.
  String get indentation {
    // Lazily add new indentation strings as required.
    while (_indentList.length <= _indentLevel) {
      _indentList.add('${_indentList.last}  ');
    }
    return _indentList[_indentLevel];
  }

  void indentMore() {
    _indentLevel++;
  }

  void indentLess() {
    _indentLevel--;
  }

  /// Always emit a newline, even under `enableMinification`.
  void forceLine() {
    out('\n', isWhitespace: true);
  }

  /// Emits a newline for readability.
  void lineOut() {
    if (!shouldCompressOutput) forceLine();
  }

  void spaceOut() {
    if (!shouldCompressOutput) out(' ', isWhitespace: true);
  }

  String lastAddedString = '\u0000';

  int get lastCharCode {
    assert(lastAddedString.isNotEmpty);
    return lastAddedString.codeUnitAt(lastAddedString.length - 1);
  }

  void out(String str, {bool isWhitespace = false}) {
    if (str != '') {
      if (pendingSemicolon) {
        if (!shouldCompressOutput) {
          _emit(';');
        } else if (str != '}') {
          // We want to output newline instead of semicolon because it makes
          // the raw stack traces much easier to read and it also makes line-
          // based tools like diff work much better.  JavaScript will
          // automatically insert the semicolon at the newline if it means a
          // parsing error is avoided, so we can only do this trick if the
          // next line is not something that can be glued onto a valid
          // expression to make a new valid expression.

          // If we're using the new emitter where most pretty printed code
          // is escaped in strings, it is a lot easier to deal with semicolons
          // than newlines because the former doesn't need escaping.
          if (options.preferSemicolonToNewlineInMinifiedOutput ||
              expressionContinuationRegExp.hasMatch(str)) {
            _emit(';');
          } else {
            _emit('\n');
          }
        }
      }
      if (pendingSpace &&
          (!shouldCompressOutput || identifierCharacterRegExp.hasMatch(str))) {
        _emit(' ');
      }
      pendingSpace = false;
      pendingSemicolon = false;
      if (!isWhitespace) {
        enterNode();
      }
      _emit(str);
      lastAddedString = str;
    }
  }

  void outLn(String str) {
    out(str);
    lineOut();
  }

  void outSemicolonLn() {
    if (shouldCompressOutput) {
      pendingSemicolon = true;
    } else {
      out(';');
      forceLine();
    }
  }

  void outIndent(String str) {
    indent();
    out(str);
  }

  void outIndentLn(String str) {
    indent();
    outLn(str);
  }

  void indent() {
    if (!shouldCompressOutput) {
      out(indentation, isWhitespace: true);
    }
  }

  EnterExitNode? currentNode;

  void _emit(String text) {
    context.emit(text);
    _charCount += text.length;
  }

  void startNode(Node node) {
    currentNode = EnterExitNode(currentNode, node);
    if (node is DeferredExpression) {
      if (!isDebugContext || node.isFinalized) {
        startNode(node.value);
      }
    }
  }

  void enterNode() {
    currentNode!.addToNode(context, _charCount);
  }

  void endNode(Node node) {
    if (node is DeferredExpression) {
      if (!isDebugContext || node.isFinalized) {
        endNode(node.value);
      }
    }
    assert(currentNode!.node == node);
    currentNode = currentNode!.exitNode(context, _charCount);
  }

  void visit(Node node) {
    startNode(node);
    node.accept(this);
    endNode(node);
  }

  void visitCommaSeparated(List<Expression> nodes, Precedence hasRequiredType,
      {required bool newInForInit, required bool newAtStatementBegin}) {
    for (int i = 0; i < nodes.length; i++) {
      if (i != 0) {
        atStatementBegin = false;
        out(',');
        spaceOut();
      }
      visitNestedExpression(nodes[i], hasRequiredType,
          newInForInit: newInForInit, newAtStatementBegin: newAtStatementBegin);
    }
  }

  void visitAll(List<Node> nodes) {
    nodes.forEach(visit);
  }

  Expression _undefer(Expression node) {
    if (isDebugContext && !node.isFinalized) return node;
    if (node is DeferredExpression) return _undefer(node.value);
    return node;
  }

  @override
  void visitProgram(Program program) {
    if (program.body.isNotEmpty) {
      visitAll(program.body);
    }
  }

  bool blockBody(Statement body,
      {required bool needsSeparation,
      required bool needsNewline,
      bool needsBraces = false}) {
    if (body is Block) {
      spaceOut();
      blockOut(body, shouldIndent: false, needsNewline: needsNewline);
      return true;
    }
    if (needsBraces) {
      spaceOut();
      out('{');
    }
    if (shouldCompressOutput && needsSeparation) {
      // If [shouldCompressOutput] is false, then the 'lineOut' will insert
      // the separation.
      out(' ', isWhitespace: true);
    } else {
      lineOut();
    }
    indentMore();
    visit(body);
    indentLess();
    if (needsBraces) {
      indent();
      out('}');
      return true;
    }
    return false;
  }

  /// Elide Blocks and DeferredStatements with Blocks as children.
  void blockOutWithoutBraces(Node node) {
    if (node is Block) {
      startNode(node);
      Block block = node;
      block.statements.forEach(blockOutWithoutBraces);
      endNode(node);
    } else if (node is DeferredStatement) {
      startNode(node);
      blockOutWithoutBraces(node.statement);
      endNode(node);
    } else {
      visit(node);
    }
  }

  int blockOut(Block node,
      {required bool shouldIndent, required bool needsNewline}) {
    if (shouldIndent) indent();
    startNode(node);
    out('{');
    lineOut();
    indentMore();
    node.statements.forEach(blockOutWithoutBraces);
    indentLess();
    indent();
    out('}');
    int closingPosition = _charCount - 1;
    endNode(node);
    if (needsNewline) lineOut();
    return closingPosition;
  }

  @override
  void visitBlock(Block block) {
    blockOut(block, shouldIndent: true, needsNewline: true);
  }

  @override
  void visitExpressionStatement(ExpressionStatement node) {
    indent();
    visitNestedExpression(node.expression, Precedence.expression,
        newInForInit: false, newAtStatementBegin: true);
    outSemicolonLn();
  }

  @override
  void visitEmptyStatement(EmptyStatement node) {
    outIndentLn(';');
  }

  void ifOut(If node, bool shouldIndent) {
    Statement then = node.then;
    Statement elsePart = node.otherwise;
    bool hasElse = node.hasElse;

    // Handle dangling elses and a workaround for Android 4.0 stock browser.
    // Android 4.0 requires braces for a single do-while in the `then` branch.
    // See issue 10923.
    bool needsBraces =
        hasElse && (then is Do || then.accept(danglingElseVisitor));
    if (shouldIndent) indent();
    out('if');
    spaceOut();
    out('(');
    visitNestedExpression(node.condition, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    bool thenWasBlock = blockBody(then,
        needsSeparation: false,
        needsNewline: !hasElse,
        needsBraces: needsBraces);
    if (hasElse) {
      if (thenWasBlock) {
        spaceOut();
      } else {
        indent();
      }
      out('else');
      if (elsePart is If) {
        pendingSpace = true;
        startNode(elsePart);
        ifOut(elsePart, false);
        endNode(elsePart);
      } else {
        blockBody(elsePart, needsSeparation: true, needsNewline: true);
      }
    }
  }

  @override
  void visitIf(If node) {
    ifOut(node, true);
  }

  @override
  void visitFor(For loop) {
    outIndent('for');
    spaceOut();
    out('(');
    if (loop.init != null) {
      visitNestedExpression(loop.init!, Precedence.expression,
          newInForInit: true, newAtStatementBegin: false);
    }
    out(';');
    if (loop.condition != null) {
      spaceOut();
      visitNestedExpression(loop.condition!, Precedence.expression,
          newInForInit: false, newAtStatementBegin: false);
    }
    out(';');
    if (loop.update != null) {
      spaceOut();
      visitNestedExpression(loop.update!, Precedence.expression,
          newInForInit: false, newAtStatementBegin: false);
    }
    out(')');
    blockBody(loop.body, needsSeparation: false, needsNewline: true);
  }

  @override
  void visitForIn(ForIn loop) {
    outIndent('for');
    spaceOut();
    out('(');
    visitNestedExpression(loop.leftHandSide, Precedence.expression,
        newInForInit: true, newAtStatementBegin: false);
    out(' in');
    pendingSpace = true;
    visitNestedExpression(loop.object, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    blockBody(loop.body, needsSeparation: false, needsNewline: true);
  }

  @override
  void visitWhile(While loop) {
    outIndent('while');
    spaceOut();
    out('(');
    visitNestedExpression(loop.condition, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    blockBody(loop.body, needsSeparation: false, needsNewline: true);
  }

  @override
  void visitDo(Do loop) {
    outIndent('do');
    if (blockBody(loop.body, needsSeparation: true, needsNewline: false)) {
      spaceOut();
    } else {
      indent();
    }
    out('while');
    spaceOut();
    out('(');
    visitNestedExpression(loop.condition, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    outSemicolonLn();
  }

  @override
  void visitContinue(Continue node) {
    if (node.targetLabel == null) {
      outIndent('continue');
    } else {
      outIndent('continue ${node.targetLabel}');
    }
    outSemicolonLn();
  }

  @override
  void visitBreak(Break node) {
    if (node.targetLabel == null) {
      outIndent('break');
    } else {
      outIndent('break ${node.targetLabel}');
    }
    outSemicolonLn();
  }

  @override
  void visitReturn(Return node) {
    final value = node.value;
    if (value == null) {
      outIndent('return');
    } else {
      outIndent('return');
      pendingSpace = true;
      visitNestedExpression(value, Precedence.expression,
          newInForInit: false, newAtStatementBegin: false);
    }
    // Set the closing position to be before the optional semicolon.
    currentNode!.closingPosition = _charCount;
    outSemicolonLn();
  }

  @override
  void visitDartYield(DartYield node) {
    if (node.hasStar) {
      outIndent('yield*');
    } else {
      outIndent('yield');
    }
    pendingSpace = true;
    visitNestedExpression(node.expression, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    outSemicolonLn();
  }

  @override
  void visitThrow(Throw node) {
    outIndent('throw');
    pendingSpace = true;
    visitNestedExpression(node.expression, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    outSemicolonLn();
  }

  @override
  void visitTry(Try node) {
    outIndent('try');
    blockBody(node.body, needsSeparation: true, needsNewline: false);
    if (node.catchPart != null) {
      visit(node.catchPart!);
    }
    if (node.finallyPart != null) {
      spaceOut();
      out('finally');
      blockBody(node.finallyPart!, needsSeparation: true, needsNewline: true);
    } else {
      lineOut();
    }
  }

  @override
  void visitCatch(Catch node) {
    spaceOut();
    out('catch');
    spaceOut();
    out('(');
    visitNestedExpression(node.declaration, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    blockBody(node.body, needsSeparation: false, needsNewline: false);
  }

  @override
  void visitSwitch(Switch node) {
    outIndent('switch');
    spaceOut();
    out('(');
    visitNestedExpression(node.key, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    spaceOut();
    outLn('{');
    indentMore();
    visitAll(node.cases);
    indentLess();
    outIndentLn('}');
  }

  @override
  void visitCase(Case node) {
    outIndent('case');
    pendingSpace = true;
    visitNestedExpression(node.expression, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    outLn(':');
    if (node.body.statements.isNotEmpty) {
      indentMore();
      blockOutWithoutBraces(node.body);
      indentLess();
    }
  }

  @override
  void visitDefault(Default node) {
    outIndentLn('default:');
    if (node.body.statements.isNotEmpty) {
      indentMore();
      blockOutWithoutBraces(node.body);
      indentLess();
    }
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    outIndent('${node.label}:');
    blockBody(node.body, needsSeparation: false, needsNewline: true);
  }

  int functionOut(Fun fun, Expression? name, VarCollector vars) {
    out('function');
    if (name != null) {
      out(' ');
      // Name must be a [Decl]. Therefore only test for primary expressions.
      visitNestedExpression(name, Precedence.primary,
          newInForInit: false, newAtStatementBegin: false);
    }
    localNamer.enterScope(vars);
    out('(');
    visitCommaSeparated(fun.params, Precedence.primary,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    switch (fun.asyncModifier) {
      case AsyncModifier.sync:
        break;
      case AsyncModifier.async:
        out(' ', isWhitespace: true);
        out('async');
        break;
      case AsyncModifier.syncStar:
        out(' ', isWhitespace: true);
        out('sync*');
        break;
      case AsyncModifier.asyncStar:
        out(' ', isWhitespace: true);
        out('async*');
        break;
    }
    spaceOut();
    int closingPosition =
        blockOut(fun.body, shouldIndent: false, needsNewline: false);
    localNamer.leaveScope();
    return closingPosition;
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration declaration) {
    VarCollector vars = VarCollector();
    vars.visitFunctionDeclaration(declaration);
    indent();
    startNode(declaration.function);
    currentNode!.closingPosition =
        functionOut(declaration.function, declaration.name, vars);
    endNode(declaration.function);
    lineOut();
  }

  void visitNestedExpression(Expression node, Precedence requiredPrecedence,
      {required bool newInForInit, required bool newAtStatementBegin}) {
    Precedence precedenceLevel = (isDebugContext && !node.isFinalized)
        ? Precedence.call
        : node.precedenceLevel;
    bool needsParentheses =
        // a - (b + c).
        (requiredPrecedence != Precedence.expression &&
                precedenceLevel.index < requiredPrecedence.index) ||
            // for (a = (x in o); ... ; ... ) { ... }
            (newInForInit && node is Binary && node.op == 'in') ||
            // (function() { ... })().
            // ({a: 2, b: 3}.toString()).
            (newAtStatementBegin &&
                (node is NamedFunction ||
                    node is FunctionExpression ||
                    node is ObjectInitializer));
    final savedInForInit = inForInit;
    if (needsParentheses) {
      inForInit = false;
      atStatementBegin = false;
      inNewTarget = false;
      out('(');
      visit(node);
      out(')');
    } else {
      inForInit = newInForInit;
      atStatementBegin = newAtStatementBegin;
      visit(node);
    }
    inForInit = savedInForInit;
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList list) {
    out('var ');
    final nodes = list.declarations;
    if (inForInit) {
      visitCommaSeparated(nodes, Precedence.assignment,
          newInForInit: inForInit, newAtStatementBegin: false);
    } else {
      // Print 'big' declarations on their own line, while keeping adjacent
      // small and uninitialized declarations on the same line.
      bool useIndent = nodes.length > 1 && list.indentSplits;
      if (useIndent) {
        indentMore();
      }
      bool lastWasBig = false;
      for (int i = 0; i < nodes.length; i++) {
        Expression node = nodes[i];
        bool thisIsBig = !_isSmallInitialization(node);
        if (i > 0) {
          atStatementBegin = false;
          out(',');
          if (lastWasBig || thisIsBig) {
            lineOut();
            indent();
          } else {
            spaceOut();
          }
        }
        visitNestedExpression(node, Precedence.assignment,
            newInForInit: inForInit, newAtStatementBegin: false);
        lastWasBig = thisIsBig;
      }
      if (useIndent) {
        indentLess();
      }
    }
  }

  bool _isSmallInitialization(Node node) {
    if (node is VariableInitialization) {
      if (node.value == null) return true;
      Node value = _undefer(node.value!);
      if (value is This) return true;
      if (value is LiteralNull) return true;
      if (value is LiteralNumber) return true;
      if (value is LiteralString && value.value.length <= 6) return true;
      if (value is ObjectInitializer && value.properties.isEmpty) return true;
      if (value is ArrayInitializer && value.elements.isEmpty) return true;
      if (value is Name && value.name.length <= 6) return true;
    }
    return false;
  }

  void _outputIncDec(String op, Expression variable, [Expression? alias]) {
    if (op == '+') {
      if (lastCharCode == char_codes.$PLUS) out(' ', isWhitespace: true);
      out('++');
    } else {
      if (lastCharCode == char_codes.$MINUS) out(' ', isWhitespace: true);
      out('--');
    }
    if (alias != null) startNode(alias);
    visitNestedExpression(variable, Precedence.unary,
        newInForInit: inForInit, newAtStatementBegin: false);
    if (alias != null) endNode(alias);
  }

  @override
  void visitAssignment(Assignment assignment) {
    /// To print assignments like `a = a + 1` and `a = a + b` compactly as
    /// `++a` and `a += b` in the face of [DeferredExpression]s we detect the
    /// pattern of the undeferred assignment.
    String? op = assignment.op;
    Node leftHandSide = _undefer(assignment.leftHandSide);
    Node rightHandSide = _undefer(assignment.value);
    if ((op == '+' || op == '-') &&
        leftHandSide is VariableUse &&
        rightHandSide is LiteralNumber &&
        rightHandSide.value == '1') {
      // Output 'a += 1' as '++a' and 'a -= 1' as '--a'.
      _outputIncDec(op!, assignment.leftHandSide);
      return;
    }
    if (!assignment.isCompound &&
        leftHandSide is VariableUse &&
        rightHandSide is Binary) {
      Expression rLeft = _undefer(rightHandSide.left);
      Expression rRight = _undefer(rightHandSide.right);
      String? op = rightHandSide.op;
      if (op == '+' ||
          op == '-' ||
          op == '/' ||
          op == '*' ||
          op == '%' ||
          op == '^' ||
          op == '&' ||
          op == '|') {
        if (rLeft is VariableUse && rLeft.name == leftHandSide.name) {
          // Output 'a = a + 1' as '++a' and 'a = a - 1' as '--a'.
          if ((op == '+' || op == '-') &&
              rRight is LiteralNumber &&
              rRight.value == '1') {
            _outputIncDec(op, assignment.leftHandSide, rightHandSide.left);
            return;
          }
          // Output 'a = a + b' as 'a += b'.
          startNode(rightHandSide.left);
          visitNestedExpression(assignment.leftHandSide, Precedence.call,
              newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
          endNode(rightHandSide.left);
          spaceOut();
          out(op);
          out('=');
          spaceOut();
          visitNestedExpression(rRight, Precedence.assignment,
              newInForInit: inForInit, newAtStatementBegin: false);
          return;
        }
      }
    }
    visitNestedExpression(assignment.leftHandSide, Precedence.call,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);

    spaceOut();
    if (op != null) out(op);
    out('=');
    spaceOut();
    visitNestedExpression(assignment.value, Precedence.assignment,
        newInForInit: inForInit, newAtStatementBegin: false);
  }

  @override
  void visitVariableInitialization(VariableInitialization initialization) {
    visitNestedExpression(initialization.declaration, Precedence.call,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
    if (initialization.value != null) {
      spaceOut();
      out('=');
      spaceOut();
      visitNestedExpression(initialization.value!, Precedence.assignment,
          newInForInit: inForInit, newAtStatementBegin: false);
    }
  }

  @override
  void visitConditional(Conditional cond) {
    visitNestedExpression(cond.condition, Precedence.logicalOr,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
    spaceOut();
    out('?');
    spaceOut();
    // The then part is allowed to have an 'in'.
    visitNestedExpression(cond.then, Precedence.assignment,
        newInForInit: false, newAtStatementBegin: false);
    spaceOut();
    out(':');
    spaceOut();
    visitNestedExpression(cond.otherwise, Precedence.assignment,
        newInForInit: inForInit, newAtStatementBegin: false);
  }

  @override
  void visitNew(New node) {
    out('new ');
    final savedInNewTarget = inNewTarget;
    inNewTarget = true;
    visitNestedExpression(node.target, Precedence.leftHandSide,
        newInForInit: inForInit, newAtStatementBegin: false);
    out('(');
    inNewTarget = false;
    visitCommaSeparated(node.arguments, Precedence.assignment,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    inNewTarget = savedInNewTarget;
  }

  @override
  void visitCall(Call call) {
    visitNestedExpression(call.target, Precedence.call,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
    out('(');
    visitCommaSeparated(call.arguments, Precedence.assignment,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
  }

  @override
  void visitBinary(Binary binary) {
    Expression left = binary.left;
    Expression right = binary.right;
    String op = binary.op;
    Precedence leftPrecedenceRequirement;
    Precedence rightPrecedenceRequirement;
    bool leftSpace = true; // left<HERE>op right
    switch (op) {
      case ',':
        //  x, (y, z) <=> (x, y), z.
        leftPrecedenceRequirement = Precedence.expression;
        rightPrecedenceRequirement = Precedence.expression;
        leftSpace = false;
        break;
      case '||':
        leftPrecedenceRequirement = Precedence.logicalOr;
        // x || (y || z) <=> (x || y) || z.
        rightPrecedenceRequirement = Precedence.logicalOr;
        break;
      case '&&':
        leftPrecedenceRequirement = Precedence.logicalAnd;
        // x && (y && z) <=> (x && y) && z.
        rightPrecedenceRequirement = Precedence.logicalAnd;
        break;
      case '|':
        leftPrecedenceRequirement = Precedence.bitOr;
        // x | (y | z) <=> (x | y) | z.
        rightPrecedenceRequirement = Precedence.bitOr;
        break;
      case '^':
        leftPrecedenceRequirement = Precedence.bitXor;
        // x ^ (y ^ z) <=> (x ^ y) ^ z.
        rightPrecedenceRequirement = Precedence.bitXor;
        break;
      case '&':
        leftPrecedenceRequirement = Precedence.bitAnd;
        // x & (y & z) <=> (x & y) & z.
        rightPrecedenceRequirement = Precedence.bitAnd;
        break;
      case '==':
      case '!=':
      case '===':
      case '!==':
        leftPrecedenceRequirement = Precedence.equality;
        rightPrecedenceRequirement = Precedence.relational;
        break;
      case '<':
      case '>':
      case '<=':
      case '>=':
      case 'instanceof':
      case 'in':
        leftPrecedenceRequirement = Precedence.relational;
        rightPrecedenceRequirement = Precedence.shift;
        break;
      case '>>':
      case '<<':
      case '>>>':
        leftPrecedenceRequirement = Precedence.shift;
        rightPrecedenceRequirement = Precedence.additive;
        break;
      case '+':
      case '-':
        leftPrecedenceRequirement = Precedence.additive;
        // We cannot remove parenthesis for "+" because
        //   x + (y + z) <!=> (x + y) + z:
        // Example:
        //   "a" + (1 + 2) => "a3";
        //   ("a" + 1) + 2 => "a12";
        rightPrecedenceRequirement = Precedence.multiplicative;
        break;
      case '*':
      case '/':
      case '%':
        leftPrecedenceRequirement = Precedence.multiplicative;
        // We cannot remove parenthesis for "*" because of precision issues.
        rightPrecedenceRequirement = Precedence.unary;
        break;
      case '**':
        // Exponentiation associates to the right, so `a ** b ** c` parses as `a
        // ** (b ** c)`. To generate the appropriate output, the left has a
        // higher precedence than the current node. The next precedence level
        // ([UNARY]), is skipped as the left hand side of an exponentiation
        // operator [must be an UPDATE
        // expression](https://tc39.es/ecma262/#sec-exp-operator).  Skipping
        // [UNARY] avoids printing `-1 ** 2`, which is a syntax error.
        leftPrecedenceRequirement = Precedence.update;
        rightPrecedenceRequirement = Precedence.exponentiation;
        break;
      default:
        leftPrecedenceRequirement = Precedence.expression;
        rightPrecedenceRequirement = Precedence.expression;
        context.error('Forgot operator: $op');
    }

    visitNestedExpression(left, leftPrecedenceRequirement,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);

    if (op == 'in' || op == 'instanceof') {
      // There are cases where the space is not required but without further
      // analysis we cannot know.
      out(' ', isWhitespace: true);
      out(op);
      out(' ', isWhitespace: true);
    } else {
      if (leftSpace) spaceOut();
      out(op);
      spaceOut();
    }
    visitNestedExpression(right, rightPrecedenceRequirement,
        newInForInit: inForInit, newAtStatementBegin: false);
  }

  @override
  void visitPrefix(Prefix unary) {
    String op = unary.op;
    switch (op) {
      case 'delete':
      case 'void':
      case 'typeof':
        // There are cases where the space is not required but without further
        // analysis we cannot know.
        out(op);
        out(' ', isWhitespace: true);
        break;
      case '+':
      case '++':
        if (lastCharCode == char_codes.$PLUS) out(' ', isWhitespace: true);
        out(op);
        break;
      case '-':
      case '--':
        if (lastCharCode == char_codes.$MINUS) out(' ', isWhitespace: true);
        out(op);
        break;
      default:
        out(op);
    }
    visitNestedExpression(unary.argument, Precedence.unary,
        newInForInit: inForInit, newAtStatementBegin: false);
  }

  @override
  void visitPostfix(Postfix postfix) {
    visitNestedExpression(postfix.argument, Precedence.call,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
    out(postfix.op);
  }

  @override
  void visitVariableUse(VariableUse ref) {
    out(localNamer.getName(ref.name));
  }

  @override
  void visitThis(This node) {
    out('this');
  }

  @override
  void visitVariableDeclaration(VariableDeclaration decl) {
    out(localNamer.getName(decl.name));
  }

  @override
  void visitParameter(Parameter param) {
    out(localNamer.getName(param.name));
  }

  bool isDigit(int charCode) {
    return char_codes.$0 <= charCode && charCode <= char_codes.$9;
  }

  bool isValidJavaScriptId(String field) {
    if (field.isEmpty) return false;
    // Ignore the leading and trailing string-delimiter.
    for (int i = 0; i < field.length; i++) {
      // TODO(floitsch): allow more characters.
      int charCode = field.codeUnitAt(i);
      if (!(char_codes.$a <= charCode && charCode <= char_codes.$z ||
          char_codes.$A <= charCode && charCode <= char_codes.$Z ||
          charCode == char_codes.$$ ||
          charCode == char_codes.$_ ||
          i > 0 && isDigit(charCode))) {
        return false;
      }
    }
    // TODO(floitsch): normally we should also check that the field is not a
    // reserved word.  We don't generate fields with reserved word names except
    // for 'super'.
    if (field == 'super') return false;
    if (field == 'catch') return false;
    return true;
  }

  @override
  void visitAccess(PropertyAccess access) {
    final precedence = inNewTarget ? Precedence.leftHandSide : Precedence.call;
    visitNestedExpression(access.receiver, precedence,
        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);

    Node selector = _undefer(access.selector);
    if (isDebugContext && !selector.isFinalized) {
      _dotString(
          access.selector, access.receiver, selector.nonfinalizedDebugText(),
          assumeValid: true);
      return;
    }
    if (selector is LiteralString) {
      _dotString(access.selector, access.receiver, selector.value);
      return;
    }
    if (selector is StringConcatenation) {
      _dotString(access.selector, access.receiver,
          _StringContentsCollector(isDebugContext).collect(selector));
      return;
    }
    if (selector is Name) {
      _dotString(access.selector, access.receiver, selector.name);
      return;
    }

    out('[');
    inNewTarget = false;
    visitNestedExpression(access.selector, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(']');
  }

  void _dotString(Node selector, Expression receiver, String selectorValue,
      {bool assumeValid = false}) {
    if (assumeValid || isValidJavaScriptId(selectorValue)) {
      if (_undefer(receiver) is LiteralNumber &&
          lastCharCode != char_codes.$CLOSE_PAREN) {
        out(' ', isWhitespace: true);
      }
      out('.');
      startNode(selector);
      out(selectorValue);
      endNode(selector);
    } else {
      out('[');
      _handleString(selectorValue);
      out(']');
    }
  }

  @override
  void visitNamedFunction(NamedFunction namedFunction) {
    VarCollector vars = VarCollector();
    vars.visitNamedFunction(namedFunction);
    startNode(namedFunction.function);
    int closingPosition = currentNode!.closingPosition =
        functionOut(namedFunction.function, namedFunction.name, vars);
    endNode(namedFunction.function);
    // Use closing position of `namedFunction.function` as the closing position
    // of the named function itself.
    currentNode!.closingPosition = closingPosition;
  }

  @override
  void visitFun(Fun fun) {
    VarCollector vars = VarCollector();
    vars.visitFun(fun);
    currentNode!.closingPosition = functionOut(fun, null, vars);
  }

  @override
  void visitArrowFunction(ArrowFunction fun) {
    VarCollector vars = VarCollector();
    vars.visitArrowFunction(fun);
    currentNode!.closingPosition = arrowFunctionOut(fun, vars);
  }

  static bool _isIdentifierParameter(Node node) => node is VariableReference;

  int arrowFunctionOut(ArrowFunction fun, VarCollector vars) {
    // TODO: support static, get/set, async, and generators.
    localNamer.enterScope(vars);
    final List<Parameter> params = fun.params;
    if (params.length == 1 && _isIdentifierParameter(params.first)) {
      visitNestedExpression(params.single, Precedence.assignment,
          newInForInit: false, newAtStatementBegin: false);
    } else {
      out('(');
      visitCommaSeparated(fun.params, Precedence.primary,
          newInForInit: false, newAtStatementBegin: false);
      out(')');
    }
    spaceOut();
    out('=>');
    spaceOut();
    int closingPosition;
    Node body = fun.body;
    if (body is Block) {
      closingPosition =
          blockOut(body, shouldIndent: false, needsNewline: false);
    } else {
      // Object initializers require parentheses to disambiguate
      // AssignmentExpression from FunctionBody. See:
      // https://tc39.github.io/ecma262/#sec-arrow-function-definitions
      bool needsParens = body is ObjectInitializer;
      if (needsParens) out('(');
      visitNestedExpression(body as Expression, Precedence.assignment,
          newInForInit: false, newAtStatementBegin: false);
      if (needsParens) out(')');
      closingPosition = _charCount;
    }
    localNamer.leaveScope();
    return closingPosition;
  }

  @override
  void visitDeferredExpression(DeferredExpression node) {
    if (isDebugContext && !node.isFinalized) {
      out(node.nonfinalizedDebugText());
      return;
    }
    // Continue printing with the expression value.
    assert(node.precedenceLevel == node.value.precedenceLevel);
    node.value.accept(this);
  }

  @override
  void visitDeferredStatement(DeferredStatement node) {
    startNode(node);
    visit(node.statement);
    endNode(node);
  }

  void outputNumberWithRequiredWhitespace(String number) {
    int charCode = number.codeUnitAt(0);
    if (charCode == char_codes.$MINUS && lastCharCode == char_codes.$MINUS) {
      out(' ', isWhitespace: true);
    }
    out(number);
  }

  @override
  void visitDeferredNumber(DeferredNumber node) {
    outputNumberWithRequiredWhitespace('${node.value}');
  }

  @override
  void visitDeferredString(DeferredString node) {
    out(node.value);
  }

  @override
  void visitLiteralBool(LiteralBool node) {
    out(node.value ? 'true' : 'false');
  }

  @override
  void visitLiteralString(LiteralString node) {
    if (isDebugContext && !node.isFinalized) {
      _handleString(node.nonfinalizedDebugText());
      return;
    }
    _handleString(node.value);
  }

  @override
  void visitStringConcatenation(StringConcatenation node) {
    _handleString(_StringContentsCollector(isDebugContext).collect(node));
  }

  void _handleString(String value) {
    final kind = StringToSource.analyze(value, utf8: options.utf8);
    out(kind.quote);
    if (kind.simple) {
      out(value);
    } else {
      final sb = StringBuffer();
      StringToSource.writeString(sb, value, kind, utf8: options.utf8);
      out(sb.toString());
    }
    out(kind.quote);
  }

  @override
  void visitName(Name node) {
    if (isDebugContext && !node.isFinalized) {
      out(node.nonfinalizedDebugText());
      return;
    }
    out(node.name);
  }

  @override
  void visitParentheses(Parentheses node) {
    out('(');
    visitNestedExpression(node.enclosed, Precedence.expression,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
  }

  @override
  void visitLiteralNumber(LiteralNumber node) {
    outputNumberWithRequiredWhitespace(node.value);
  }

  @override
  void visitLiteralNull(LiteralNull node) {
    out('null');
  }

  @override
  void visitArrayInitializer(ArrayInitializer node) {
    out('[');
    List<Expression> elements = node.elements;
    for (int i = 0; i < elements.length; i++) {
      Expression element = elements[i];
      if (element is ArrayHole) {
        // Note that array holes must have a trailing "," even if they are
        // in last position. Otherwise `[,]` (having length 1) would become
        // equal to `[]` (the empty array)
        // and [1,,] (array with 1 and a hole) would become [1,] = [1].
        startNode(element);
        out(',');
        endNode(element);
        continue;
      }
      if (i != 0) spaceOut();
      visitNestedExpression(element, Precedence.assignment,
          newInForInit: false, newAtStatementBegin: false);
      // We can skip the trailing "," for the last element (since it's not
      // an array hole).
      if (i != elements.length - 1) out(',');
    }
    out(']');
  }

  @override
  void visitArrayHole(ArrayHole node) {
    context.error('Unreachable');
  }

  @override
  void visitObjectInitializer(ObjectInitializer node) {
    // Print all the properties on one line until we see a function-valued
    // property.  Ideally, we would use a proper pretty-printer to make the
    // decision based on layout.
    bool exitOneLinerMode(Expression value) {
      return value is Fun ||
          value is ArrayInitializer && value.elements.any((e) => e is Fun);
    }

    bool isOneLiner = node.isOneLiner || shouldCompressOutput;
    List<Property> properties = node.properties;
    out('{');
    indentMore();
    for (int i = 0; i < properties.length; i++) {
      Expression value = properties[i].value;
      if (isOneLiner && exitOneLinerMode(value)) isOneLiner = false;
      if (i != 0) {
        out(',');
        if (isOneLiner) spaceOut();
      }
      if (!isOneLiner) {
        forceLine();
        indent();
      }
      visit(properties[i]);
    }
    indentLess();
    if (!isOneLiner && properties.isNotEmpty) {
      lineOut();
      indent();
    }
    out('}');
  }

  @override
  void visitProperty(Property node) {
    propertyNameOut(node);
    out(':');
    spaceOut();
    visitNestedExpression(node.value, Precedence.assignment,
        newInForInit: false, newAtStatementBegin: false);
  }

  @override
  void visitMethodDefinition(MethodDefinition node) {
    propertyNameOut(node);
    VarCollector vars = VarCollector();
    vars.visitMethodDefinition(node);
    startNode(node.function);
    currentNode!.closingPosition = methodOut(node, vars);
    endNode(node.function);
  }

  int methodOut(MethodDefinition node, VarCollector vars) {
    // TODO: support static, get/set, async, and generators.
    Fun fun = node.function;
    localNamer.enterScope(vars);
    out('(');
    visitCommaSeparated(fun.params, Precedence.primary,
        newInForInit: false, newAtStatementBegin: false);
    out(')');
    spaceOut();
    int closingPosition =
        blockOut(fun.body, shouldIndent: false, needsNewline: false);
    localNamer.leaveScope();
    return closingPosition;
  }

  void propertyNameOut(Property node) {
    startNode(node.name);
    Node name = _undefer(node.name);
    if (name is LiteralString) {
      _outPropertyName(name.value);
    } else if (name is Name) {
      _outPropertyName(name.name);
    } else if (name is LiteralNumber) {
      out(name.value);
    } else {
      // Handle general expressions, .e.g. `{[x]: 1}`.
      // String concatenation could be better.
      out('[');
      visitNestedExpression(node.name, Precedence.expression,
          newInForInit: false, newAtStatementBegin: false);
      out(']');
    }
    endNode(node.name);
  }

  void _outPropertyName(String name) {
    if (isValidJavaScriptId(name)) {
      out(name);
    } else {
      _handleString(name);
    }
  }

  @override
  void visitRegExpLiteral(RegExpLiteral node) {
    out(node.pattern);
  }

  @override
  void visitLiteralExpression(LiteralExpression node) {
    out(node.template);
  }

  @override
  void visitLiteralStatement(LiteralStatement node) {
    outLn(node.code);
  }

  void visitInterpolatedNode(InterpolatedNode node) {
    out('#${node.nameOrPosition}');
  }

  @override
  void visitInterpolatedExpression(InterpolatedExpression node) =>
      visitInterpolatedNode(node);

  @override
  void visitInterpolatedLiteral(InterpolatedLiteral node) =>
      visitInterpolatedNode(node);

  @override
  void visitInterpolatedParameter(InterpolatedParameter node) =>
      visitInterpolatedNode(node);

  @override
  void visitInterpolatedSelector(InterpolatedSelector node) =>
      visitInterpolatedNode(node);

  @override
  void visitInterpolatedStatement(InterpolatedStatement node) {
    outLn('#${node.nameOrPosition}');
  }

  @override
  void visitInterpolatedDeclaration(InterpolatedDeclaration node) {
    visitInterpolatedNode(node);
  }

  @override
  void visitComment(Comment node) {
    if (shouldCompressOutput) return;
    String comment = node.comment.trim();
    if (comment.isEmpty) return;
    for (var line in comment.split('\n')) {
      if (comment.startsWith('//')) {
        outIndentLn(line.trim());
      } else {
        outIndentLn('// ${line.trim()}');
      }
    }
  }

  @override
  void visitAwait(Await node) {
    out('await ');
    visit(node.expression);
  }
}

class _StringContentsCollector extends BaseVisitorVoid {
  final StringBuffer _buffer = StringBuffer();
  final bool isDebugContext;

  _StringContentsCollector(this.isDebugContext);

  String collect(Node node) {
    node.accept(this);
    return _buffer.toString();
  }

  void _add(String value) {
    _buffer.write(value);
  }

  @override
  void visitNode(Node node) {
    throw StateError('Node should not be part of StringConcatenation: $node');
  }

  @override
  void visitLiteralString(LiteralString node) {
    if (isDebugContext && !node.isFinalized) {
      _add(node.nonfinalizedDebugText());
    } else {
      _add(node.value);
    }
  }

  @override
  void visitLiteralNumber(LiteralNumber node) {
    if (isDebugContext && !node.isFinalized) {
      _add(node.nonfinalizedDebugText());
    } else {
      _add(node.value);
    }
  }

  @override
  void visitName(Name node) {
    if (isDebugContext && !node.isFinalized) {
      _add(node.nonfinalizedDebugText());
    } else {
      _add(node.name);
    }
  }

  @override
  void visitStringConcatenation(StringConcatenation node) {
    node.visitChildren(this);
  }
}

class OrderedSet<T> {
  final Set<T> set;
  final List<T> list;

  OrderedSet()
      : set = <T>{},
        list = <T>[];

  void add(T x) {
    if (set.add(x)) {
      // [Set.add] returns `true` if 'x' was added.
      list.add(x);
    }
  }

  void forEach(void Function(T x) fun) {
    list.forEach(fun);
  }
}

// Collects all the var declarations in the function.  We need to do this in a
// separate pass because JS vars are lifted to the top of the function.
class VarCollector extends BaseVisitorVoid {
  bool nested;
  bool enableRenaming = true;
  final OrderedSet<String> vars;
  final OrderedSet<String> params;

  static final String disableVariableMinificationPattern = '::norenaming::';
  static final String enableVariableMinificationPattern = '::dorenaming::';

  VarCollector()
      : nested = false,
        vars = OrderedSet<String>(),
        params = OrderedSet<String>();

  void forEachVar(void Function(String) fn) => vars.forEach(fn);
  void forEachParam(void Function(String) fn) => params.forEach(fn);

  void collectVarsInFunction(FunctionExpression fun) {
    if (!nested) {
      nested = true;
      for (int i = 0; i < fun.params.length; i++) {
        params.add(fun.params[i].name);
      }
      fun.body.accept(this);
      nested = false;
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration declaration) {
    // Note that we don't bother collecting the name of the function.
    collectVarsInFunction(declaration.function);
  }

  @override
  void visitNamedFunction(NamedFunction namedFunction) {
    // Note that we don't bother collecting the name of the function.
    collectVarsInFunction(namedFunction.function);
  }

  @override
  void visitMethodDefinition(MethodDefinition method) {
    // Note that we don't bother collecting the name of the function.
    collectVarsInFunction(method.function);
  }

  @override
  void visitFun(Fun fun) {
    collectVarsInFunction(fun);
  }

  @override
  void visitArrowFunction(ArrowFunction fun) {
    collectVarsInFunction(fun);
  }

  @override
  void visitThis(This node) {}

  @override
  void visitComment(Comment node) {
    if (node.comment.contains(disableVariableMinificationPattern)) {
      enableRenaming = false;
    } else if (node.comment.contains(enableVariableMinificationPattern)) {
      enableRenaming = true;
    }
  }

  @override
  void visitVariableDeclaration(VariableDeclaration decl) {
    if (enableRenaming && decl.allowRename) vars.add(decl.name);
  }
}

/// Returns true, if the given node must be wrapped into braces when used
/// as then-statement in an [If] that has an else branch.
class DanglingElseVisitor extends BaseVisitor<bool> {
  JavaScriptPrintingContext context;

  DanglingElseVisitor(this.context);

  @override
  bool visitProgram(Program node) => false;

  @override
  bool visitNode(Node node) {
    context.error('Forgot node: $node');
    return true;
  }

  @override
  bool visitComment(Comment node) => true;

  @override
  bool visitBlock(Block node) {
    // TODO(sra): The following is no longer true. Revert to `=> false;`.

    // Singleton blocks are in many places printed as the contained statement so
    // that statement might capture the dangling else.
    if (node.statements.length != 1) return false;
    return node.statements.single.accept(this);
  }

  @override
  bool visitExpressionStatement(ExpressionStatement node) => false;
  @override
  bool visitEmptyStatement(EmptyStatement node) => false;
  @override
  bool visitDeferredStatement(DeferredStatement node) {
    return node.statement.accept(this);
  }

  @override
  bool visitIf(If node) {
    if (!node.hasElse) return true;
    return node.otherwise.accept(this);
  }

  @override
  bool visitFor(For node) => node.body.accept(this);
  @override
  bool visitForIn(ForIn node) => node.body.accept(this);
  @override
  bool visitWhile(While node) => node.body.accept(this);
  @override
  bool visitDo(Do node) => false;
  @override
  bool visitContinue(Continue node) => false;
  @override
  bool visitBreak(Break node) => false;
  @override
  bool visitReturn(Return node) => false;
  @override
  bool visitThrow(Throw node) => false;
  @override
  bool visitTry(Try node) {
    if (node.finallyPart != null) {
      return node.finallyPart!.accept(this);
    } else {
      return node.catchPart!.accept(this);
    }
  }

  @override
  bool visitCatch(Catch node) => node.body.accept(this);
  @override
  bool visitSwitch(Switch node) => false;
  @override
  bool visitCase(Case node) => false;
  @override
  bool visitDefault(Default node) => false;
  @override
  bool visitFunctionDeclaration(FunctionDeclaration node) => false;
  @override
  bool visitLabeledStatement(LabeledStatement node) => node.body.accept(this);
  @override
  bool visitLiteralStatement(LiteralStatement node) => true;

  @override
  bool visitDartYield(DartYield node) => false;

  @override
  bool visitExpression(Expression node) => false;
}

abstract class LocalNamer {
  String getName(String oldName);
  String declareVariable(String oldName);
  String declareParameter(String oldName);
  void enterScope(VarCollector vars);
  void leaveScope();
}

class IdentityNamer implements LocalNamer {
  @override
  String getName(String oldName) => oldName;
  @override
  String declareVariable(String oldName) => oldName;
  @override
  String declareParameter(String oldName) => oldName;
  @override
  void enterScope(VarCollector vars) {}
  @override
  void leaveScope() {}
}

class MinifyRenamer implements LocalNamer {
  final List<Map<String, String>> maps = [];
  final List<int> parameterNumberStack = [];
  final List<int> variableNumberStack = [];
  int parameterNumber = 0;
  int variableNumber = 0;

  MinifyRenamer();

  @override
  void enterScope(VarCollector vars) {
    maps.add({});
    variableNumberStack.add(variableNumber);
    parameterNumberStack.add(parameterNumber);
    vars.forEachVar(declareVariable);
    vars.forEachParam(declareParameter);
  }

  @override
  void leaveScope() {
    maps.removeLast();
    variableNumber = variableNumberStack.removeLast();
    parameterNumber = parameterNumberStack.removeLast();
  }

  @override
  String getName(String oldName) {
    // Go from inner scope to outer looking for mapping of name.
    for (int i = maps.length - 1; i >= 0; i--) {
      var map = maps[i];
      var replacement = map[oldName];
      if (replacement != null) return replacement;
    }
    return oldName;
  }

  static const LOWER_CASE_LETTERS = 26;
  static const LETTERS = LOWER_CASE_LETTERS;
  static const DIGITS = 10;

  static int nthLetter(int n) {
    return (n < LOWER_CASE_LETTERS)
        ? char_codes.$a + n
        : char_codes.$A + n - LOWER_CASE_LETTERS;
  }

  // Parameters go from a to z and variables go from z to a.  This makes each
  // argument list and each top-of-function var declaration look similar and
  // helps gzip compress the file.  If we have more than 26 arguments and
  // variables then we meet somewhere in the middle of the alphabet.  After
  // that we give up trying to be nice to the compression algorithm and just
  // use the same namespace for arguments and variables, starting with A, and
  // moving on to a0, a1, etc.
  @override
  String declareVariable(String oldName) {
    if (avoidRenaming(oldName)) return oldName;
    String newName;
    if (variableNumber + parameterNumber < LOWER_CASE_LETTERS) {
      // Variables start from z and go backwards, for better gzipability.
      newName = getNameNumber(oldName, LOWER_CASE_LETTERS - 1 - variableNumber);
    } else {
      // After 26 variables and parameters we allocate them in the same order.
      newName = getNameNumber(oldName, variableNumber + parameterNumber);
    }
    variableNumber++;
    return newName;
  }

  @override
  String declareParameter(String oldName) {
    if (avoidRenaming(oldName)) return oldName;
    String newName;
    if (variableNumber + parameterNumber < LOWER_CASE_LETTERS) {
      newName = getNameNumber(oldName, parameterNumber);
    } else {
      newName = getNameNumber(oldName, variableNumber + parameterNumber);
    }
    parameterNumber++;
    return newName;
  }

  bool avoidRenaming(String oldName) {
    // Variables of this $form$ are used in pattern matching the message of JS
    // exceptions, so should not be renamed.
    // TODO(sra): Introduce a way for indicating in the JS text which variables
    // should not be renamed.
    return oldName.startsWith(r'$') && oldName.endsWith(r'$');
  }

  String getNameNumber(String oldName, int n) {
    if (maps.isEmpty) return oldName;

    String newName;
    if (n < LETTERS) {
      // Start naming variables a, b, c, ..., z, A, B, C, ..., Z.
      newName = String.fromCharCodes([nthLetter(n)]);
    } else {
      // Then name variables a0, a1, a2, ..., a9, b0, b1, ..., Z9, aa0, aa1, ...
      // For all functions with fewer than 500 locals this is just as compact
      // as using aa, ab, etc. but avoids clashes with keywords.
      n -= LETTERS;
      int digit = n % DIGITS;
      n ~/= DIGITS;
      int alphaChars = 1;
      int nameSpaceSize = LETTERS;
      // Find out whether we should use the 1-character namespace (size 52), the
      // 2-character namespace (size 52*52), etc.
      while (n >= nameSpaceSize) {
        n -= nameSpaceSize;
        alphaChars++;
        nameSpaceSize *= LETTERS;
      }
      var codes = <int>[];
      for (var i = 0; i < alphaChars; i++) {
        nameSpaceSize ~/= LETTERS;
        codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS));
      }
      codes.add(char_codes.$0 + digit);
      newName = String.fromCharCodes(codes);
    }
    assert(RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName));
    maps.last[oldName] = newName;
    return newName;
  }
}

/// Information pertaining the enter and exit callbacks for [node].
class EnterExitNode {
  final EnterExitNode? parent;
  final Node node;

  int? startPosition;
  int? closingPosition;

  EnterExitNode(this.parent, this.node);

  void addToNode(JavaScriptPrintingContext context, int position) {
    if (startPosition == null) {
      // [position] is the start position of [node].
      // This might be the start position of the parent as well.
      parent?.addToNode(context, position);
      startPosition = position;
      context.enterNode(node, position);
    }
  }

  EnterExitNode? exitNode(JavaScriptPrintingContext context, int position) {
    // Enter must happen before exit.
    addToNode(context, position);
    context.exitNode(node, startPosition!, position, closingPosition);
    return parent;
  }
}
