// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.syntax;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrintable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
import java.io.IOException;
import java.util.Arrays;
import java.util.Formattable;
import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;
import java.util.MissingFormatWidthException;
import java.util.UnknownFormatConversionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/** (Pretty) Printing of Skylark values */
public class Printer {

  public static final char SKYLARK_QUOTATION_MARK = '"';

  /*
   * Suggested maximum number of list elements that should be printed via printAbbreviatedList().
   * By default, this setting is not considered and no limitation takes place.
   */
  public static final int SUGGESTED_CRITICAL_LIST_ELEMENTS_COUNT = 4;

  /*
   * Suggested limit for printAbbreviatedList() to shorten the values of list elements when
   * their combined string length reaches this value.
   * By default, this setting is not considered and no limitation takes place.
   */
  public static final int SUGGESTED_CRITICAL_LIST_ELEMENTS_STRING_LENGTH = 32;

  /**
   * Creates an instance of {@link BasePrinter} that wraps an existing buffer.
   *
   * @param buffer an {@link Appendable}
   * @return new {@link BasePrinter}
   */
  static BasePrinter getPrinter(Appendable buffer) {
    return new BasePrinter(buffer);
  }

  /**
   * Creates an instance of {@link BasePrinter} with an empty buffer.
   *
   * @return new {@link BasePrinter}
   */
  public static BasePrinter getPrinter() {
    return new BasePrinter(new StringBuilder());
  }

  /**
   * Creates an instance of {@link PrettyPrinter} with an empty buffer.
   *
   * @return new {@link PrettyPrinter}
   */
  public static PrettyPrinter getPrettyPrinter() {
    return new PrettyPrinter(new StringBuilder());
  }

  /**
   * Creates an instance of {@link WorkspacePrettyPrinter} with an empty buffer.
   *
   * @return new {@link WorkspacePrettyPrinter}
   */
  public static WorkspacePrettyPrinter getWorkspacePrettyPrinter() {
    return new WorkspacePrettyPrinter(new StringBuilder());
  }

  /**
   * Creates an instance of {@link BasePrinter} with an empty buffer and whose format strings allow
   * only %s and %%.
   */
  public static BasePrinter getSimplifiedPrinter() {
    return new BasePrinter(new StringBuilder(), /*simplifiedFormatStrings=*/ true);
  }

  private Printer() {}

  // These static methods proxy to the similar methods of BasePrinter

  /**
   * Format an object with Skylark's {@code debugPrint}.
   */
  public static String debugPrint(Object x) {
    return getPrinter().debugPrint(x).toString();
  }

  /**
   * Format an object with Skylark's {@code str}.
   */
  public static String str(Object x) {
    return getPrinter().str(x).toString();
  }

  /**
   * Format an object with Skylark's {@code repr}.
   */
  public static String repr(Object x) {
    return getPrinter().repr(x).toString();
  }

  /**
   * Print a list of object representations.
   *
   * <p>The length of the output will be limited when both {@code maxItemsToPrint} and
   * {@code criticalItemsStringLength} have values greater than zero.
   *
   * @param list the list of objects to repr (each as with repr)
   * @param before a string to print before the list
   * @param separator a separator to print between each object
   * @param after a string to print after the list
   * @param singletonTerminator null or a string to print after the list if it is a singleton The
   *     singleton case is notably relied upon in python syntax to distinguish a tuple of size one
   *     such as ("foo",) from a merely parenthesized object such as ("foo").
   * @param maxItemsToPrint the maximum number of elements to be printed.
   * @param criticalItemsStringLength a soft limit for the total string length of all arguments.
   *     'Soft' means that this limit may be exceeded because of formatting.
   * @return string representation.
   */
  public static String printAbbreviatedList(
      Iterable<?> list,
      String before,
      String separator,
      String after,
      @Nullable String singletonTerminator,
      int maxItemsToPrint,
      int criticalItemsStringLength) {
    return new LengthLimitedPrinter()
        .printAbbreviatedList(
            list,
            before,
            separator,
            after,
            singletonTerminator,
            maxItemsToPrint,
            criticalItemsStringLength)
        .toString();
  }

  /**
   * Print a list of object representations.
   *
   * @param list the list of objects to repr (each as with repr)
   * @param before a string to print before the list
   * @param separator a separator to print between each object
   * @param after a string to print after the list
   * @param singletonTerminator null or a string to print after the list if it is a singleton The
   *     singleton case is notably relied upon in python syntax to distinguish a tuple of size one
   *     such as ("foo",) from a merely parenthesized object such as ("foo").
   * @return string representation.
   */
    public static String printAbbreviatedList(
      Iterable<?> list,
      String before,
      String separator,
      String after,
      @Nullable String singletonTerminator) {
    return printAbbreviatedList(list, before, separator, after, singletonTerminator,
        SUGGESTED_CRITICAL_LIST_ELEMENTS_COUNT, SUGGESTED_CRITICAL_LIST_ELEMENTS_STRING_LENGTH);
  }

  /**
   * Print a list of object representations.
   *
   * <p>The length of the output will be limited when both {@code maxItemsToPrint} and
   * {@code criticalItemsStringLength} have values greater than zero.
   *
   * @param list the list of objects to repr (each as with repr)
   * @param isTuple if true the list will be formatted with parentheses and with a trailing comma
   *     in case of one-element tuples.
   * @param maxItemsToPrint the maximum number of elements to be printed.
   * @param criticalItemsStringLength a soft limit for the total string length of all arguments.
   *     'Soft' means that this limit may be exceeded because of formatting.
   * @return string representation.
   */
  public static String printAbbreviatedList(
      Iterable<?> list,
      boolean isTuple,
      int maxItemsToPrint,
      int criticalItemsStringLength) {
    return new LengthLimitedPrinter()
        .printAbbreviatedList(list, isTuple, maxItemsToPrint, criticalItemsStringLength)
        .toString();
  }

  /**
   * Perform Python-style string formatting, as per pattern % tuple Limitations: only %d %s %r %%
   * are supported.
   *
   * @param pattern a format string.
   * @param arguments an array containing positional arguments.
   * @return the formatted string.
   */
  public static String format(String pattern, Object... arguments) {
    return getPrinter().format(pattern, arguments).toString();
  }

  /**
   * Perform Python-style string formatting, as per pattern % tuple Limitations: only %d %s %r %%
   * are supported.
   *
   * @param pattern a format string.
   * @param arguments a tuple containing positional arguments.
   * @return the formatted string.
   */
  public static String formatWithList(String pattern, List<?> arguments) {
    return getPrinter().formatWithList(pattern, arguments).toString();
  }

  /**
   * Perform Python-style string formatting, lazily.
   *
   * @param pattern a format string.
   * @param arguments positional arguments.
   * @return the formatted string.
   */
  public static Formattable formattable(final String pattern, Object... arguments) {
    final List<Object> args = Arrays.asList(arguments);
    return new Formattable() {
      @Override
      public String toString() {
        return formatWithList(pattern, args);
      }

      @Override
      public void formatTo(Formatter formatter, int flags, int width, int precision) {
        Printer.getPrinter(formatter.out()).formatWithList(pattern, args);
      }
    };
  }

  /**
   * Append a char to a buffer. In case of {@link IOException} throw an {@link AssertionError}
   * instead
   *
   * @return buffer
   */
  public static Appendable append(Appendable buffer, char c) {
    try {
      return buffer.append(c);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /**
   * Append a char sequence to a buffer. In case of {@link IOException} throw an
   * {@link AssertionError} instead
   *
   * @return buffer
   */
  public static Appendable append(Appendable buffer, CharSequence s) {
    try {
      return buffer.append(s);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /**
   * Append a char sequence range to a buffer. In case of {@link IOException} throw an
   * {@link AssertionError} instead
   * @return buffer
   */
  private static Appendable append(Appendable buffer, CharSequence s, int start, int end) {
    try {
      return buffer.append(s, start, end);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /** Actual class that implements Printer API */
  public static class BasePrinter implements SkylarkPrinter {
    // Methods of this class should not recurse through static methods of Printer

    protected final Appendable buffer;

    /**
     * If true, the only percent sequences allowed in format strings are %s substitutions and %%
     * escapes.
     */
    protected final boolean simplifiedFormatStrings;

    /**
     * Creates a printer.
     *
     * @param buffer the {@link Appendable} that will be written to
     * @param simplifiedFormatStrings if true, format strings will allow only %s and %%
     */
    protected BasePrinter(Appendable buffer, boolean simplifiedFormatStrings) {
      this.buffer = buffer;
      this.simplifiedFormatStrings = simplifiedFormatStrings;
    }

    /**
     * Creates a printer that writes to the given buffer and that does not use simplified format
     * strings.
     */
    protected BasePrinter(Appendable buffer) {
      this(buffer, /*simplifiedFormatStrings=*/ false);
    }

    /**
     * Creates a printer that uses a fresh buffer and that does not use simplified format strings.
     */
    protected BasePrinter() {
      this(new StringBuilder());
    }

    @Override
    public String toString() {
      return buffer.toString();
    }

    /**
     * Print an informal debug-only representation of object x.
     *
     * @param o the object
     * @return the buffer, in fluent style
     */
    public BasePrinter debugPrint(Object o) {
      if (o instanceof SkylarkValue) {
        ((SkylarkValue) o).debugPrint(this);
        return this;
      }

      return this.str(o);
    }

    /**
     * Print an informal representation of object x. Currently only differs from repr in the
     * behavior for strings and labels at top-level, that are returned as is rather than quoted.
     *
     * @param o the object
     * @return the buffer, in fluent style
     */
    public BasePrinter str(Object o) {
      if (o instanceof SkylarkValue) {
        ((SkylarkValue) o).str(this);
        return this;
      }

      if (o instanceof String) {
        return this.append((String) o);
      }
      return this.repr(o);
    }

    /**
     * Print an official representation of object x. For regular data structures, the value should
     * be parsable back into an equal data structure.
     *
     * @param o the string a representation of which to repr.
     * @return BasePrinter.
     */
    @Override
    public BasePrinter repr(Object o) {
      if (o == null) {
        // Java null is not a valid Skylark value, but sometimes printers are used on non-Skylark
        // values such as Locations or ASTs.
        this.append("null");

      } else if (o instanceof SkylarkPrintable) {
        ((SkylarkPrintable) o).repr(this);

      } else if (o instanceof String) {
        writeString((String) o);

      } else if (o instanceof Integer || o instanceof Double) {
        this.append(o.toString());

      } else if (Boolean.TRUE.equals(o)) {
        this.append("True");

      } else if (Boolean.FALSE.equals(o)) {
        this.append("False");

      } else if (o instanceof Map<?, ?>) {
        Map<?, ?> dict = (Map<?, ?>) o;
        this.printList(dict.entrySet(), "{", ", ", "}", null);

      } else if (o instanceof List<?>) {
        List<?> seq = (List<?>) o;
        this.printList(seq, false);

      } else if (o instanceof Map.Entry<?, ?>) {
        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
        this.repr(entry.getKey());
        this.append(": ");
        this.repr(entry.getValue());
      } else if (o instanceof Class<?>) {
        this.append(EvalUtils.getDataTypeNameFromClass((Class<?>) o));

      } else if (o instanceof ASTNode || o instanceof Location) {
        // AST node objects and locations are printed in tracebacks and error messages,
        // it's safe to print their toString representations
        this.append(o.toString());

      } else {
        // Other types of objects shouldn't be leaked to Skylark, but if happens, their
        // .toString method shouldn't be used because their return values are likely to contain
        // memory addresses or other nondeterministic information.
        this.append("<unknown object " + o.getClass().getName() + ">");
      }

      return this;
    }

    /**
     * Write a properly escaped Skylark representation of a string to a buffer.
     *
     * @param s the string a representation of which to repr.
     * @return this printer.
     */
    protected BasePrinter writeString(String s) {
      this.append(SKYLARK_QUOTATION_MARK);
      int len = s.length();
      for (int i = 0; i < len; i++) {
        char c = s.charAt(i);
        escapeCharacter(c);
      }
      return this.append(SKYLARK_QUOTATION_MARK);
    }

    private BasePrinter backslashChar(char c) {
      return this.append('\\').append(c);
    }

    private BasePrinter escapeCharacter(char c) {
      if (c == SKYLARK_QUOTATION_MARK) {
        return backslashChar(c);
      }
      switch (c) {
        case '\\':
          return backslashChar('\\');
        case '\r':
          return backslashChar('r');
        case '\n':
          return backslashChar('n');
        case '\t':
          return backslashChar('t');
        default:
          if (c < 32) {
            //TODO(bazel-team): support \x escapes
            return this.append(String.format("\\x%02x", (int) c));
          }
          return this.append(c); // no need to support UTF-8
      } // endswitch
    }

    /**
     * Print a list of object representations
     *
     * @param list the list of objects to repr (each as with repr)
     * @param before a string to print before the list items, e.g. an opening bracket
     * @param separator a separator to print between items
     * @param after a string to print after the list items, e.g. a closing bracket
     * @param singletonTerminator null or a string to print after the list if it is a singleton The
     *     singleton case is notably relied upon in python syntax to distinguish a tuple of size one
     *     such as ("foo",) from a merely parenthesized object such as ("foo").
     * @return this printer.
     */
    @Override
    public BasePrinter printList(
        Iterable<?> list,
        String before,
        String separator,
        String after,
        @Nullable String singletonTerminator) {

      this.append(before);
      int len = appendListElements(list, separator);
      if (singletonTerminator != null && len == 1) {
        this.append(singletonTerminator);
      }
      return this.append(after);
    }

    /**
     * Appends the given elements to the specified {@link Appendable} and returns the number of
     * elements.
     */
    private int appendListElements(Iterable<?> list, String separator) {
      boolean printSeparator = false; // don't print the separator before the first element
      int len = 0;
      for (Object o : list) {
        if (printSeparator) {
          this.append(separator);
        }
        this.repr(o);
        printSeparator = true;
        len++;
      }
      return len;
    }

    /**
     * Print a Skylark list or tuple of object representations
     *
     * @param list the contents of the list or tuple
     * @param isTuple if true the list will be formatted with parentheses and with a trailing comma
     *     in case of one-element tuples. 'Soft' means that this limit may be exceeded because of
     *     formatting.
     * @return this printer.
     */
    @Override
    public BasePrinter printList(Iterable<?> list, boolean isTuple) {
      if (isTuple) {
        return this.printList(list, "(", ", ", ")", ",");
      } else {
        return this.printList(list, "[", ", ", "]", null);
      }
    }

    /**
     * Perform Python-style string formatting, similar to the {@code pattern % tuple} syntax.
     *
     * <p>The only supported placeholder patterns are
     * <ul>
     *   <li>{@code %s} (convert as if by {@code str()})
     *   <li>{@code %r} (convert as if by {@code repr()})
     *   <li>{@code %d} (convert an integer to its decimal representation)
     * </ul>
     * To encode a literal percent character, escape it as {@code %%}. It is an error to have a
     * non-escaped {@code %} at the end of the string or followed by any character not listed above.
     *
     * <p>If this printer has {@code simplifiedFormatStrings} set, only {@code %s} and {@code %%}
     * are permitted.
     *
     * @param pattern a format string that may contain placeholders
     * @param arguments an array containing arguments to substitute into the placeholders in order
     * @return the formatted string
     * @throws IllegalFormatException if {@code pattern} is not a valid format string, or if
     *     {@code arguments} mismatches the number or type of placeholders in {@code pattern}
     */
    @Override
    public BasePrinter format(String pattern, Object... arguments) {
      return this.formatWithList(pattern, Arrays.asList(arguments));
    }

    /**
     * Perform Python-style string formatting, similar to the {@code pattern % tuple} syntax.
     *
     * <p>Same as {@link #format(String, Object...)}, but with a list instead of variadic args.
     */
    @Override
    public BasePrinter formatWithList(String pattern, List<?> arguments) {
      // TODO(bazel-team): support formatting arguments, and more complex Python patterns.
      // N.B. MissingFormatWidthException is the only kind of IllegalFormatException
      // whose constructor can take and display arbitrary error message, hence its use below.

      int length = pattern.length();
      int argLength = arguments.size();
      int i = 0; // index of next character in pattern
      int a = 0; // index of next argument in arguments

      while (i < length) {
        int p = pattern.indexOf('%', i);
        if (p == -1) {
          Printer.append(buffer, pattern, i, length);
          break;
        }
        if (p > i) {
          Printer.append(buffer, pattern, i, p);
        }
        if (p == length - 1) {
          throw new MissingFormatWidthException(
              "incomplete format pattern ends with %: " + this.repr(pattern));
        }
        char directive = pattern.charAt(p + 1);
        i = p + 2;
        switch (directive) {
          case '%':
            this.append('%');
            continue;
          case 'd':
          case 'r':
          case 's':
            if (simplifiedFormatStrings && (directive != 's')) {
              throw new UnknownFormatConversionException(
                  "cannot use %" + directive + " substitution placeholder when "
                      + "simplifiedFormatStrings is set");
            }
            if (a >= argLength) {
              throw new MissingFormatWidthException(
                  "not enough arguments for format pattern "
                      + Printer.repr(pattern)
                      + ": "
                      + Printer.repr(Tuple.copyOf(arguments)));
            }
            Object argument = arguments.get(a++);
            switch (directive) {
              case 'd':
                if (argument instanceof Integer) {
                  this.append(argument.toString());
                  continue;
                } else {
                  throw new MissingFormatWidthException(
                      "invalid argument " + Printer.repr(argument) + " for format pattern %d");
                }
              case 'r':
                this.repr(argument);
                continue;
              case 's':
                this.str(argument);
                continue;
            }
            // fall through
          default:
            throw new MissingFormatWidthException(
                // The call to Printer.repr doesn't cause an infinite recursion because it's
                // only used to format a string properly
                String.format("unsupported format character \"%s\" at index %s in %s",
                    String.valueOf(directive), p + 1, Printer.repr(pattern)));
        }
      }
      if (a < argLength) {
        throw new MissingFormatWidthException(
            "not all arguments converted during string formatting");
      }
      return this;
    }

    @Override
    public BasePrinter append(char c) {
      Printer.append(buffer, c);
      return this;
    }

    @Override
    public BasePrinter append(CharSequence s) {
      Printer.append(buffer, s);
      return this;
    }

    BasePrinter append(CharSequence sequence, int start, int end) {
      return this.append(sequence.subSequence(start, end));
    }
  }

  /** A printer that breaks lines between the entries of lists, with proper indenting. */
  public static class PrettyPrinter extends BasePrinter {
    static final int BASE_INDENT = 4;
    private int indent;

    protected PrettyPrinter(Appendable buffer) {
      super(buffer);
      indent = 0;
    }

    @Override
    public BasePrinter printList(
        Iterable<?> list,
        String before,
        String untrimmedSeparator,
        String after,
        @Nullable String singletonTerminator) {

      // If the list is empty, do not split the presentation over
      // several lines.
      if (!list.iterator().hasNext()) {
        this.append(before + after);
        return this;
      }

      String separator = untrimmedSeparator.trim();

      this.append(before + "\n");
      indent += BASE_INDENT;
      boolean printSeparator = false; // don't print the separator before the first element
      int len = 0;
      for (Object o : list) {
        if (printSeparator) {
          this.append(separator + "\n");
        }
        this.append(Strings.repeat(" ", indent));
        this.repr(o);
        printSeparator = true;
        len++;
      }
      if (singletonTerminator != null && len == 1) {
        this.append(singletonTerminator);
      }
      this.append("\n");
      indent -= BASE_INDENT;
      this.append(Strings.repeat(" ", indent) + after);
      return this;
    }
  }

  /**
   * A pretty printer that represents values in a form usable in WORKSPACE files.
   *
   * <p>In WORKSPACE files, the Label constructor is not available. Fortunately, in all places where
   * a label is needed, we can pass the canonical string associated with this label.
   */
  public static class WorkspacePrettyPrinter extends PrettyPrinter {

    protected WorkspacePrettyPrinter(Appendable buffer) {
      super(buffer);
    }

    @Override
    public BasePrinter repr(Object o) {
      if (o instanceof Label) {
        this.repr(((Label) o).getCanonicalForm());
      } else {
        super.repr(o);
      }
      return this;
    }
  }

  /** A version of {@code BasePrinter} that is able to print abbreviated lists. */
  public static final class LengthLimitedPrinter extends BasePrinter {

    private static final ImmutableSet<Character> SPECIAL_CHARS =
        ImmutableSet.of(',', ' ', '"', '\'', ':', '(', ')', '[', ']', '{', '}');

    private static final Pattern ARGS_PATTERN = Pattern.compile("<\\d+ more arguments>");

    // Limits can be set several times recursively and then unset the same amount of times.
    // But in fact they should be set only the first time and unset only the last time.
    // To achieve that we need to keep track of the recursion depth.
    private int recursionDepth;
    // Current limit of symbols to print in the limited mode (`ignoreLimit = false`).
    private int limit;
    private boolean ignoreLimit = true;
    private boolean previouslyShortened;

    /**
     * Print a list of object representations.
     *
     * <p>The length of the output will be limited when both {@code maxItemsToPrint} and {@code
     * criticalItemsStringLength} have values greater than zero.
     *
     * @param list the list of objects to repr (each as with repr)
     * @param before a string to print before the list
     * @param separator a separator to print between each object
     * @param after a string to print after the list
     * @param singletonTerminator null or a string to print after the list if it is a singleton The
     *     singleton case is notably relied upon in python syntax to distinguish a tuple of size one
     *     such as ("foo",) from a merely parenthesized object such as ("foo").
     * @param maxItemsToPrint the maximum number of elements to be printed.
     * @param criticalItemsStringLength a soft limit for the total string length of all arguments.
     *     'Soft' means that this limit may be exceeded because of formatting.
     * @return the BasePrinter.
     */
    LengthLimitedPrinter printAbbreviatedList(
        Iterable<?> list,
        String before,
        String separator,
        String after,
        @Nullable String singletonTerminator,
        int maxItemsToPrint,
        int criticalItemsStringLength) {
      this.append(before);
      int len = appendListElements(list, separator, maxItemsToPrint, criticalItemsStringLength);
      if (singletonTerminator != null && len == 1) {
        this.append(singletonTerminator);
      }
      return this.append(after);
    }

    /**
     * Print a Skylark list or tuple of object representations
     *
     * @param list the contents of the list or tuple
     * @param isTuple if true the list will be formatted with parentheses and with a trailing comma
     *     in case of one-element tuples.
     * @param maxItemsToPrint the maximum number of elements to be printed.
     * @param criticalItemsStringLength a soft limit for the total string length of all arguments.
     *     'Soft' means that this limit may be exceeded because of formatting.
     * @return this printer.
     */
    public LengthLimitedPrinter printAbbreviatedList(
        Iterable<?> list, boolean isTuple, int maxItemsToPrint, int criticalItemsStringLength) {
      if (isTuple) {
        return this.printAbbreviatedList(
            list, "(", ", ", ")", ",", maxItemsToPrint, criticalItemsStringLength);
      } else {
        return this.printAbbreviatedList(
            list, "[", ", ", "]", null, maxItemsToPrint, criticalItemsStringLength);
      }
    }

    /**
     * Tries to append the given elements to the specified {@link Appendable} until specific limits
     * are reached.
     *
     * @return the number of appended elements.
     */
    private int appendListElements(
        Iterable<?> list, String separator, int maxItemsToPrint, int criticalItemsStringLength) {
      boolean printSeparator = false; // don't print the separator before the first element
      boolean skipArgs = false;
      int items = Iterables.size(list);
      int len = 0;
      // We don't want to print "1 more arguments", hence we don't skip arguments if there is only
      // one above the limit.
      int itemsToPrint = (items - maxItemsToPrint == 1) ? items : maxItemsToPrint;
      enforceLimit(criticalItemsStringLength);
      for (Object o : list) {
        // We don't want to print "1 more arguments", even if we hit the string limit.
        if (len == itemsToPrint || (hasHitLimit() && len < items - 1)) {
          skipArgs = true;
          break;
        }
        if (printSeparator) {
          this.append(separator);
        }
        this.repr(o);
        printSeparator = true;
        len++;
      }
      ignoreLimit();
      if (skipArgs) {
        this.append(separator);
        this.append(String.format("<%d more arguments>", items - len));
      }
      return len;
    }

    @Override
    public LengthLimitedPrinter append(CharSequence csq) {
      if (ignoreLimit || hasOnlySpecialChars(csq)) {
        // Don't update limit.
        Printer.append(buffer, csq);
        previouslyShortened = false;
      } else {
        int length = csq.length();
        if (length <= limit) {
          limit -= length;
          Printer.append(buffer, csq);
        } else {
          Printer.append(buffer, csq, 0, limit);
          // We don't want to append multiple ellipses.
          if (!previouslyShortened) {
            Printer.append(buffer, "...");
          }
          appendTrailingSpecialChars(csq, limit);
          previouslyShortened = true;
          limit = 0;
        }
      }
      return this;
    }

    @Override
    public LengthLimitedPrinter append(char c) {
      // Use the local `append(sequence)` method so that limits can apply
      return this.append(String.valueOf(c));
    }

    /**
     * Appends any trailing "special characters" (e.g. brackets, quotation marks) in the given
     * sequence to the output buffer, regardless of the limit.
     *
     * <p>For example, let's look at foo(['too long']). Without this method, the shortened result
     * would be foo(['too...) instead of the prettier foo(['too...']).
     *
     * <p>If the input string was already shortened and contains "<x more arguments>", this part
     * will also be appended.
     */
    // TODO(bazel-team): Given an input list
    //
    //     [1, 2, 3, [10, 20, 30, 40, 50, 60], 4, 5, 6]
    //
    // the inner list gets doubly mangled as
    //
    //     [1, 2, 3, [10, 20, 30, 40, <2 more argu...<2 more arguments>], <3 more arguments>]
    private LengthLimitedPrinter appendTrailingSpecialChars(CharSequence csq, int limit) {
      int length = csq.length();
      Matcher matcher = ARGS_PATTERN.matcher(csq);
      // We assume that everything following the "x more arguments" part has to be copied, too.
      int start = matcher.find() ? matcher.start() : length;
      // Find the left-most non-arg char that has to be copied.
      for (int i = start - 1; i > limit; --i) {
        if (isSpecialChar(csq.charAt(i))) {
          start = i;
        } else {
          break;
        }
      }
      if (start < length) {
        Printer.append(buffer, csq, start, csq.length());
      }
      return this;
    }

    /**
     * Returns whether the given sequence denotes characters that are not part of the value of an
     * argument.
     *
     * <p>Examples are brackets, braces and quotation marks.
     */
    private boolean hasOnlySpecialChars(CharSequence csq) {
      for (int i = 0; i < csq.length(); ++i) {
        if (!isSpecialChar(csq.charAt(i))) {
          return false;
        }
      }
      return true;
    }

    private boolean isSpecialChar(char c) {
      return SPECIAL_CHARS.contains(c);
    }

    boolean hasHitLimit() {
      return limit <= 0;
    }

    private void enforceLimit(int limit) {
      ignoreLimit = false;
      if (recursionDepth == 0) {
        this.limit = limit;
        ++recursionDepth;
      }
    }

    private void ignoreLimit() {
      if (recursionDepth > 0) {
        --recursionDepth;
      }
      if (recursionDepth == 0) {
        ignoreLimit = true;
      }
    }
  }
}
