// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/console/format_node_console.h"

#include "src/developer/debug/zxdb/common/ref_ptr_to.h"
#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/format_name.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/expr/format.h"
#include "src/developer/debug/zxdb/expr/format_node.h"
#include "src/lib/fxl/memory/ref_counted.h"

namespace zxdb {

namespace {

// Provides a way to execute a single callback when a set of deferred actions is complete.
class AggregateDeferredCallback : public fxl::RefCountedThreadSafe<AggregateDeferredCallback> {
 public:
  // Returns a subordinate callback, the completion of which will contribute to the outer callback.
  fit::deferred_callback MakeSubordinate() {
    // This callback exists only to hold the bound reference to the outer callback.
    return fit::defer_callback([ref = RefPtrTo(this)]() {});
  }

 private:
  FRIEND_REF_COUNTED_THREAD_SAFE(AggregateDeferredCallback);
  FRIEND_MAKE_REF_COUNTED(AggregateDeferredCallback);

  explicit AggregateDeferredCallback(fit::deferred_callback cb) : outer_(std::move(cb)) {}

  fit::deferred_callback outer_;
};

// Some state needs to be tracked recursively as we iterate through the tree.
struct RecursiveState {
  explicit RecursiveState(const ConsoleFormatOptions& opts) : options(opts) {}

  // Returns a modified version of the state for one additional level of recursion, advancing
  // both indent and tree depth.
  RecursiveState Advance() const;

  // Advances the tree depth but not the visual nesting depth.
  RecursiveState AdvanceNoIndent() const;

  // Returns true if the combination of options means the type should be shown.
  bool TypeForcedOn() const {
    return !inhibit_one_type && options.verbosity == ConsoleFormatOptions::Verbosity::kAllTypes;
  }

  // Returns true if the current item should be formatted in expanded tree mode or in one line.
  bool ShouldExpand() const {
    return options.wrapping == ConsoleFormatOptions::Wrapping::kExpanded ||
           (options.wrapping == ConsoleFormatOptions::Wrapping::kSmart && smart_indent_is_expanded);
  }

  int GetIndentAmount() const {
    if (!ShouldExpand())
      return 0;
    return options.indent_amount * indent_depth;
  }

  // Returns the string to indent a node at the given level.
  std::string GetIndentString() const { return std::string(GetIndentAmount(), ' '); }

  // Returns true if items at this level should be elided because the printing depth is too deep.
  bool DepthTooDeep() const { return tree_depth >= options.max_depth; }

  const ConsoleFormatOptions options;

  // Forces various information off for exactly one level of printing. Use for array printing, for
  // example, to avoid duplicating the type information for every entry.
  bool inhibit_one_name = false;
  bool inhibit_one_type = false;

  // How deep in the node tree we are, the top level is 0.
  int tree_depth = 0;

  // How many levels of visual indent we are, the top level is 0. This is often the same as the
  // tree depth but some things like pointer resolution are different levels of the tree but
  // are presented as the same visual level.
  int indent_depth = 0;

  // Number of pointers we've expanded so far in this level of recursion.
  int pointer_depth = 0;

  // Controls what mode of smart indenting (single-line or expanded) the current node should be
  // formatted in.
  bool smart_indent_is_expanded = true;
};

RecursiveState RecursiveState::Advance() const {
  RecursiveState result = *this;
  result.inhibit_one_name = false;
  result.inhibit_one_type = false;

  result.tree_depth++;
  result.indent_depth++;

  return result;
}

RecursiveState RecursiveState::AdvanceNoIndent() const {
  RecursiveState result = Advance();
  result.indent_depth--;  // Undo visual indent from Advance().
  return result;
}

void RecursiveDescribeFormatNode(FormatNode* node, fxl::RefPtr<EvalContext> context,
                                 const RecursiveState& state, fit::deferred_callback cb) {
  if (state.tree_depth == state.options.max_depth)
    return;  // Reached max depth, give up.

  auto on_complete = fit::defer_callback([weak_node = node->GetWeakPtr(), context,
                                          cb = std::move(cb), state = state.Advance()]() mutable {
    // Description is complete.
    if (!weak_node || weak_node->children().empty())
      return;

    // Check for pointer expansion to avoid recursing into too many.
    if (weak_node->description_kind() == FormatNode::kPointer) {
      if (state.pointer_depth == state.options.pointer_expand_depth)
        return;  // Don't recurse into another level of pointer.
      state.pointer_depth++;
    }

    // Recurse into children.
    auto aggregator = fxl::MakeRefCounted<AggregateDeferredCallback>(std::move(cb));
    for (const auto& child : weak_node->children())
      RecursiveDescribeFormatNode(child.get(), context, state, aggregator->MakeSubordinate());
  });

  if (node->state() != FormatNode::kDescribed)
    FillFormatNodeDescription(node, state.options, context, std::move(on_complete));
}

bool IsRust(const FormatNode* node) {
  if (!node->value().type())
    return false;
  return node->value().type()->GetLanguage() == DwarfLang::kRust;
}

// Forward decls, see the implementation for comments.
OutputBuffer DoFormatNode(const FormatNode* node, const RecursiveState& state, int line_start_char);
OutputBuffer DoFormatNodeOneWay(const FormatNode* node, const RecursiveState& state,
                                int indent_amount);

// Get a possibly-elided version of the type name for a medium verbosity level.
std::string GetElidedTypeName(const RecursiveState& state, const std::string& name) {
  if (state.options.verbosity != ConsoleFormatOptions::Verbosity::kMinimal)
    return name;  // No eliding except in minimal mode.

  // Pick different thresholds depending on if we're doing multiline or not. The threshold and
  // the eliding length are different so we don't elide one or two characters.
  size_t always_allow_below = 64;
  size_t elide_to = 50;
  if (!state.ShouldExpand()) {
    always_allow_below /= 2;
    elide_to /= 2;
  }

  // Names shorter than this are always displayed in full.
  if (name.size() <= always_allow_below)
    return name;

  return name.substr(0, elide_to) + "…";
}

// Rust collections (structs) normally have the type name before the bracket like "MyStruct{...}".
// This function appends this name.
//
// For some struct types including common standard containers the names can get very long. As a
// result in "minimal" verbosity mode we never show the namespaces and also elide template
// parameters when the template is long.
void AppendRustCollectionName(const FormatNode* node, const RecursiveState& state,
                              OutputBuffer* out) {
  if (!IsRust(node) || !node->value().type())
    return;

  if (state.options.verbosity != ConsoleFormatOptions::Verbosity::kMinimal) {
    // Use the full identifier name in the more verbose modes.
    FormatIdentifierOptions opts;
    opts.show_global_qual = false;
    opts.elide_templates = false;
    opts.bold_last = false;
    out->Append(FormatIdentifier(node->value().type()->GetIdentifier(), opts));
    return;
  }

  // Special-case "Vec" with the macro that's normally used and omit the type.
  if (StringBeginsWith(node->type(), "alloc::vec::Vec<")) {
    out->Append("vec!");
    return;
  }

  // In minimal mode, extract just the last component of the identifier.
  const Identifier& ident = node->value().type()->GetIdentifier();
  if (ident.empty())
    return;
  ParsedIdentifier parsed =
      ToParsedIdentifier(Identifier(IdentifierQualification::kRelative, ident.components().back()));

  if (parsed.components()[0].has_template()) {
    // Some containers have very long template names. Since Rust structs always have the name, the
    // lengths can get a little bit nuts. Elide the template contents when too long by converting
    // all template parameters to one string and eliding.
    const auto& template_contents = parsed.components()[0].template_contents();
    std::string template_string;
    for (size_t i = 0; i < template_contents.size(); i++) {
      if (i > 0)
        template_string += ", ";
      template_string += template_contents[i];
    }

    // Replace the template parameters with our single string, elided if necessary.
    parsed.components()[0] = ParsedIdentifierComponent(parsed.components()[0].name(),
                                                       {GetElidedTypeName(state, template_string)});
  }

  FormatIdentifierOptions ident_opts;
  ident_opts.show_global_qual = false;
  ident_opts.elide_templates = false;
  ident_opts.bold_last = false;
  out->Append(FormatIdentifier(parsed, ident_opts));
}

// Writes the suffix for when there are multiple items in a collection or an array.
void AppendItemSuffix(const RecursiveState& state, bool last_item, OutputBuffer* out) {
  if (state.ShouldExpand())
    out->Append("\n");  // Expanded children always end with a newline.
  else if (!last_item)
    out->Append(", ");  // Get commas for everything but the last.
}

// Returns true if type information should be displayed before the variable name, as in
//   <TYPE> name = value
bool ShouldPrependTypeNameBeforeName(const FormatNode* node, const RecursiveState& state) {
  if (!state.TypeForcedOn())
    return false;  // Never show types unless requested.

  if (node->type().empty())
    return false;  // Don't show empty types.

  if (!IsRust(node))
    return true;  // Non-Rust code always gets the type.

  if (node->description_kind() == FormatNode::kCollection ||
      node->description_kind() == FormatNode::kArray ||
      node->description_kind() == FormatNode::kRustTuple ||
      node->description_kind() == FormatNode::kRustTupleStruct) {
    // Rust structs and tuple structs are special. They encode the type after the variable, so:
    // "foo = StructName{...}" and we don't want to prepend it before "foo". But this doesn't happen
    // for tuples.
    //
    // Rust tuples don't have the name shown ever. The individual members will have their types
    // displayed which will encode the type of the tuple.
    return false;
  }

  return true;
}

// Appends the formatted name and "=" as needed by this node.
void AppendNodeNameAndType(const FormatNode* node, const RecursiveState& state, OutputBuffer* out) {
  if (ShouldPrependTypeNameBeforeName(node, state))
    out->Append(Syntax::kComment, "(" + node->type() + ") ");

  if (!state.inhibit_one_name && !node->name().empty()) {
    // Node name. Base class names are less important so get dimmed. Especially STL base classes
    // can get very long so we also elide them unless verbose mode is turned on.
    if (node->child_kind() == FormatNode::kBaseClass) {
      out->Append(Syntax::kComment, GetElidedTypeName(state, node->name()));
    } else {
      // Normal variable-style node name.
      out->Append(Syntax::kVariable, node->name());
    }

    // Rust uses colons for most things, while C uses equals. The exception for Rust is local
    // variables which "=" to better match how the variables are declared.
    if (IsRust(node) && node->child_kind() != FormatNode::kVariable)
      out->Append(": ");
    else
      out->Append(" = ");
  }
}

// Writes the node's children. The caller sets up how it wants the children to be formatted by
// passing both the recursive state for the node, and the state it wants to use for the children.
//
// The opening and closing strings are used to wrap the contents, e.g. "{" and "}". If these are
// empty it's assumed that the first line doesn't need a newline after it in multiline mode
// (normally the opening character would be followed by a newline and an indent in multiline mode).
void AppendNodeChildren(const FormatNode* node, const RecursiveState& node_state,
                        const std::string& opening, const std::string& closing,
                        const RecursiveState& child_state, OutputBuffer* out) {
  out->Append(opening);

  if (child_state.DepthTooDeep()) {
    // Don't print the child names if those children will be elided. Otherwise this prints a
    // whole struct out with no data: "{foo=…, bar=…, baz=…}" which is wasteful of space and not
    // helpful.
    out->Append(Syntax::kComment, "…");
    out->Append(closing);
    return;
  }

  // Special-case empty ones because we never want wrapping.
  if (node->children().empty()) {
    out->Append(closing);
    return;
  }

  if (!opening.empty() && node_state.ShouldExpand())
    out->Append("\n");

  int child_indent = child_state.GetIndentAmount();
  for (size_t i = 0; i < node->children().size(); i++) {
    const FormatNode* child = node->children()[i].get();

    if (child->state() == FormatNode::kEmpty) {
      // Arrays can have "empty" nodes which use the name to indicate clipping ("...").
      if (!child->name().empty())
        out->Append(Syntax::kComment, child->name());
    } else {
      out->Append(DoFormatNode(child, child_state, child_indent));
    }

    // Separator (comma or newline).
    AppendItemSuffix(node_state, i + 1 == node->children().size(), out);
  }

  out->Append(node_state.GetIndentString() + closing);
}

OutputBuffer DoFormatArrayOrTupleNode(const FormatNode* node, const RecursiveState& state) {
  OutputBuffer out;

  RecursiveState child_state = state.Advance();
  // In multiline mode, show the names of the array indices ("[0] = ...").
  child_state.inhibit_one_name = !state.ShouldExpand();

  if (node->description_kind() == FormatNode::kArray) {
    // Arrays all have the same type so don't show the type for every child.
    child_state.inhibit_one_type = true;

    if (IsRust(node)) {
      // Rust sequences use "[...]".
      AppendRustCollectionName(node, state, &out);
      AppendNodeChildren(node, state, "[", "]", child_state, &out);
    } else {
      AppendNodeChildren(node, state, "{", "}", child_state, &out);
    }
  } else {
    // Rust tuple or tuple struct. These should not be empty.
    if (node->description_kind() == FormatNode::kRustTupleStruct) {
      // Tuple structs get the name, regular tuples have none.
      AppendRustCollectionName(node, state, &out);
    }

    // Tuples of length 1 never show the child names, even in expanded mode because it's not
    // helpful and looks weird.o
    //
    // We show the indices of tuple members in expanded mode for larger tuples even though
    // Rust wouldn't do that because highly nested data structures can get very difficult to
    // follow. Something like a closure or a generator can go on for >100 lines and have many
    // tuple members (>10). Without these indices the structure is not interpretable. This doesn't
    // come up when using println in the language very often because normally these types of
    // tuples are not printed.
    if (node->children().size() == 1)
      child_state.inhibit_one_name = true;

    AppendNodeChildren(node, state, "(", ")", child_state, &out);
  }

  return out;
}

OutputBuffer DoFormatCollectionNode(const FormatNode* node, const RecursiveState& state) {
  OutputBuffer out;

  // Rust structs are always prefixed with the struct name. This does nothing for non-Rust.
  AppendRustCollectionName(node, state, &out);

  // Special-case empty collections because we never want wrapping.
  if (node->children().empty()) {
    // Rust empty structs have no brackets.
    if (!IsRust(node))
      out.Append("{}");
    return out;
  }

  AppendNodeChildren(node, state, "{", "}", state.Advance(), &out);
  return out;
}

OutputBuffer DoFormatPointerNode(const FormatNode* node, const RecursiveState& state) {
  OutputBuffer out;

  // When type information is forced on, the type will have already been printed. Otherwise we print
  // a "(*)" to indicate the value is a pointer.
  if (!state.TypeForcedOn())
    out.Append(Syntax::kComment, "(*)");

  // Pointers will have a child node that expands to the pointed-to value. If this is in a
  // "described" state with no error, then show the data.
  //
  // Don't show errors dereferencing pointers here since for long structure listings with
  // potentially multiple bad pointers, these get very verbose. The user can print the specific
  // value and see the error if desired.
  if (node->children().empty() || node->children()[0]->state() != FormatNode::kDescribed ||
      node->children()[0]->err().has_error()) {
    // Just have the pointer address.
    out.Append(node->description());
  } else {
    // Have the pointed-to data, dim the address and show the data. Omit types because we already
    // printed the pointer type. We do not want to indent another level.
    RecursiveState child_state = state.AdvanceNoIndent();
    child_state.inhibit_one_name = true;
    child_state.inhibit_one_type = true;

    out.Append(Syntax::kComment, node->description() + " " + GetRightArrow() + " ");
    // Use the "one way" version to propagate our formatting mode. This node cant't get different
    // formatting than its child.
    out.Append(DoFormatNodeOneWay(node->children()[0].get(), child_state, 0));
  }
  return out;
}

OutputBuffer DoFormatReferenceNode(const FormatNode* node, const RecursiveState& state) {
  // References will have a child node that expands to the referenced value. If this is in a
  // "described" state, then we have the data and should show it. Otherwise omit this.
  if (node->children().empty() || node->children()[0]->state() != FormatNode::kDescribed) {
    // The caller should have expanded the references if it wants them shown. If not, display
    // a placeholder with the address. Show the whole thing dimmed to help indicate this isn't the
    // actual value.
    return OutputBuffer(Syntax::kComment, "(&)" + node->description());
  }

  // Have the pointed-to data, just show the value. We do not want to indent another level.
  RecursiveState child_state = state.AdvanceNoIndent();
  child_state.inhibit_one_name = true;
  child_state.inhibit_one_type = true;

  // Use the "one way" version to propagate our formatting mode. This node cant't get different
  // formatting than its child.
  return DoFormatNodeOneWay(node->children()[0].get(), child_state, 0);
}

// A Rust enum is currently like a reference in that is has a child that's the resolved type.
// A resolved enum type will be a TupleStruct (unnamed members) or a Struct (named members). Enums
// with no members are encoded as empty structs which the struct printing code will handle.
OutputBuffer DoFormatRustEnum(const FormatNode* node, const RecursiveState& state) {
  if (node->children().empty()) {
    // The caller should have expanded the enum if it wants it to be shown. If not, display the
    // description which will generally be the short name of the enum.
    return OutputBuffer(Syntax::kComment, node->description());
  }

  // Have the pointed-to data, just show the value. We do not want to indent another level. The
  // type is also hidden because it will be a generated type. If requested, the type of the overall
  // enum will have already been printed.
  RecursiveState child_state = state.AdvanceNoIndent();
  child_state.inhibit_one_name = true;
  child_state.inhibit_one_type = true;

  // Use the "one way" version to propagate our formatting mode. This node can't get different
  // formatting than its child.
  return DoFormatNodeOneWay(node->children()[0].get(), child_state, 0);
}

// A generic node with one child for things like std::optional or std::atomic.
OutputBuffer DoFormatWrapper(const FormatNode* node, const RecursiveState& state) {
  if (node->children().empty())
    return OutputBuffer(node->description() + node->wrapper_prefix() + node->wrapper_suffix());

  RecursiveState child_state = state.AdvanceNoIndent();

  OutputBuffer out;
  out.Append(node->description());
  out.Append(node->wrapper_prefix());
  out.Append(DoFormatNodeOneWay(node->children()[0].get(), child_state, 0));
  out.Append(node->wrapper_suffix());
  return out;
}

// Appends the description for a normal node (number or whatever).
OutputBuffer DoFormatStandardNode(const FormatNode* node, const RecursiveState& state) {
  return OutputBuffer(node->description());
}

// Groups have no heading, they're always just a list of children.
OutputBuffer DoFormatGroupNode(const FormatNode* node, const RecursiveState& state) {
  OutputBuffer out;
  AppendNodeChildren(node, state, std::string(), std::string(), state, &out);
  return out;
}

// Inner implementation for DoFormatNode() (see that for more). This does the actual formatting one
// time according to the current formatting options and state.
//
// Some callers may want to call this directly rather than DoFormatNode() if they want to bypass the
// two-pass formatting. This is useful for pointers which are two nodes (when auto dereferenced) but
// appear as one and the expansion mode of the outer should be passed transparently to the nested
// node.
OutputBuffer DoFormatNodeOneWay(const FormatNode* node, const RecursiveState& state,
                                int indent_amount) {
  OutputBuffer out;

  if (indent_amount)
    out.Append(std::string(indent_amount, ' '));

  AppendNodeNameAndType(node, state, &out);
  if (state.DepthTooDeep() || node->state() != FormatNode::kDescribed) {
    // Hit max depth, give up.
    out.Append(Syntax::kComment, "…");
  } else if (node->err().has_error()) {
    // Write the error.
    out.Append(Syntax::kComment, "<" + node->err().msg() + ">");
  } else {
    // Normal formatting.
    switch (node->description_kind()) {
      case FormatNode::kNone:
      case FormatNode::kBaseType:
      case FormatNode::kFunctionPointer:
      case FormatNode::kOther:
      case FormatNode::kString:
        // All these things just print the description only.
        out.Append(DoFormatStandardNode(node, state));
        break;
      case FormatNode::kGroup:
        out.Append(DoFormatGroupNode(node, state));
        break;
      case FormatNode::kArray:
      case FormatNode::kRustTuple:
      case FormatNode::kRustTupleStruct:
        out.Append(DoFormatArrayOrTupleNode(node, state));
        break;
      case FormatNode::kCollection:
        out.Append(DoFormatCollectionNode(node, state));
        break;
      case FormatNode::kPointer:
        out.Append(DoFormatPointerNode(node, state));
        break;
      case FormatNode::kReference:
        out.Append(DoFormatReferenceNode(node, state));
        break;
      case FormatNode::kRustEnum:
        out.Append(DoFormatRustEnum(node, state));
        break;
      case FormatNode::kWrapper:
        out.Append(DoFormatWrapper(node, state));
        break;
    }
  }

  return out;
}

// Formats one node. This layer provides the smart wrapping logic where we may try to format an
// item twice, first to see if it fits on one line, and possibly again ig it doesn't.
//
// The caller of this function is in charge of computing (but not inserting) the appropriate level
// of indent and also appending trailing newlines if necessary.
//
// The caller must compute the indenting amount because whether or not there's indenting for this
// node depends the expansion level of the caller, not this node. (This item could be in single-line
// mode and still be indented if the caller is expanded.)
OutputBuffer DoFormatNode(const FormatNode* node, const RecursiveState& state, int indent_amount) {
  if (state.options.wrapping != ConsoleFormatOptions::Wrapping::kSmart)
    return DoFormatNodeOneWay(node, state, indent_amount);  // Nothing fancy to do.

  // Nodes with few children we try to fit on one line if possible in smart mode. Generally
  // structures with more than 4 children will always spill over to multiline mode, so this check is
  // more of an optimization to avoid trying and failing to format the whole thing as a single line
  // first. Even if it fits, many members on a line are not readable.
  if (state.smart_indent_is_expanded && node->children().size() <= 4) {
    // The previous node was in an expanded state. First try to format this one as non-expanded.
    // to see if it fits.
    RecursiveState one_line_state = state;
    one_line_state.smart_indent_is_expanded = false;

    OutputBuffer one_line = DoFormatNodeOneWay(node, one_line_state, indent_amount);
    if (static_cast<int>(one_line.UnicodeCharWidth()) <= state.options.smart_indent_cols)
      return one_line;  // Fits.

    // Too big, format as expanded.
    return DoFormatNodeOneWay(node, state, indent_amount);
  }

  // The previous node was already in one-line mode, stay in that mode.
  return DoFormatNodeOneWay(node, state, indent_amount);
}

}  // namespace

void DescribeFormatNodeForConsole(FormatNode* node, const ConsoleFormatOptions& options,
                                  fxl::RefPtr<EvalContext> context, fit::deferred_callback cb) {
  RecursiveDescribeFormatNode(node, context, RecursiveState(options), std::move(cb));
}

OutputBuffer FormatNodeForConsole(const FormatNode& node, const ConsoleFormatOptions& options) {
  return DoFormatNode(&node, RecursiveState(options), 0);
}

fxl::RefPtr<AsyncOutputBuffer> FormatValueForConsole(ExprValue value,
                                                     const ConsoleFormatOptions& options,
                                                     fxl::RefPtr<EvalContext> context,
                                                     const std::string& value_name) {
  auto node = std::make_unique<FormatNode>(value_name, std::move(value));
  node->set_child_kind(FormatNode::kVariable);

  FormatNode* node_ptr = node.get();

  auto out = fxl::MakeRefCounted<AsyncOutputBuffer>();
  DescribeFormatNodeForConsole(node_ptr, options, context,
                               fit::defer_callback([node = std::move(node), options, out]() {
                                 // Asynchronous expansion is complete, now format the completed
                                 // output.
                                 out->Complete(FormatNodeForConsole(*node, options));
                               }));
  return out;
}

fxl::RefPtr<AsyncOutputBuffer> FormatVariableForConsole(const Variable* var,
                                                        const ConsoleFormatOptions& options,
                                                        fxl::RefPtr<EvalContext> context) {
  auto out = fxl::MakeRefCounted<AsyncOutputBuffer>();
  context->GetVariableValue(
      RefPtrTo(var), [name = var->GetAssignedName(), context, options, out](ErrOrValue value) {
        if (value.has_error()) {
          // In the error case, construct a node with the error set so the formatting with other
          // types of errors is consistent.
          FormatNode err_node(name);
          err_node.SetDescribedError(value.err());
          out->Complete(FormatNodeForConsole(err_node, options));
        } else {
          out->Complete(FormatValueForConsole(value.take_value(), options, context, name));
        }
      });
  return out;
}

fxl::RefPtr<AsyncOutputBuffer> FormatExpressionsForConsole(
    const std::vector<std::string>& expressions, const ConsoleFormatOptions& options,
    fxl::RefPtr<EvalContext> context) {
  // Put all of the expressions in a "group" node and then evaluate and format this node. This will
  // allow single- and multi-line formatting for the values and also handles all of the asynchronous
  // state across all of the expressions automatically.
  auto out = fxl::MakeRefCounted<AsyncOutputBuffer>();
  auto list_node = std::make_unique<FormatNode>(FormatNode::GroupTag());
  FormatNode* list_node_ptr = list_node.get();

  for (const std::string& expr : expressions) {
    // Use the expression as the description.
    auto child_node = std::make_unique<FormatNode>(expr, expr);
    list_node->children().push_back(std::move(child_node));
  }

  DescribeFormatNodeForConsole(
      list_node_ptr, options, context,
      fit::defer_callback([list_node = std::move(list_node), options, out]() {
        RecursiveState state(options);
        out->Complete(FormatNodeForConsole(*list_node, options));
      }));
  return out;
}

}  // namespace zxdb
