// Copyright 2017-2020 The Verible Authors.
//
// 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.

#include "verilog/formatting/tree_unwrapper.h"

#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <ostream>
#include <type_traits>
#include <utility>
#include <vector>

#include "absl/base/macros.h"
#include "absl/container/inlined_vector.h"
#include "absl/strings/match.h"
#include "common/formatting/basic_format_style.h"
#include "common/formatting/format_token.h"
#include "common/formatting/token_partition_tree.h"
#include "common/formatting/tree_unwrapper.h"
#include "common/formatting/unwrapped_line.h"
#include "common/strings/range.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/constants.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/text_structure.h"
#include "common/text/token_info.h"
#include "common/text/token_stream_view.h"
#include "common/text/tree_utils.h"
#include "common/util/container_iterator_range.h"
#include "common/util/enum_flags.h"
#include "common/util/logging.h"
#include "common/util/tree_operations.h"
#include "common/util/value_saver.h"
#include "common/util/vector_tree_iterators.h"
#include "verilog/CST/declaration.h"
#include "verilog/CST/functions.h"
#include "verilog/CST/macro.h"
#include "verilog/CST/statement.h"
#include "verilog/CST/verilog_nonterminals.h"
#include "verilog/formatting/verilog_token.h"
#include "verilog/parser/verilog_parser.h"
#include "verilog/parser/verilog_token_classifications.h"
#include "verilog/parser/verilog_token_enum.h"

namespace verilog {
namespace formatter {

using ::verible::iterator_range;
using ::verible::NodeTag;
using ::verible::PartitionPolicyEnum;
using ::verible::PreFormatToken;
using ::verible::SpacingOptions;
using ::verible::SymbolTag;
using ::verible::SyntaxTreeNode;
using ::verible::TokenInfo;
using ::verible::TokenPartitionTree;
using ::verible::TokenWithContext;
using ::verilog::IsComment;

// Used to filter the TokenStreamView by discarding space-only tokens.
static bool KeepNonWhitespace(const TokenInfo& t) {
  if (t.token_enum() == verible::TK_EOF) return false;  // omit the EOF token
  return !IsWhitespace(verilog_tokentype(t.token_enum()));
}

static bool NodeIsBeginEndBlock(const SyntaxTreeNode& node) {
  return node.MatchesTagAnyOf({NodeEnum::kSeqBlock, NodeEnum::kGenerateBlock});
}

static SyntaxTreeNode& GetBlockEnd(const SyntaxTreeNode& block) {
  CHECK(NodeIsBeginEndBlock(block));
  return verible::SymbolCastToNode(*block.children().back());
}

static const verible::Symbol* GetEndLabel(const SyntaxTreeNode& end_node) {
  return GetSubtreeAsSymbol(end_node, NodeEnum::kEnd, 1);
}

static bool NodeIsConditionalConstruct(const SyntaxTreeNode& node) {
  return node.MatchesTagAnyOf({NodeEnum::kConditionalStatement,
                               NodeEnum::kConditionalGenerateConstruct});
}

static bool NodeIsConditionalOrBlock(const SyntaxTreeNode& node) {
  return NodeIsBeginEndBlock(node) || NodeIsConditionalConstruct(node);
}

// Creates a PreFormatToken given a TokenInfo and returns it
static PreFormatToken CreateFormatToken(const TokenInfo& token) {
  PreFormatToken format_token(&token);
  format_token.format_token_enum =
      GetFormatTokenType(verilog_tokentype(format_token.TokenEnum()));
  switch (format_token.format_token_enum) {
    case FormatTokenType::open_group:
      format_token.balancing = verible::GroupBalancing::Open;
      break;
    case FormatTokenType::close_group:
      format_token.balancing = verible::GroupBalancing::Close;
      break;
    default:
      format_token.balancing = verible::GroupBalancing::None;
      break;
  }
  return format_token;
}

UnwrapperData::UnwrapperData(const verible::TokenSequence& tokens) {
  // Create a TokenStreamView that removes spaces, but preserves comments.
  {
    verible::InitTokenStreamView(tokens, &tokens_view_no_whitespace);
    verible::FilterTokenStreamViewInPlace(KeepNonWhitespace,
                                          &tokens_view_no_whitespace);
  }

  // Create an array of PreFormatTokens.
  {
    preformatted_tokens.reserve(tokens_view_no_whitespace.size());
    std::transform(tokens_view_no_whitespace.begin(),
                   tokens_view_no_whitespace.end(),
                   std::back_inserter(preformatted_tokens),
                   [=](verible::TokenSequence::const_iterator iter) {
                     return CreateFormatToken(*iter);
                   });
  }
}

// Represents a state of scanning tokens between syntax tree leaves.
enum TokenScannerState {
  // Initial state: immediately after a leaf token
  kStart,

  // While encountering any string of consecutive newlines
  kHaveNewline,

  // Transition from newline to non-newline
  kNewPartition,

  // Reached next leaf token, stop.  Preserve existing newline.
  kEndWithNewline,

  // Reached next leaf token, stop.
  kEndNoNewline,
};

static const verible::EnumNameMap<TokenScannerState>&
TokenScannerStateStrings() {
  static const verible::EnumNameMap<TokenScannerState>
      kTokenScannerStateStringMap({
          {"kStart", TokenScannerState::kStart},
          {"kHaveNewline", TokenScannerState::kHaveNewline},
          {"kNewPartition", TokenScannerState::kNewPartition},
          {"kEndWithNewline", TokenScannerState::kEndWithNewline},
          {"kEndNoNewline", TokenScannerState::kEndNoNewline},
      });
  return kTokenScannerStateStringMap;
}

// Conventional stream printer (declared in header providing enum).
std::ostream& operator<<(std::ostream& stream, TokenScannerState p) {
  return TokenScannerStateStrings().Unparse(p, stream);
}

// This finite state machine class is used to determine the placement of
// non-whitespace and non-syntax-tree-node tokens such as comments in
// UnwrappedLines.  The input to this FSM is a Verilog-specific token enum.
// This class is an internal implementation detail of the TreeUnwrapper class.
// TODO(fangism): handle attributes.
class TreeUnwrapper::TokenScanner {
 public:
  TokenScanner() = default;

  // Deleted standard interfaces:
  TokenScanner(const TokenScanner&) = delete;
  TokenScanner(TokenScanner&&) = delete;
  TokenScanner& operator=(const TokenScanner&) = delete;
  TokenScanner& operator=(TokenScanner&&) = delete;

  // Re-initializes state.
  void Reset() {
    current_state_ = State::kStart;
    seen_any_nonspace_ = false;
  }

  // Calls TransitionState using current_state_ and the tranition token_Type
  void UpdateState(verilog_tokentype token_type) {
    current_state_ = TransitionState(current_state_, token_type);
    seen_any_nonspace_ |= IsComment(token_type);
  }

  // Returns true if this is a state that should start a new token partition.
  bool ShouldStartNewPartition() const {
    return current_state_ == State::kNewPartition ||
           (current_state_ == State::kEndWithNewline && seen_any_nonspace_);
  }

 protected:
  typedef TokenScannerState State;

  // The current state of the TokenScanner.
  State current_state_ = kStart;
  bool seen_any_nonspace_ = false;

  // Transitions the TokenScanner given a TokenState and a verilog_tokentype
  // transition
  static State TransitionState(const State& old_state,
                               verilog_tokentype token_type);
};

static bool IsNewlineOrEOF(verilog_tokentype token_type) {
  return token_type == verilog_tokentype::TK_NEWLINE ||
         token_type == verible::TK_EOF;
}

/*
 * TransitionState computes the next state in the state machine given
 * a current TokenScanner::State and token_type transition.
 * This state machine is only expected to handle tokens that can appear
 * between syntax tree leaves (whitespace, comments, attributes).
 *
 * Transitions are expected to take place across 3 phases of inter-leaf
 * scanning:
 *   TreeUnwrapper::LookAheadBeyondCurrentLeaf()
 *   TreeUnwrapper::LookAheadBeyondCurrentNode()
 *   TreeUnwrapper::CatchUpToCurrentLeaf()
 */
TokenScannerState TreeUnwrapper::TokenScanner::TransitionState(
    const State& old_state, verilog_tokentype token_type) {
  VLOG(4) << "state transition on: " << old_state
          << ", token: " << verilog_symbol_name(token_type);
  State new_state = old_state;
  switch (old_state) {
    case kStart: {
      if (IsNewlineOrEOF(token_type)) {
        new_state = kHaveNewline;
      } else if (IsComment(token_type)) {
        new_state = kStart;  // same state
      } else {
        new_state = kEndNoNewline;
      }
      break;
    }
    case kHaveNewline: {
      if (IsNewlineOrEOF(token_type)) {
        new_state = kHaveNewline;  // same state
      } else if (IsComment(token_type)) {
        new_state = kNewPartition;
      } else {
        new_state = kEndWithNewline;
      }
      break;
    }
    case kNewPartition: {
      if (IsNewlineOrEOF(token_type)) {
        new_state = kHaveNewline;
      } else if (IsComment(token_type)) {
        new_state = kStart;
      } else {
        new_state = kEndNoNewline;
      }
      break;
    }
    case kEndWithNewline:
    case kEndNoNewline: {
      // Terminal states.  Must Reset() next.
      break;
    }
    default:
      break;
  }
  VLOG(4) << "new state: " << new_state;
  return new_state;
}

void TreeUnwrapper::EatSpaces() {
  // TODO(fangism): consider a NextNonSpaceToken() method that combines
  // NextUnfilteredToken with EatSpaces.
  const auto before = NextUnfilteredToken();
  SkipUnfilteredTokens(
      [](const TokenInfo& token) { return token.token_enum() == TK_SPACE; });
  const auto after = NextUnfilteredToken();
  VLOG(4) << __FUNCTION__ << " ate " << std::distance(before, after)
          << " space tokens";
}

TreeUnwrapper::TreeUnwrapper(const verible::TextStructureView& view,
                             const FormatStyle& style,
                             const preformatted_tokens_type& ftokens)
    : verible::TreeUnwrapper(view, ftokens),
      style_(style),
      inter_leaf_scanner_(new TokenScanner),
      token_context_(FullText(), [](std::ostream& stream, int e) {
        stream << verilog_symbol_name(e);
      }) {
  // Verify that unfiltered token stream is properly EOF terminated,
  // so that stream scanners (inter_leaf_scanner_) know when to stop.
  const auto& tokens = view.TokenStream();
  CHECK(!tokens.empty());
  const auto& back(tokens.back());
  CHECK(back.isEOF());
  CHECK(back.text().empty());
}

TreeUnwrapper::~TreeUnwrapper() {}

static bool IsPreprocessorClause(NodeEnum e) {
  switch (e) {
    case NodeEnum::kPreprocessorIfdefClause:
    case NodeEnum::kPreprocessorIfndefClause:
    case NodeEnum::kPreprocessorElseClause:
    case NodeEnum::kPreprocessorElsifClause:
      return true;
    default:
      return false;
  }
}

// These are constructs where it is permissible to fit on one line, but in the
// event that the statement body is split, we need to ensure it is properly
// indented, even if it is a single statement.
// Keep this list in sync below where the same function name appears in comment.
static bool ShouldIndentRelativeToDirectParent(
    const verible::SyntaxTreeContext& context) {
  // TODO(fangism): flip logic to check that item/statement is *not* a direct
  // child of one of the exceptions: sequential/parallel/generate blocks.
  return context.DirectParentIsOneOf({
      //
      NodeEnum::kLoopGenerateConstruct,             //
      NodeEnum::kCaseStatement,                     //
      NodeEnum::kRandCaseStatement,                 //
      NodeEnum::kForLoopStatement,                  //
      NodeEnum::kForeverLoopStatement,              //
      NodeEnum::kRepeatLoopStatement,               //
      NodeEnum::kWhileLoopStatement,                //
      NodeEnum::kDoWhileLoopStatement,              //
      NodeEnum::kForeachLoopStatement,              //
      NodeEnum::kConditionalStatement,              //
      NodeEnum::kIfClause,                          //
      NodeEnum::kGenerateIfClause,                  //
      NodeEnum::kAssertionClause,                   //
      NodeEnum::kAssumeClause,                      //
      NodeEnum::kProceduralTimingControlStatement,  //
      NodeEnum::kCoverStatement,                    //
      NodeEnum::kAssertPropertyClause,              //
      NodeEnum::kAssumePropertyClause,              //
      NodeEnum::kExpectPropertyClause,              //
      NodeEnum::kCoverPropertyStatement,            //
      NodeEnum::kCoverSequenceStatement,            //
      NodeEnum::kWaitStatement,                     //
      NodeEnum::kInitialStatement,                  //
      NodeEnum::kAlwaysStatement,                   //
      NodeEnum::kFinalStatement,                    //
      // Do not further indent under kElseClause and kElseGenerateClause,
      // so that chained else-ifs remain flat.
  });
}

void TreeUnwrapper::UpdateInterLeafScanner(verilog_tokentype token_type) {
  VLOG(4) << __FUNCTION__ << ", token: " << verilog_symbol_name(token_type);
  inter_leaf_scanner_->UpdateState(token_type);
  if (inter_leaf_scanner_->ShouldStartNewPartition()) {
    VLOG(4) << "new partition";
    // interleaf-tokens like comments do not have corresponding syntax tree
    // nodes, so pass nullptr.
    StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, nullptr);
  }
  VLOG(4) << "end of " << __FUNCTION__;
}

void TreeUnwrapper::AdvanceLastVisitedLeaf() {
  VLOG(4) << __FUNCTION__;
  EatSpaces();
  const auto& next_token = *NextUnfilteredToken();
  const verilog_tokentype token_enum =
      verilog_tokentype(next_token.token_enum());
  UpdateInterLeafScanner(token_enum);
  AdvanceNextUnfilteredToken();
  VLOG(4) << "end of " << __FUNCTION__;
}

verible::TokenWithContext TreeUnwrapper::VerboseToken(
    const TokenInfo& token) const {
  return TokenWithContext{token, token_context_};
}

static void VerilogOriginPrinter(
    std::ostream& stream, const verible::TokenInfo::Context& token_context,
    const verible::Symbol* symbol) {
  CHECK_NOTNULL(symbol);

  if (symbol->Kind() == verible::SymbolKind::kNode) {
    stream << NodeEnum(symbol->Tag().tag);
  } else {
    stream << "#" << verilog_symbol_name(verilog_tokentype(symbol->Tag().tag));
  }

  const auto* left = verible::GetLeftmostLeaf(*symbol);
  const auto* right = verible::GetRightmostLeaf(*symbol);
  if (left && right) {
    const int start = left->get().left(token_context.base);
    const int end = right->get().right(token_context.base);
    stream << "@" << start << "-" << end;
  }
  stream << " ";
  verible::UnwrappedLine::DefaultOriginPrinter(stream, symbol);
}

verible::TokenPartitionTreePrinter TreeUnwrapper::VerilogPartitionPrinter(
    const verible::TokenPartitionTree& partition) const {
  return verible::TokenPartitionTreePrinter(
      partition, false,
      [this](std::ostream& stream, const verible::Symbol* symbol) {
        VerilogOriginPrinter(stream, this->token_context_, symbol);
      });
}

void TreeUnwrapper::CatchUpToCurrentLeaf(const TokenInfo& leaf_token) {
  VLOG(4) << __FUNCTION__ << " to " << VerboseToken(leaf_token);
  // "Catch up" NextUnfilteredToken() to the current leaf.
  // Assigns non-whitespace tokens such as comments into UnwrappedLines.
  // Recall that SyntaxTreeLeaf has its own copy of TokenInfo, so we need to
  // compare a unique property of TokenInfo instead of its address.
  while (!NextUnfilteredToken()->isEOF()) {
    EatSpaces();
    // compare const char* addresses:
    if (NextUnfilteredToken()->text().begin() != leaf_token.text().begin()) {
      VLOG(4) << "token: " << VerboseToken(*NextUnfilteredToken());
      AdvanceLastVisitedLeaf();
    } else {
      break;
    }
  }
  VLOG(4) << "end of " << __FUNCTION__;
}

// Scan forward from the current leaf token, until some implementation-defined
// stopping condition.  This collects comments up until the first newline,
// and appends them to the most recent partition.
void TreeUnwrapper::LookAheadBeyondCurrentLeaf() {
  VLOG(4) << __FUNCTION__;
  // Re-initialize internal token-scanning state machine.
  inter_leaf_scanner_->Reset();

  // Consume trailing comments after the last leaf token.
  // Ignore spaces but stop at newline.
  // Advance until hitting a newline or catching up to the current leaf node,
  // whichever comes first.
  //
  // TODO(fangism): This might not adequately handle a block of //-style
  // comments that span multiple lines.  e.g.
  //
  //   ... some token;   // start of long comment ...
  //                     // continuation of long comment
  //   next tokens...
  //
  while (!NextUnfilteredToken()->isEOF()) {
    EatSpaces();
    VLOG(4) << "lookahead token: " << VerboseToken(*NextUnfilteredToken());
    if (auto next_tok = verilog_tokentype(NextUnfilteredToken()->token_enum());
        IsComment(next_tok) || next_tok == verilog_tokentype::TK_LINE_CONT) {
      // TODO(fangism): or IsAttribute().  Basically, any token that is not
      // in the syntax tree and not a space.
      AdvanceLastVisitedLeaf();
    } else {  // including newline
      // Don't advance NextUnfilteredToken() in this case.
      VLOG(4) << "no advance";
      break;
    }
  }
  VLOG(4) << "end of " << __FUNCTION__;
}

// Scan forward up to a syntax tree leaf token, but return (possibly) the
// position of the last newline *before* that leaf token.
// This allows prefix comments and attributes to stick with their
// intended token that immediately follows.
static verible::TokenSequence::const_iterator StopAtLastNewlineBeforeTreeLeaf(
    const verible::TokenSequence::const_iterator token_begin,
    const TokenInfo::Context& context) {
  VLOG(4) << __FUNCTION__;
  auto token_iter = token_begin;
  auto last_newline = token_begin;
  bool have_last_newline = false;

  // Find next syntax tree token or EOF.
  bool break_while = false;
  while (!token_iter->isEOF() && !break_while) {
    VLOG(4) << "scan: " << TokenWithContext{*token_iter, context};
    switch (token_iter->token_enum()) {
      // TODO(b/144653479): this token-case logic is redundant with other
      // places; plumb that through to here instead of replicating it.
      case TK_NEWLINE:
        have_last_newline = true;
        last_newline = token_iter;
        ABSL_FALLTHROUGH_INTENDED;
      case TK_SPACE:
      case TK_EOL_COMMENT:
      case TK_COMMENT_BLOCK:
      case TK_ATTRIBUTE:
        ++token_iter;
        break;
      default:
        break_while = true;
        break;
    }
  }

  const auto result = have_last_newline ? last_newline : token_iter;
  VLOG(4) << "end of " << __FUNCTION__ << ", advanced "
          << std::distance(token_begin, result) << " tokens";
  return result;
}

// Scan forward for comments between leaf tokens, and append them to a partition
// with the correct amount of indentation.
void TreeUnwrapper::LookAheadBeyondCurrentNode() {
  VLOG(4) << __FUNCTION__;
  // Scan until token is reached, or the last newline before token is reached.
  const auto token_begin = NextUnfilteredToken();
  const auto token_end =
      StopAtLastNewlineBeforeTreeLeaf(token_begin, token_context_);
  VLOG(4) << "stop before: " << VerboseToken(*token_end);
  while (NextUnfilteredToken() != token_end) {
    // Almost like AdvanceLastVisitedLeaf(), except suppress the last
    // advancement.
    EatSpaces();
    const auto next_token_iter = NextUnfilteredToken();
    const auto& next_token = *next_token_iter;
    VLOG(4) << "token: " << VerboseToken(next_token);
    const verilog_tokentype token_enum =
        verilog_tokentype(next_token.token_enum());
    UpdateInterLeafScanner(token_enum);
    if (next_token_iter != token_end) {
      AdvanceNextUnfilteredToken();
    } else {
      break;
    }
  }
  VLOG(4) << "end of " << __FUNCTION__;
}

// This hook is called between the children nodes of the handled node types.
// This is what allows partitions containing only comments to be properly
// indented to the same level that non-comment sub-partitions would.
void TreeUnwrapper::InterChildNodeHook(const SyntaxTreeNode& node) {
  const auto tag = NodeEnum(node.Tag().tag);
  VLOG(4) << __FUNCTION__ << " node type: " << tag;
  switch (tag) {
    // TODO(fangism): cover all other major lists
    case NodeEnum::kFormalParameterList:
    case NodeEnum::kPortDeclarationList:
    case NodeEnum::kActualParameterByNameList:
    case NodeEnum::kPortActualList:
    case NodeEnum::kPortList:
    case NodeEnum::kModuleItemList:
    case NodeEnum::kGenerateItemList:
    case NodeEnum::kClassItems:
    case NodeEnum::kEnumNameList:
    case NodeEnum::kDescriptionList:  // top-level item comments
    case NodeEnum::kStatementList:
    case NodeEnum::kPackageItemList:
    case NodeEnum::kSpecifyItemList:
    case NodeEnum::kBlockItemStatementList:
    case NodeEnum::kFunctionItemList:
    case NodeEnum::kCaseItemList:
    case NodeEnum::kCaseInsideItemList:
    case NodeEnum::kGenerateCaseItemList:
    case NodeEnum::kConstraintExpressionList:
    case NodeEnum::kConstraintBlockItemList:
    case NodeEnum::kDistributionItemList:
    case NodeEnum::kStructUnionMemberList:
      LookAheadBeyondCurrentNode();
      break;
    case NodeEnum::kArgumentList:
    case NodeEnum::kMacroArgList:
      // Put each argument, separator, and comment in a new unwrapped line
      StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, &node);
      // Catch comments after last argument
      LookAheadBeyondCurrentNode();
      break;
    default:
      break;
  }
  VLOG(4) << "end of " << __FUNCTION__ << " node type: " << tag;
}

void TreeUnwrapper::CollectLeadingFilteredTokens() {
  VLOG(4) << __FUNCTION__;
  // inter_leaf_scanner_ is already initialized to kStart state
  LookAheadBeyondCurrentNode();
  VLOG(4) << "end of " << __FUNCTION__;
}

void TreeUnwrapper::CollectTrailingFilteredTokens() {
  VLOG(4) << __FUNCTION__;
  // This should emulate ::Visit(leaf == EOF token).

  // A newline means there are no comments to add to this UnwrappedLine
  // TODO(fangism): fold this logic into CatchUpToCurrentLeaf()
  if (IsNewlineOrEOF(verilog_tokentype(NextUnfilteredToken()->token_enum()))) {
    // Filtered tokens may include comments, which do not correspond to syntax
    // tree nodes, so pass nullptr.
    StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, nullptr);
  }

  // "Catch up" to EOF.
  // The very last unfiltered token scanned should be the EOF.
  // The byte offset of the EOF token is used as the stop-condition.
  CatchUpToCurrentLeaf(EOFToken());
  VLOG(4) << "end of " << __FUNCTION__;
}

enum class ContextHint {
  kInsideStandaloneMacroCall,
};

static const verible::EnumNameMap<ContextHint>& ContextHintStrings() {
  static const verible::EnumNameMap<ContextHint> kContextHintStringMap({
      {"kInsideStandaloneMacroCall", ContextHint::kInsideStandaloneMacroCall},
  });
  return kContextHintStringMap;
}

std::ostream& operator<<(std::ostream& stream, ContextHint p) {
  return ContextHintStrings().Unparse(p, stream);
}

std::ostream& operator<<(std::ostream& stream,
                         const std::vector<ContextHint>& f) {
  return stream << verible::SequenceFormatter(f);
}

// Visitor to determine which node enum function to call
void TreeUnwrapper::Visit(const SyntaxTreeNode& node) {
  const auto tag = static_cast<NodeEnum>(node.Tag().tag);
  VLOG(3) << __FUNCTION__ << " node: " << tag;

  const auto context_hints_size = context_hints_.size();

  // This phase is only concerned with creating token partitions (during tree
  // recursive descent) and setting correct indentation values.  It is ok to
  // have excessive partitioning during this phase.
  SetIndentationsAndCreatePartitions(node);

  // This phase is only concerned with reshaping operations on token partitions,
  // such as merging, flattening, hoisting.  Reshaping should only occur on the
  // return path of tree traversal (here).

  auto* partition = PreviousSibling(*CurrentTokenPartition());
  if (partition != nullptr) {
    ReshapeTokenPartitions(node, style_, partition);
  }

  CHECK_GE(context_hints_.size(), context_hints_size);
  // Remove hints from traversed context
  context_hints_.erase(context_hints_.begin() + context_hints_size,
                       context_hints_.end());
}

// CST-descending phase that creates partitions with correct indentation.
// TODO(mglb): This function is > 600 lines and should probably be split
//             up into multiple.
void TreeUnwrapper::SetIndentationsAndCreatePartitions(
    const SyntaxTreeNode& node) {
  const auto tag = static_cast<NodeEnum>(node.Tag().tag);
  VLOG(3) << __FUNCTION__ << " node: " << tag;
  VLOG(4) << "Context hints: " << ContextHints();
  if (!Context().empty()) {
    DVLOG(4) << "Context: "
             << absl::StrJoin(Context().begin(), Context().end(), " / ",
                              [](std::string* out, const SyntaxTreeNode* n) {
                                const auto tag =
                                    static_cast<NodeEnum>(n->Tag().tag);
                                absl::StrAppend(out, NodeEnumToString(tag));
                              });
  }

  // Tips:
  // In addition to the handling based on the node enum,
  // indentation decisions can be based on the following:
  //   * Context() -- lookup upwards
  //   * node.children() substructure -- look downwards
  //     + prefer to use more robust CST functions that have abstracted
  //       away positional and structural details.
  //   * Localize examination of the above to 1 or 2 levels (up/down)
  //     where possible.
  //
  // Do not:
  //   * try to manipulate the partition structures; reshaping is left to a
  //     different phase, ReshapeTokenPartitions().

  // Suppress additional indentation when:
  // - at the syntax tree root
  // - direct parent is `ifdef/`ifndef/`else/`elsif clause
  // - at the first level of macro argument expansion
  const bool suppress_indentation =
      Context().empty() ||
      IsPreprocessorClause(NodeEnum(Context().top().Tag().tag)) ||
      Context().DirectParentIs(NodeEnum::kMacroArgList);

  // Traversal control section.
  switch (tag) {
    case NodeEnum::kDescriptionList: {
      // top-level doesn't need to open a new partition level
      // This is because the TreeUnwrapper base class created this partition
      // already.
      // TODO(fangism): make this consistent with style of other cases
      // and call VisitIndentedSection(node, 0, kAlwaysExpand);
      VisitNewUnwrappedLine(node);
      break;
    }

    // Indent only when applying kAppendFittingSubPartitions in parents
    case NodeEnum::kArgumentList:
    case NodeEnum::kIdentifierList: {
      if (Context().DirectParentsAre(
              {NodeEnum::kParenGroup, NodeEnum::kFunctionCall}) &&
          Context().IsInside(NodeEnum::kAlwaysStatement) &&
          Context().IsInside(NodeEnum::kNetVariableAssignment)) {
        if (any_of(node.children().begin(), node.children().end(),
                   [](const verible::SymbolPtr& p) {
                     return p->Tag().tag ==
                            static_cast<int>(NodeEnum::kParamByName);
                   })) {
          // Indentation of named arguments of functions
          VisitIndentedSection(node, style_.indentation_spaces,
                               PartitionPolicyEnum::kTabularAlignment);
        } else {
          VisitIndentedSection(node, style_.indentation_spaces,
                               PartitionPolicyEnum::kFitOnLineElseExpand);
        }
      } else if (HasContextHint(ContextHint::kInsideStandaloneMacroCall) &&
                 Context().DirectParentsAre(
                     {NodeEnum::kParenGroup, NodeEnum::kSystemTFCall})) {
        VisitIndentedSection(node, style_.wrap_spaces,
                             PartitionPolicyEnum::kWrap);
      } else if (Context().DirectParentsAre(
                     {NodeEnum::kParenGroup,
                      NodeEnum::kRandomizeFunctionCall}) ||
                 (Context().DirectParentsAre(
                     {NodeEnum::kParenGroup, NodeEnum::kFunctionCall})) ||
                 (Context().DirectParentsAre(
                     {NodeEnum::kParenGroup, NodeEnum::kClassNew})) ||
                 Context().DirectParentsAre(
                     {NodeEnum::kParenGroup,
                      NodeEnum::kRandomizeMethodCallExtension}) ||
                 Context().DirectParentsAre(
                     {NodeEnum::kParenGroup, NodeEnum::kSystemTFCall}) ||
                 Context().DirectParentsAre(
                     {NodeEnum::kParenGroup, NodeEnum::kMethodCallExtension})) {
        // TODO(fangism): Using wrap_spaces because of poor support of
        //     function/system/method/random calls inside trailing assignments,
        //     if headers, ternary operators and so on
        VisitIndentedSection(node, style_.wrap_spaces,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else {
        TraverseChildren(node);
      }
      break;
    }

    // The following constructs are flushed-left, not indented:
    case NodeEnum::kPreprocessorIfdefClause:
    case NodeEnum::kPreprocessorIfndefClause:
    case NodeEnum::kPreprocessorElseClause:
    case NodeEnum::kPreprocessorElsifClause: {
      VisitNewUnindentedUnwrappedLine(node);
      break;
    }

    // The following constructs start a new UnwrappedLine indented to the
    // current level.
    case NodeEnum::kGenerateRegion:
    case NodeEnum::kCaseGenerateConstruct:
    case NodeEnum::kLoopGenerateConstruct:
    case NodeEnum::kClassConstructor:
    case NodeEnum::kPackageImportDeclaration:
    case NodeEnum::kPreprocessorInclude:
    case NodeEnum::kPreprocessorUndef:
    case NodeEnum::kTFPortDeclaration:
    case NodeEnum::kTypeDeclaration:
    case NodeEnum::kNetTypeDeclaration:
    case NodeEnum::kForwardDeclaration:
    case NodeEnum::kConstraintDeclaration:
    case NodeEnum::kConstraintExpression:
    case NodeEnum::kCovergroupDeclaration:
    case NodeEnum::kCoverageOption:
    case NodeEnum::kCoverageBin:
    case NodeEnum::kCoverCross:
    case NodeEnum::kBinsSelection:
    case NodeEnum::kDistributionItem:
    case NodeEnum::kStructUnionMember:
    case NodeEnum::kEnumName:
    case NodeEnum::kNetDeclaration:
    case NodeEnum::kModulePortDeclaration:
    case NodeEnum::kAlwaysStatement:
    case NodeEnum::kInitialStatement:
    case NodeEnum::kFinalStatement:
    case NodeEnum::kDisableStatement:
    case NodeEnum::kSpecifyItem:
    case NodeEnum::kForInitialization:
    case NodeEnum::kForCondition:
    case NodeEnum::kForStepList:
    case NodeEnum::kParamByName:
    case NodeEnum::kActualNamedPort:
    case NodeEnum::kActualPositionalPort:
    case NodeEnum::kAssertionVariableDeclaration:
    case NodeEnum::kPortItem:
    case NodeEnum::kMacroFormalArg:
    case NodeEnum::kPropertyDeclaration:
    case NodeEnum::kSequenceDeclaration:
    case NodeEnum::kPort:
    case NodeEnum::kPortDeclaration:
    case NodeEnum::kParamDeclaration:
    case NodeEnum::kClockingDeclaration:
    case NodeEnum::kClockingItem:
    case NodeEnum::kUdpPrimitive:
    case NodeEnum::kGenvarDeclaration:
    case NodeEnum::kConditionalGenerateConstruct:

    case NodeEnum::kMacroGenericItem:
    case NodeEnum::kModuleHeader:
    case NodeEnum::kBindDirective:
    case NodeEnum::kDataDeclaration:
    case NodeEnum::kGateInstantiation:
    case NodeEnum::kLoopHeader:
    case NodeEnum::kCovergroupHeader:
    case NodeEnum::kModportDeclaration:
    case NodeEnum::kInstantiationType:
    case NodeEnum::kRegisterVariable:
    case NodeEnum::kVariableDeclarationAssignment:
    case NodeEnum::kCaseItem:
    case NodeEnum::kDefaultItem:
    case NodeEnum::kCaseInsideItem:
    case NodeEnum::kCasePatternItem:
    case NodeEnum::kGenerateCaseItem:
    case NodeEnum::kGateInstance:
    case NodeEnum::kGenerateIfClause:
    case NodeEnum::kGenerateElseClause:
    case NodeEnum::kGenerateIfHeader:
    case NodeEnum::kIfClause:
    case NodeEnum::kElseClause:
    case NodeEnum::kIfHeader:
    case NodeEnum::kAssertionClause:
    case NodeEnum::kAssumeClause:
    case NodeEnum::kAssertPropertyClause:
    case NodeEnum::kAssumePropertyClause:
    case NodeEnum::kExpectPropertyClause: {
      VisitIndentedSection(node, 0, PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }

      // The following cases will always expand into their constituent
      // partitions:
    case NodeEnum::kModuleDeclaration:
    case NodeEnum::kProgramDeclaration:
    case NodeEnum::kPackageDeclaration:
    case NodeEnum::kInterfaceDeclaration:
    case NodeEnum::kFunctionDeclaration:
    case NodeEnum::kTaskDeclaration:
    case NodeEnum::kClassDeclaration:
    case NodeEnum::kClassHeader:
    case NodeEnum::kBegin:
    case NodeEnum::kEnd:
    // case NodeEnum::kFork:  // TODO(fangism): introduce this node enum
    // case NodeEnum::kJoin:  // TODO(fangism): introduce this node enum
    case NodeEnum::kParBlock:
    case NodeEnum::kSeqBlock:
    case NodeEnum::kGenerateBlock: {
      VisitIndentedSection(node, 0, PartitionPolicyEnum::kAlwaysExpand);
      break;
    }

    // The following set of cases are related to flow-control (loops and
    // conditionals) for statements and generate items:
    case NodeEnum::kAssertionBody:
    case NodeEnum::kAssumeBody:
    case NodeEnum::kCoverBody:
    case NodeEnum::kAssertPropertyBody:
    case NodeEnum::kAssumePropertyBody:
    case NodeEnum::kExpectPropertyBody:
    case NodeEnum::kCoverPropertyBody:
    case NodeEnum::kCoverSequenceBody:
    case NodeEnum::kWaitBody:
    case NodeEnum::kGenerateIfBody:
    case NodeEnum::kIfBody: {
      // In the case of if-begin, let the 'begin'-'end' block indent its own
      // section.  Othewise for single statements/items, indent here.
      const auto* subnode =
          verible::CheckOptionalSymbolAsNode(GetSubtreeAsSymbol(node, tag, 0));
      const auto next_indent =
          (subnode != nullptr && NodeIsBeginEndBlock(*subnode))
              ? 0
              : style_.indentation_spaces;
      VisitIndentedSection(node, next_indent,
                           PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }
    case NodeEnum::kGenerateElseBody:
    case NodeEnum::kElseBody: {
      // In the case of else-begin, let the 'begin'-'end' block indent its own
      // section, otherwise, indent single statements here.
      // In the case of else-if, suppress further indentation, deferring to
      // the conditional construct.
      const auto* subnode = GetSubtreeAsNode(node, tag, 0);
      const auto next_indent = subnode && NodeIsConditionalOrBlock(*subnode)
                                   ? 0
                                   : style_.indentation_spaces;
      VisitIndentedSection(node, next_indent,
                           PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }

    // For the following items, start a new unwrapped line only if they are
    // *direct* descendants of list elements.  This effectively suppresses
    // starting a new line when single statements are found to extend other
    // statements, delayed assignments, single-statement if/for loops.
    // search-anchor: STATEMENT_TYPES
    case NodeEnum::kNullItem:       // ;
    case NodeEnum::kNullStatement:  // ;
    case NodeEnum::kStatement:
    case NodeEnum::kLabeledStatement:  // e.g. foo_label : do_something();
    case NodeEnum::kJumpStatement:
    case NodeEnum::kWaitStatement:       // wait(expr) ...
    case NodeEnum::kWaitForkStatement:   // wait fork;
    case NodeEnum::kAssertionStatement:  // assert(expr);
    case NodeEnum::kAssumeStatement:     // assume(expr);
    case NodeEnum::kCoverStatement:      // cover(expr);
    case NodeEnum::kAssertPropertyStatement:
    case NodeEnum::kAssumePropertyStatement:
    case NodeEnum::kExpectPropertyStatement:
    case NodeEnum::kCoverPropertyStatement:
    case NodeEnum::kCoverSequenceStatement:
      // TODO(fangism): case NodeEnum::kRestrictPropertyStatement:
    case NodeEnum::kContinuousAssignmentStatement:  // e.g. assign x=y;
    case NodeEnum::kProceduralContinuousAssignmentStatement:  // e.g. assign
                                                              // x=y;
    case NodeEnum::kProceduralContinuousDeassignmentStatement:
    case NodeEnum::kProceduralContinuousForceStatement:
    case NodeEnum::kProceduralContinuousReleaseStatement:
    case NodeEnum::kNetVariableAssignment:           // e.g. x=y
    case NodeEnum::kBlockingAssignmentStatement:     // id=expr
    case NodeEnum::kNonblockingAssignmentStatement:  // dest <= src;
    case NodeEnum::kAssignModifyStatement:           // id+=expr
    case NodeEnum::kIncrementDecrementExpression:    // --y
    case NodeEnum::kProceduralTimingControlStatement:

      // various flow control constructs
    case NodeEnum::kCaseStatement:
    case NodeEnum::kRandCaseStatement:
    case NodeEnum::kForLoopStatement:
    case NodeEnum::kForeverLoopStatement:
    case NodeEnum::kRepeatLoopStatement:
    case NodeEnum::kWhileLoopStatement:
    case NodeEnum::kDoWhileLoopStatement:
    case NodeEnum::kForeachLoopStatement:
    case NodeEnum::kConditionalStatement:  //
    {
      // Single statements directly inside a flow-control construct
      // should be properly indented one level.
      const int indent = ShouldIndentRelativeToDirectParent(Context())
                             ? style_.indentation_spaces
                             : 0;
      VisitIndentedSection(node, indent,
                           PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }

    case NodeEnum::kReferenceCallBase: {
      // TODO(fangism): Create own section only for standalone calls
      if (Context().DirectParentIs(NodeEnum::kStatement)) {
        const auto& subnode = verible::SymbolCastToNode(
            *ABSL_DIE_IF_NULL(node.children().back()));
        if (subnode.MatchesTag(NodeEnum::kRandomizeMethodCallExtension) &&
            subnode.children().back() != nullptr) {
          // TODO(fangism): Handle constriants
          VisitIndentedSection(node, 0, PartitionPolicyEnum::kAlwaysExpand);
        } else if (subnode.MatchesTagAnyOf(
                       {NodeEnum::kMethodCallExtension,
                        NodeEnum::kRandomizeMethodCallExtension,
                        NodeEnum::kFunctionCall})) {
          VisitIndentedSection(
              node, 0, PartitionPolicyEnum::kAppendFittingSubPartitions);
        } else {
          TraverseChildren(node);
        }
      } else {
        TraverseChildren(node);
      }
      break;
    }

    case NodeEnum::kRandomizeFunctionCall: {
      // TODO(fangism): Create own section only for standalone calls
      if (Context().DirectParentIs(NodeEnum::kStatement)) {
        if (node.children().back() != nullptr) {
          // TODO(fangism): Handle constriants
          VisitIndentedSection(node, 0, PartitionPolicyEnum::kAlwaysExpand);
        } else {
          VisitIndentedSection(
              node, 0, PartitionPolicyEnum::kAppendFittingSubPartitions);
        }
      } else {
        TraverseChildren(node);
      }
      break;
    }

    case NodeEnum::kSystemTFCall: {
      const auto is_nested_call = [&] {
        return Context().DirectParentsAre(
                   {NodeEnum::kExpression, NodeEnum::kArgumentList}) ||
               Context().DirectParentsAre(
                   {NodeEnum::kExpression, NodeEnum::kMacroArgList});
      };

      const auto is_standalone_call = [&] {
        return Context().DirectParentsAre(
                   {NodeEnum::kStatement, NodeEnum::kStatementList}) ||
               Context().DirectParentsAre(
                   {NodeEnum::kStatement, NodeEnum::kBlockItemStatementList}) ||
               Context().DirectParentIs(NodeEnum::kModuleItemList);
      };

      // TODO(mglb): Format non-standalone calls with layout optimizer.
      // This requires using layout optimizer for structures wrapping the
      // calls.

      if (is_nested_call() &&
          HasContextHint(ContextHint::kInsideStandaloneMacroCall)) {
        VisitIndentedSection(node, 0, PartitionPolicyEnum::kStack);
      } else if (is_standalone_call()) {
        PushContextHint(ContextHint::kInsideStandaloneMacroCall);
        VisitIndentedSection(node, 0, PartitionPolicyEnum::kStack);
      } else {
        TraverseChildren(node);
      }
      break;
    };

    case NodeEnum::kMacroCall: {
      // Single statements directly inside a controlled construct
      // should be properly indented one level.
      const int indent = ShouldIndentRelativeToDirectParent(Context())
                             ? style_.indentation_spaces
                             : 0;

      const auto is_nested_call = [&] {
        return Context().DirectParentsAre(
                   {NodeEnum::kExpression, NodeEnum::kArgumentList}) ||
               Context().DirectParentsAre(
                   {NodeEnum::kExpression, NodeEnum::kMacroArgList});
      };
      const auto is_standalone_call = [&] {
        return ((Context().DirectParentIs(NodeEnum::kModuleItemList) ||
                 Context().DirectParentIs(NodeEnum::kClassItems) ||
                 Context().DirectParentIs(NodeEnum::kDescriptionList) ||
                 Context().DirectParentsAre({
                     NodeEnum::kStatementList,
                     NodeEnum::kTaskDeclaration,
                 }) ||
                 Context().DirectParentsAre({
                     NodeEnum::kLocalRoot,
                     NodeEnum::kReference,
                     NodeEnum::kReferenceCallBase,
                 }) ||
                 Context().DirectParentsAre({
                     NodeEnum::kBlockItemStatementList,
                     NodeEnum::kSeqBlock,
                     NodeEnum::kIfBody,
                     NodeEnum::kIfClause,
                 })) &&
                !(Context().IsInside(NodeEnum::kNetVariableAssignment)  //
                  ));
      };

      // TODO(mglb): Format non-standalone calls with layout optimizer.
      // This would require using layout optimizer for structures wrapping the
      // calls.

      if (is_nested_call() &&
          HasContextHint(ContextHint::kInsideStandaloneMacroCall)) {
        VLOG(4) << "kMacroCall: nested";
        VisitIndentedSection(node, indent, PartitionPolicyEnum::kStack);
      } else if (is_standalone_call()) {
        VLOG(4) << "kMacroCall: standalone";
        PushContextHint(ContextHint::kInsideStandaloneMacroCall);
        VisitIndentedSection(node, indent, PartitionPolicyEnum::kStack);
      } else {
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kAppendFittingSubPartitions);
      }

      break;
    }

    case NodeEnum::kParenGroup: {
      const bool is_directly_inside_macro_call = Context().DirectParentIsOneOf({
          NodeEnum::kMacroCall,
          NodeEnum::kSystemTFCall,
      });

      if (HasContextHint(ContextHint::kInsideStandaloneMacroCall) &&
          is_directly_inside_macro_call) {
        const bool is_nested_call = Context().IsInsideFirst(
            {
                NodeEnum::kArgumentList,
                NodeEnum::kMacroArgList,
                NodeEnum::kParenGroup,
            },
            {
                NodeEnum::kStatementList,
                NodeEnum::kStatement,
            });

        if (is_nested_call) {
          VisitIndentedSection(node, 0, PartitionPolicyEnum::kWrap);
        } else {
          VisitIndentedSection(node, style_.wrap_spaces,
                               PartitionPolicyEnum::kWrap);
        }
      } else {
        TraverseChildren(node);
      }
      break;
    }

    // The following constructs wish to use the partition policy of appending
    // trailing subpartitions greedily as long as they fit, wrapping as
    // needed.
    case NodeEnum::kPreprocessorDefine:
    case NodeEnum::kClassConstructorPrototype:
    case NodeEnum::kTaskHeader:
    case NodeEnum::kFunctionHeader:
    case NodeEnum::kTaskPrototype:
    case NodeEnum::kFunctionPrototype: {
      if (Context().IsInside(NodeEnum::kDPIExportItem) ||
          Context().IsInside(NodeEnum::kDPIImportItem)) {
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else {
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kAppendFittingSubPartitions);
      }
      break;
    }

    case NodeEnum::kDPIExportItem:
    case NodeEnum::kDPIImportItem: {
      VisitIndentedSection(node, 0, PartitionPolicyEnum::kAlwaysExpand);
      break;
    }

    // For the following constructs, always expand the view to subpartitions.
    // Add a level of indentation.
    case NodeEnum::kPackageImportList:
    case NodeEnum::kPackageItemList:
    case NodeEnum::kInterfaceClassDeclaration:
    case NodeEnum::kCasePatternItemList:
    case NodeEnum::kConstraintBlockItemList:
    case NodeEnum::kConstraintExpressionList:
    case NodeEnum::kAssertionVariableDeclarationList:
    // The final sequence_expr of a sequence_declaration is same indentation
    // level as the kAssertionVariableDeclarationList that precedes it.
    case NodeEnum::kSequenceDeclarationFinalExpr:
    case NodeEnum::kCoverageSpecOptionList:
    case NodeEnum::kCrossBodyItemList:
    case NodeEnum::kUdpBody:
    case NodeEnum::kUdpPortDeclaration:
    case NodeEnum::kUdpSequenceEntry:
    case NodeEnum::kUdpCombEntry:
    case NodeEnum::kSpecifyItemList:
    case NodeEnum::kClockingItemList: {
      // Do not further indent preprocessor clauses.
      const int indent = suppress_indentation ? 0 : style_.indentation_spaces;
      VisitIndentedSection(node, indent, PartitionPolicyEnum::kAlwaysExpand);
      break;
    }

    case NodeEnum::kBinOptionList: {
      PartitionPolicyEnum shouldExpand =
          style_.expand_coverpoints ? PartitionPolicyEnum::kAlwaysExpand
                                    : PartitionPolicyEnum::kFitOnLineElseExpand;
      // Do not further indent preprocessor clauses.
      const int indent = suppress_indentation ? 0 : style_.indentation_spaces;
      VisitIndentedSection(node, indent, shouldExpand);
      break;
    }

    case NodeEnum::kCoverPoint: {
      if (style_.expand_coverpoints) {
        VisitIndentedSection(node, 0, PartitionPolicyEnum::kAlwaysExpand);
      } else
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }

    case NodeEnum::kMacroArgList: {
      if (node.children().front() == nullptr ||
          node.children().front()->Tag().tag == verible::kUntagged) {
        // Empty arguments list.
        TraverseChildren(node);
        break;
      }
      if (HasContextHint(ContextHint::kInsideStandaloneMacroCall) &&
          Context().DirectParentsAre(
              {NodeEnum::kParenGroup, NodeEnum::kMacroCall})) {
        VisitIndentedSection(node, style_.wrap_spaces,
                             PartitionPolicyEnum::kWrap);
        break;
      }
    }
      [[fallthrough]];
    // Add a level of grouping that is treated as wrapping.
    case NodeEnum::kMacroFormalParameterList:
    case NodeEnum::kForSpec:
    case NodeEnum::kModportSimplePortsDeclaration:
    case NodeEnum::kModportTFPortsDeclaration:
    case NodeEnum::kGateInstanceRegisterVariableList:
    case NodeEnum::kVariableDeclarationAssignmentList: {
      // Do not further indent preprocessor clauses.
      const int indent = suppress_indentation ? 0 : style_.wrap_spaces;
      VisitIndentedSection(node, indent,
                           PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }
    case NodeEnum::kOpenRangeList: {
      if (Context().DirectParentsAre(
              {NodeEnum::kConcatenationExpression, NodeEnum::kExpression}) &&
          !Context().IsInside(NodeEnum::kCoverageBin) &&
          !Context().IsInside(NodeEnum::kConditionExpression) &&
          (!Context().IsInside(NodeEnum::kBinaryExpression) ||
           Context().IsInside(NodeEnum::kPropertyImplicationList))) {
        // Do not further indent preprocessor clauses.
        const int indent = suppress_indentation ? 0 : style_.indentation_spaces;
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
        break;
      } else {
        // Default handling
        TraverseChildren(node);
        break;
      }
    }

    case NodeEnum::kPortList: {
      if (Context().IsInside(NodeEnum::kDPIExportItem) ||
          Context().IsInside(NodeEnum::kDPIImportItem)) {
        const int indent = suppress_indentation ? 0 : style_.indentation_spaces;
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kTabularAlignment);
      } else {
        const int indent = suppress_indentation ? 0 : style_.wrap_spaces;
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      }
      break;
    }

    case NodeEnum::kBlockItemStatementList:
    case NodeEnum::kStatementList:
    case NodeEnum::kFunctionItemList:
    case NodeEnum::kCaseItemList:
    case NodeEnum::kCaseInsideItemList:
    case NodeEnum::kGenerateCaseItemList:
    case NodeEnum::kClassItems:
    case NodeEnum::kModuleItemList:
    case NodeEnum::kGenerateItemList:
    case NodeEnum::kDistributionItemList:
    case NodeEnum::kEnumNameList:
    case NodeEnum::kStructUnionMemberList: {
      const int indent = suppress_indentation ? 0 : style_.indentation_spaces;
      VisitIndentedSection(node, indent,
                           PartitionPolicyEnum::kTabularAlignment);
      break;
    }

      // module instantiations (which look like data declarations) want to
      // expand one parameter/port per line.
    case NodeEnum::kActualParameterByNameList: {
      const int indent =
          suppress_indentation ? 0 : style_.NamedParameterIndentation();
      VisitIndentedSection(node, indent,
                           PartitionPolicyEnum::kTabularAlignment);
      break;
    }
    case NodeEnum::kPortActualList:  // covers named and positional ports
    {
      const int indent =
          suppress_indentation ? 0 : style_.NamedPortIndentation();
      const auto policy = Context().IsInside(NodeEnum::kDataDeclaration) ||
                                  Context().IsInside(NodeEnum::kBindDirective)
                              ? PartitionPolicyEnum::kTabularAlignment
                              : PartitionPolicyEnum::kFitOnLineElseExpand;
      VisitIndentedSection(node, indent, policy);
      break;
    }

    case NodeEnum::kPortDeclarationList: {
      if (Context().IsInside(NodeEnum::kPortDeclarationList)) {
        // This "recursion" can occur when there are preprocessing conditional
        // port declaration lists.
        // When this occurs, suppress creating another token partition level.
        // This will essentially flatten all port declarations to the same token
        // partition tree depth, and importantly, be alignable across
        // preprocessing directives as sibling subpartitions.
        // Alternatively, we could have done this flattening during
        // ReshapeTokenPartitions(), but it would've taken more work to
        // re-identify the subpartitions (children) to flatten.
        TraverseChildren(node);
        break;
      }
      // Do not further indent preprocessor clauses.
      const int indent =
          suppress_indentation ? 0 : style_.PortDeclarationsIndentation();
      if (Context().IsInside(NodeEnum::kClassHeader) ||
          // kModuleHeader covers interfaces and programs
          Context().IsInside(NodeEnum::kModuleHeader)) {
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kTabularAlignment);
      } else {
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      }
      break;
    }
    case NodeEnum::kFormalParameterList: {
      // Do not further indent preprocessor clauses.
      const int indent =
          suppress_indentation ? 0 : style_.FormalParametersIndentation();
      if (Context().IsInside(NodeEnum::kClassHeader) ||
          // kModuleHeader covers interfaces and programs
          Context().IsInside(NodeEnum::kModuleHeader)) {
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kTabularAlignment);
      } else {
        VisitIndentedSection(node, indent,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      }
      break;
    }

      // Since NodeEnum::kActualParameterPositionalList consists of a
      // comma-separated list of expressions, we let those default to appending
      // to current token partition, and let the line-wrap-optimizer handle the
      // enclosing construct, such as a parameterized type like "foo #(1, 2)".

      // Special cases:
    case NodeEnum::kPropertySpec: {
      if (Context().IsInside(NodeEnum::kPropertyDeclaration)) {
        // indent the same level as kAssertionVariableDeclarationList
        // which (optionally) appears before the final property_spec.
        VisitIndentedSection(node, style_.indentation_spaces,
                             PartitionPolicyEnum::kAlwaysExpand);
      } else if (Context().DirectParentIs(NodeEnum::kMacroArgList)) {
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else {
        TraverseChildren(node);
      }
      break;
    }

    // kReference can be found in kIdentifierList
    // and kExpression can be found in kArgumentList & kMacroArgList
    case NodeEnum::kReference:
    case NodeEnum::kExpression: {
      if (Context().DirectParentIsOneOf({NodeEnum::kMacroArgList,
                                         NodeEnum::kArgumentList,
                                         NodeEnum::kIdentifierList})) {
        // original un-lexed macro argument was successfully expanded
        VisitNewUnwrappedLine(node);
      } else if (Context().DirectParentsAre({NodeEnum::kOpenRangeList,
                                             NodeEnum::kConcatenationExpression,
                                             NodeEnum::kExpression}) &&
                 !Context().IsInside(NodeEnum::kCoverageBin) &&
                 !Context().IsInside(NodeEnum::kConditionExpression) &&
                 (!Context().IsInside(NodeEnum::kBinaryExpression) ||
                  Context().IsInside(NodeEnum::kPropertyImplicationList))) {
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else if (Context().IsInside(NodeEnum::kAssignmentPattern)) {
        VisitIndentedSection(node, 0,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else {
        TraverseChildren(node);
      }
      break;
    }

    case NodeEnum::kExpressionList:
    case NodeEnum::kUntagged: {
      if (Context().DirectParentIs(NodeEnum::kAssignmentPattern)) {
        VisitIndentedSection(node, style_.wrap_spaces,
                             PartitionPolicyEnum::kFitOnLineElseExpand);
      } else {
        TraverseChildren(node);
      }
      break;
    }

    case NodeEnum::kAssignmentPattern:
    case NodeEnum::kPatternExpression: {
      VisitIndentedSection(node, 0, PartitionPolicyEnum::kFitOnLineElseExpand);
      break;
    }

    default: {
      TraverseChildren(node);
      // TODO(fangism): Eventually replace this case with:
      // VisitIndentedSection(node, 0,
      //     PartitionPolicyEnum::kFitOnLineElseExpand);
    }
  }
}

static bool PartitionStartsWithSemicolon(const TokenPartitionTree& partition) {
  const auto& uwline = partition.Value();
  if (uwline.IsEmpty()) return false;
  const auto first_token = uwline.TokensRange().front().TokenEnum();
  return (first_token == ';' ||
          first_token ==
              verilog_tokentype::SemicolonEndOfAssertionVariableDeclarations);
}

static bool PartitionIsCloseParenSemi(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.size() < 2) return false;
  if (ftokens.front().TokenEnum() != ')') return false;
  return ftokens.back().TokenEnum() == ';';
}

static bool PartitionStartsWithCloseParen(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.empty()) return false;
  const auto token_enum = ftokens.front().TokenEnum();
  return ((token_enum == ')') || (token_enum == MacroCallCloseToEndLine));
}

static bool PartitionEndsWithOpenParen(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.empty()) return false;
  const auto token_enum = ftokens.back().TokenEnum();
  return token_enum == '(';
}

static bool PartitionIsCloseBrace(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.size() != 1) return false;
  const auto token_enum = ftokens.front().TokenEnum();
  return token_enum == '}';
}

static bool PartitionEndsWithOpenBrace(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.empty()) return false;
  const auto token_enum = ftokens.back().TokenEnum();
  return token_enum == '{';
}

static bool PartitionStartsWithCloseBrace(const TokenPartitionTree& partition) {
  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.empty()) return false;
  const auto token_enum = ftokens.front().TokenEnum();
  return token_enum == '}';
}

// Returns true if the partition is forced to start in a new line.
static bool PartitionIsForcedIntoNewLine(const TokenPartitionTree& partition) {
  const auto policy = partition.Value().PartitionPolicy();
  if (policy == PartitionPolicyEnum::kAlreadyFormatted) return true;
  if (policy == PartitionPolicyEnum::kInline) return false;
  if (!is_leaf(partition)) {
    auto* first_leaf = &LeftmostDescendant(partition);
    const auto leaf_policy = first_leaf->Value().PartitionPolicy();
    if (leaf_policy == PartitionPolicyEnum::kAlreadyFormatted ||
        leaf_policy == PartitionPolicyEnum::kInline)
      return true;
  }

  const auto ftokens = partition.Value().TokensRange();
  if (ftokens.empty()) return false;
  return ftokens.front().before.break_decision == SpacingOptions::MustWrap;
}

// Joins partition containing only a ',' (and optionally comments) with
// a partition preceding or following it.
static void AttachSeparatorToPreviousOrNextPartition(
    TokenPartitionTree* partition) {
  CHECK_NOTNULL(partition);
  VLOG(5) << __FUNCTION__ << ": subpartition:\n" << *partition;

  if (!is_leaf(*partition)) {
    VLOG(5) << "  skip: not a leaf.";
    return;
  }

  // Find a separator and make sure this is the only non-comment token
  const verible::PreFormatToken* separator = nullptr;
  for (const auto& token : partition->Value().TokensRange()) {
    switch (token.TokenEnum()) {
      case verilog_tokentype::TK_COMMENT_BLOCK:
      case verilog_tokentype::TK_EOL_COMMENT:
      case verilog_tokentype::TK_ATTRIBUTE:
        break;
      case ',':
      case ':':
        if (separator == nullptr) {
          separator = &token;
          break;
        }
        [[fallthrough]];
      default:
        VLOG(5) << "  skip: contains tokens other than separator and comments.";
        return;
    }
  }
  if (separator == nullptr) {
    VLOG(5) << "  skip: separator token not found.";
    return;
  }

  // Merge with previous partition if both partitions are in the same line in
  // original text
  const auto* previous_partition = PreviousLeaf(*partition);
  if (previous_partition != nullptr) {
    if (!previous_partition->Value().TokensRange().empty()) {
      const auto& previous_token =
          previous_partition->Value().TokensRange().back();
      absl::string_view original_text_between = verible::make_string_view_range(
          previous_token.Text().end(), separator->Text().begin());
      if (!absl::StrContains(original_text_between, '\n')) {
        VLOG(5) << "  merge into previous partition.";
        verible::MergeLeafIntoPreviousLeaf(partition);
        return;
      }
    }
  }

  // Merge with next partition if both partitions are in the same line in
  // original text
  const auto* next_partition = NextLeaf(*partition);
  if (next_partition != nullptr) {
    if (!next_partition->Value().TokensRange().empty()) {
      const auto& next_token = next_partition->Value().TokensRange().front();
      absl::string_view original_text_between = verible::make_string_view_range(
          separator->Text().end(), next_token.Text().begin());
      if (!absl::StrContains(original_text_between, '\n')) {
        VLOG(5) << "  merge into next partition.";
        verible::MergeLeafIntoNextLeaf(partition);
        return;
      }
    }
  }

  // If there are no comments (separator is the only token)...
  if (partition->Value().TokensRange().size() == 1) {
    // Try merging with previous partition
    if (!PartitionIsForcedIntoNewLine(*partition)) {
      VLOG(5) << "  merge into previous partition.";
      verible::MergeLeafIntoPreviousLeaf(partition);
      return;
    }

    // Try merging with next partition
    if (next_partition != nullptr &&
        !PartitionIsForcedIntoNewLine(*next_partition)) {
      VLOG(5) << "  merge into next partition.";
      verible::MergeLeafIntoNextLeaf(partition);
      return;
    }
  }

  // Leave the separator in its own line and clear its Origin() to not confuse
  // tabular alignment.
  VLOG(5) << "  keep in separate line, remove origin.";
  partition->Value().SetOrigin(nullptr);
}

void AttachSeparatorsToListElementPartitions(TokenPartitionTree* partition) {
  CHECK_NOTNULL(partition);
  // Skip the first partition, it can't contain just a separator.
  for (int i = 1; i < static_cast<int>(partition->Children().size()); ++i) {
    auto& subpartition = partition->Children()[i];
    // This can change children count
    AttachSeparatorToPreviousOrNextPartition(&subpartition);
  }
}

static void AttachTrailingSemicolonToPreviousPartition(
    TokenPartitionTree* partition) {
  // TODO(mglb): Replace this function with
  // AttachSeparatorToPreviousOrNextPartition().

  // Attach the trailing ';' partition to the previous sibling leaf.
  // VisitIndentedSection() finished by starting a new partition,
  // so we need to back-track to the previous sibling partition.

  // In some cases where macros are involved, there may not necessarily
  // be a semicolon where one is grammatically expected.
  // In those cases, do nothing.
  auto* semicolon_partition = &RightmostDescendant(*partition);
  if (PartitionStartsWithSemicolon(*semicolon_partition)) {
    // When the semicolon is forced to wrap (e.g. when previous partition ends
    // with EOL comment), wrap previous partition with a group and append the
    // semicolon partition to it.
    if (PartitionIsForcedIntoNewLine(*semicolon_partition)) {
      auto* group = verible::GroupLeafWithPreviousLeaf(semicolon_partition);
      // Update invalidated pointer
      semicolon_partition = &RightmostDescendant(*group);
      group->Value().SetPartitionPolicy(
          verible::PartitionPolicyEnum::kAlwaysExpand);
      // Set indentation of partition with semicolon to match indentation of the
      // partition it has been grouped with
      semicolon_partition->Value().SetIndentationSpaces(
          group->Value().IndentationSpaces());
    } else {
      verible::MergeLeafIntoPreviousLeaf(semicolon_partition);
    }
    VLOG(4) << "after moving semicolon:\n" << *partition;
  }
}

static void AdjustSubsequentPartitionsIndentation(TokenPartitionTree* partition,
                                                  int indentation) {
  // Adjust indentation of subsequent partitions
  const auto npartitions = partition->Children().size();
  if (npartitions > 1) {
    const auto& first_partition = partition->Children().front();
    const auto& last_partition = partition->Children().back();

    // Do not indent intentionally wrapped partitions, e.g.
    // { (>>[assign foo = {] }
    // { (>>>>[<auto>]
    //   { (>>>>[a ,] }
    //   { (>>>>[b ,] }
    //   { (>>>>[c ,] }
    //   { (>>>>[d] }
    // }
    // { (>>[} ;] }
    if (!(PartitionEndsWithOpenBrace(first_partition) &&
          PartitionStartsWithCloseBrace(last_partition)) &&
        !(PartitionEndsWithOpenParen(first_partition) &&
          PartitionIsCloseParenSemi(last_partition))) {
      for (unsigned int idx = 1; idx < npartitions; ++idx) {
        AdjustIndentationRelative(&partition->Children()[idx], indentation);
      }
    }
  }
}

// Merges first found subpartition ending with "=" or ":" with "'{" or "{"
// from the subpartition following it.
static void AttachOpeningBraceToDeclarationsAssignmentOperator(
    TokenPartitionTree* partition) {
  const int children_count = partition->Children().size();
  if (children_count <= 1) return;

  for (int i = 0; i < children_count - 1; ++i) {
    auto& current = RightmostDescendant(partition->Children()[i]);
    const auto tokens = current.Value().TokensRange();
    if (tokens.empty()) continue;

    auto rbegin = std::make_reverse_iterator(tokens.end());
    auto rend = std::make_reverse_iterator(tokens.begin());
    auto last_non_comment_it =
        std::find_if_not(rbegin, rend, [](const PreFormatToken& token) {
          // Lines with EOL Comment are non-mergable, so don't skip it here.
          return token.TokenEnum() == verilog_tokentype::TK_COMMENT_BLOCK;
        });
    if (last_non_comment_it == rend ||
        !(last_non_comment_it->TokenEnum() == '=' ||
          last_non_comment_it->TokenEnum() == ':'))
      continue;

    const auto& next = partition->Children()[i + 1];
    if (next.Value().IsEmpty()) continue;

    const auto& next_token = next.Value().TokensRange().front();
    if (!(next_token.TokenEnum() == verilog_tokentype::TK_LP ||
          next_token.TokenEnum() == '{'))
      continue;

    if (!PartitionIsForcedIntoNewLine(next)) {
      verible::MergeLeafIntoNextLeaf(&current);
      // There shouldn't be more matching partitions
      return;
    }
  }
}

static void ReshapeIfClause(const SyntaxTreeNode& node,
                            TokenPartitionTree* partition_ptr) {
  auto& partition = *partition_ptr;
  const SyntaxTreeNode* body = GetAnyControlStatementBody(node);
  if (body == nullptr || !NodeIsBeginEndBlock(*body)) {
    VLOG(4) << "if-body was not a begin-end block.";
    // If body is a null statement, attach it to the previous partition.
    AttachTrailingSemicolonToPreviousPartition(partition_ptr);
    return;
  }

  // Then fuse the 'begin' partition with the preceding 'if (...)'
  auto& if_body_partition = partition.Children().back();
  auto& begin_partition = if_body_partition.Children().front();
  verible::MergeLeafIntoPreviousLeaf(&begin_partition);
  partition.Value().SetPartitionPolicy(
      if_body_partition.Value().PartitionPolicy());
  // if seq_block body was empty, that leaves only 'end', so hoist.
  // if if-header was flat, hoist that too.
  FlattenOneChild(partition, verible::BirthRank(if_body_partition));
}

static void ReshapeElseClause(const SyntaxTreeNode& node,
                              TokenPartitionTree* partition_ptr) {
  auto& partition = *partition_ptr;
  const SyntaxTreeNode& else_body_subnode =
      *ABSL_DIE_IF_NULL(GetAnyControlStatementBody(node));
  if (!NodeIsConditionalOrBlock(else_body_subnode)) {
    VLOG(4) << "else-body was neither a begin-end block nor if-conditional.";
    // If body is a null statement, attach it to the previous partition.
    AttachTrailingSemicolonToPreviousPartition(partition_ptr);
    return;
  }

  // Then fuse 'else' and 'begin' partitions together
  // or fuse the 'else' and 'if' (header) partitions together
  auto& children = partition.Children();
  auto else_partition_iter = std::find_if(
      children.begin(), children.end(), [](const TokenPartitionTree& n) {
        const auto* origin = n.Value().Origin();
        return origin &&
               origin->Tag() == verible::LeafTag(verilog_tokentype::TK_else);
      });
  if (else_partition_iter == children.end()) return;

  auto& else_partition = *else_partition_iter;
  auto* next_leaf = NextLeaf(else_partition);
  if (!next_leaf || PartitionIsForcedIntoNewLine(*next_leaf)) return;

  const auto* next_origin = next_leaf->Value().Origin();
  if (!next_origin ||
      !(next_origin->Tag() == verible::NodeTag(NodeEnum::kBegin) ||
        next_origin->Tag() == verible::LeafTag(verilog_tokentype::TK_begin) ||
        next_origin->Tag() == verible::NodeTag(NodeEnum::kIfHeader) ||
        next_origin->Tag() == verible::NodeTag(NodeEnum::kGenerateIfHeader) ||
        next_origin->Tag() == verible::LeafTag(verilog_tokentype::TK_if)))
    return;

  verible::MergeLeafIntoNextLeaf(&else_partition);
}

static void HoistOnlyChildPartition(TokenPartitionTree* partition) {
  // kWrap uses relative child indentation as a hanging
  // if (partition->Value().PartitionPolicy() == PartitionPolicyEnum::kWrap) {
  // TODO(mglb): implement or remove.
  // }
  const auto* origin = partition->Value().Origin();
  if (HoistOnlyChild(*partition)) {
    VLOG(4) << "reshape: hoisted, using child partition policy, parent origin";
    // Preserve source origin
    partition->Value().SetOrigin(origin);
  }
}

static void PushEndIntoElsePartition(TokenPartitionTree* partition_ptr) {
  // Then combine 'end' with the following 'else' ...
  // Do not flatten, so that if- and else- clauses can make formatting
  // decisions independently from each other.
  auto& partition = *partition_ptr;
  auto& if_clause_partition = partition.Children().front();
  auto* end_partition = &RightmostDescendant(if_clause_partition);
  auto* end_parent = verible::MergeLeafIntoNextLeaf(end_partition);
  // if moving leaf results in any singleton partitions, hoist.
  if (end_parent != nullptr) {
    HoistOnlyChildPartition(end_parent);
  }
}

static void MergeEndElseWithoutLabel(const SyntaxTreeNode& conditional,
                                     TokenPartitionTree* partition_ptr) {
  auto& partition = *partition_ptr;
  // Handle merging of 'else' partition with (possibly)
  // a previous 'end' partition.
  // Do not flatten, so that if- and else- clauses can make formatting
  // decisions independently from each other.
  const auto* if_body_subnode =
      GetAnyControlStatementBody(*GetAnyConditionalIfClause(conditional));
  if (if_body_subnode == nullptr || !NodeIsBeginEndBlock(*if_body_subnode)) {
    VLOG(4) << "if-body was not begin-end block";
    return;
  }
  VLOG(4) << "if body was a begin-end block";
  const auto* end_label = GetEndLabel(GetBlockEnd(*if_body_subnode));
  if (end_label != nullptr) {
    VLOG(4) << "'end' came with label, no merge";
    return;
  }
  VLOG(4) << "No 'end' label, merge 'end' and 'else...' partitions";
  PushEndIntoElsePartition(&partition);
}

static void FlattenElseIfElse(const SyntaxTreeNode& else_clause,
                              TokenPartitionTree* partition_ptr) {
  // Keep chained else-if-else conditionals in a flat structure.
  auto& partition = *partition_ptr;
  const auto& else_body_subnode = *GetAnyControlStatementBody(else_clause);
  if (NodeIsConditionalConstruct(else_body_subnode) &&
      GetAnyConditionalElseClause(else_body_subnode) != nullptr) {
    FlattenOneChild(partition, partition.Children().size() - 1);
  }
}

static void ReshapeConditionalConstruct(const SyntaxTreeNode& conditional,
                                        TokenPartitionTree* partition_ptr) {
  const auto* else_clause = GetAnyConditionalElseClause(conditional);
  if (else_clause == nullptr) {
    VLOG(4) << "there was no else clause";
    return;
  }
  VLOG(4) << "there was an else clause";
  MergeEndElseWithoutLabel(conditional, partition_ptr);
  FlattenElseIfElse(*else_clause, partition_ptr);
}

static bool TokenIsComment(const PreFormatToken& t) {
  return IsComment(verilog_tokentype(t.TokenEnum()));
}

static void SetCommentLinePartitionAsAlreadyFormatted(
    TokenPartitionTree* partition) {
  for (auto& child : partition->Children()) {
    if (!is_leaf(child)) continue;
    const auto tokens = child.Value().TokensRange();
    if (std::all_of(tokens.begin(), tokens.end(), TokenIsComment)) {
      child.Value().SetPartitionPolicy(PartitionPolicyEnum::kAlreadyFormatted);
    }
  }
}

using TokenPartitionPredicate = std::function<bool(const TokenPartitionTree&)>;

// TokenPartitionPredicate returning true for partitions whose Origin's tag is
// equal to any tag from `tags` list.
struct OriginTagIs {
  OriginTagIs(std::initializer_list<SymbolTag> tags) : tags(tags) {}

  std::initializer_list<SymbolTag> tags;

  bool operator()(const TokenPartitionTree& partition) const {
    if (!partition.Value().Origin()) return false;
    for (const auto& tag : tags) {
      if (partition.Value().Origin()->Tag() == tag) return true;
    }
    return false;
  }
};

// TokenPartitionPredicate returning true for partitions containing token with a
// type equal to any value from `token_types` list.
struct ContainsToken {
  ContainsToken(std::initializer_list<int> token_types)
      : token_types(token_types) {}

  std::initializer_list<int> token_types;

  bool operator()(const TokenPartitionTree& partition) const {
    for (const auto& token : partition.Value().TokensRange()) {
      for (const auto token_type : token_types) {
        if (token.TokenEnum() == token_type) return true;
      }
    }
    return false;
  }
};

// Finds direct child of the `parent` node satisfying the `predicate`. Returns
// nullptr when child has not been found.
static const TokenPartitionTree* FindDirectChild(
    const TokenPartitionTree* parent, TokenPartitionPredicate predicate) {
  if (!parent) return nullptr;
  auto iter = std::find_if(parent->Children().begin(), parent->Children().end(),
                           std::move(predicate));
  if (iter == parent->Children().end()) return nullptr;
  return &(*iter);
}

// Finds direct child of the `parent` node satisfying the `predicate`. Returns
// nullptr when child has not been found.
static TokenPartitionTree* FindDirectChild(TokenPartitionTree* parent,
                                           TokenPartitionPredicate predicate) {
  const TokenPartitionTree* const_parent = parent;
  return const_cast<TokenPartitionTree*>(
      FindDirectChild(const_parent, std::move(predicate)));
}

static bool LineBreaksInsidePartitionBeforeChild(
    const TokenPartitionTree& parent, const TokenPartitionTree& child) {
  for (auto& node : parent.Children()) {
    if (PartitionIsForcedIntoNewLine(node)) return true;
    if (&node == &child) break;
  }
  return false;
}

class MacroCallReshaper {
 public:
  explicit MacroCallReshaper(const FormatStyle& style,
                             TokenPartitionTree* main_node)
      : style_(style),
        main_node_(main_node),
        is_nested_(IsNested(*main_node)) {}

  void Reshape() {
    const auto* const main_node_origin = main_node_->Value().Origin();

    if (!FindInitialPartitions()) {
      // Something went wrong, leave partitions intact. Log message has been
      // printed.
      return;
    }

    if (semicolon_) {
      if (semicolon_ == NextSibling(*paren_group_)) {
        if (!PartitionIsForcedIntoNewLine(*semicolon_)) {
          // Merge with ')'
          verible::MergeLeafIntoPreviousLeaf(semicolon_);
          semicolon_ = nullptr;
        }
      }
    }

    if (ReshapeEmptyParenGroup()) {
      auto* identifier_with_paren_group = main_node_;
      if (!IsLastChild(*paren_group_)) {
        // There is a semicolon preceded by comment line(s).
        identifier_with_paren_group =
            verible::GroupLeafWithPreviousLeaf(paren_group_);
        identifier_with_paren_group->Value().SetPartitionPolicy(
            PartitionPolicyEnum::kJuxtapositionOrIndentedStack);
        main_node_->Value().SetPartitionPolicy(PartitionPolicyEnum::kStack);
      }

      if (main_node_origin &&
          main_node_origin->Tag() == NodeTag(NodeEnum::kMacroCall)) {
        // '(' must follow macro identifier in the same line
        CHECK(!PartitionIsForcedIntoNewLine(*paren_group_));
        identifier_with_paren_group->Children().clear();
        identifier_with_paren_group->Value().SetPartitionPolicy(
            PartitionPolicyEnum::kAlreadyFormatted);
      }

      return;
    }

    if ((!argument_list_ || is_leaf(*argument_list_)) &&
        (BirthRank(*r_paren_) - BirthRank(*l_paren_) > 1)) {
      // Group partitions between parentheses (comments and stuff)
      CreateArgumentList();
    }

    if (argument_list_ &&
        (is_nested_ || !PartitionIsForcedIntoNewLine(*r_paren_))) {
      // Format like a part of argument list.
      MoveRightParenToArgumentList();
    }

    if (argument_list_ && style_.try_wrap_long_lines) {
      for (auto& arg : argument_list_->Children()) {
        const auto tokens = arg.Value().TokensRange();
        // Hack: in order to avoid wrapping just before comment, do not enable
        // wrapping on partitions containing comments.
        if (is_leaf(arg) &&
            arg.Value().PartitionPolicy() !=
                PartitionPolicyEnum::kAlreadyFormatted &&
            std::none_of(tokens.begin(), tokens.end(),
                         [](const PreFormatToken& t) {
                           return IsComment(verilog_tokentype(t.TokenEnum()));
                         }))
          arg.Value().SetPartitionPolicy(PartitionPolicyEnum::kWrap);
      }
    }

    if (main_node_origin &&
        main_node_origin->Tag() == NodeTag(NodeEnum::kMacroCall)) {
      // '(' must follow macro identifier in the same line
      MergeIdentifierAndLeftParen();
    } else if (!LineBreaksInsidePartitionBeforeChild(*paren_group_,
                                                     *l_paren_)) {
      GroupIdentifierCommentsAndLeftParen();
    } else if (l_paren_ != &paren_group_->Children().front()) {
      GroupCommentsAndLeftParen();
    }

    if (argument_list_) {
      HoistOnlyChildPartition(argument_list_);
      if (paren_group_->Children().size() == 3) {
        // Children: '(', argument_list, ')'
        GroupLeftParenAndArgumentList();
      }

      if (!PartitionIsForcedIntoNewLine(paren_group_->Children().back())) {
        paren_group_->Value().SetPartitionPolicy(
            PartitionPolicyEnum::kJuxtapositionOrIndentedStack);
      } else {
        paren_group_->Value().SetPartitionPolicy(PartitionPolicyEnum::kStack);
      }
    }
  }

 private:
  static bool IsLeftParenPartition(const TokenPartitionTree& node) {
    const auto tokens = node.Value().TokensRange();
    bool found = false;
    auto token = tokens.begin();
    for (; token != tokens.end(); ++token) {
      if (token->TokenEnum() == '(') {
        found = true;
        ++token;
        break;
      }
      if (token->TokenEnum() == verilog_tokentype::TK_COMMENT_BLOCK) continue;
      return false;
    }
    for (; token != tokens.end(); ++token) {
      if (IsComment(verilog_tokentype(token->TokenEnum()))) continue;
      if (found && token->TokenEnum() == ')') continue;
      return false;
    }
    return found;
  }

  // Report a bug/untested situation, but don't abort.
#define LOG_PARTITION_BUG(reason)                               \
  LOG(ERROR) << "formatting of macro call failed: " << (reason) \
             << "\n*** Please file a bug. ***";

  bool FindInitialPartitions() {
    // Note: identifier can contain tokens for macro name + EOL comment
    identifier_ = FindDirectChild(
        main_node_, ContainsToken{verilog_tokentype::SystemTFIdentifier,
                                  verilog_tokentype::MacroCallId});
    if (!identifier_) {
      LOG_PARTITION_BUG("identifier not found.");
      return false;
    }

    paren_group_ = FindDirectChild(main_node_,
                                   OriginTagIs{NodeTag(NodeEnum::kParenGroup)});

    // Macro can be used without parentheses
    if (!paren_group_) {
      return false;
    }

    // Make sure there's nothing between identifier and paren group partitions.
    // Optional comment partitions are expected to be inside paren group.
    if (NextSibling(*identifier_) != paren_group_) {
      LOG_PARTITION_BUG(
          "Unexpected partitions between identifier and paren_group.");
      return false;
    }

    if (!IsLastChild(*paren_group_)) {
      semicolon_ = &main_node_->Children().back();
      if (!ContainsToken{';'}(*semicolon_)) {
        LOG_PARTITION_BUG("Unexpected partition(s) after the call.");
        LOG(ERROR) << "\n" << *main_node_;
        return false;
      }
    }

    if (is_leaf(*paren_group_)) {
      l_paren_ = paren_group_;
      r_paren_ = paren_group_;
    } else {
      l_paren_ = FindDirectChild(paren_group_, IsLeftParenPartition);
      if (!l_paren_) {
        LOG_PARTITION_BUG("'(' not found.");
        return false;
      }
      r_paren_ = &paren_group_->Children().back();
      if (!ContainsToken{
              ')', verilog_tokentype::MacroCallCloseToEndLine}(*r_paren_)) {
        LOG_PARTITION_BUG("')' not found.");
        return false;
      }
      const auto l_paren_index = BirthRank(*l_paren_);
      const auto r_paren_index = BirthRank(*r_paren_);
      CHECK_LE(l_paren_index, r_paren_index);
      for (std::size_t i = l_paren_index + 1; i < r_paren_index; ++i) {
        auto& child = paren_group_->Children()[i];
        if (OriginTagIs{NodeTag(NodeEnum::kArgumentList),
                        NodeTag(NodeEnum::kMacroArgList)}(child)) {
          argument_list_ = &child;
          break;
        }
      }
    }
    return true;
  }

#undef LOG_PARTITION_BUG

  bool ReshapeEmptyParenGroup() {
    if (paren_group_->Children().size() == 2 && l_paren_ != r_paren_ &&
        l_paren_->Value().TokensRange().end() ==
            r_paren_->Value().TokensRange().begin() &&
        !PartitionIsForcedIntoNewLine(*r_paren_)) {
      VLOG(6) << "Flatten paren group.";
      paren_group_->Children().clear();
    }
    if (is_leaf(*paren_group_)) {
      if (!PartitionIsForcedIntoNewLine(*paren_group_)) {
        main_node_->Value().SetPartitionPolicy(
            PartitionPolicyEnum::kJuxtapositionOrIndentedStack);
      }
      VLOG(6) << "Empty paren group.";
      return true;
    }

    return false;
  }

  void CreateArgumentList() {
    const int arguments_indentation =
        paren_group_->Value().IndentationSpaces() + style_.wrap_spaces;
    auto group = TokenPartitionTree(verible::UnwrappedLine(
        arguments_indentation, l_paren_->Value().TokensRange().end(),
        PartitionPolicyEnum::kWrap));
    group.Value().SpanUpToToken(r_paren_->Value().TokensRange().begin());

    const auto paren_group_begin = paren_group_->Children().begin();
    const auto args_begin = paren_group_begin + BirthRank(*l_paren_) + 1;
    const auto args_end = paren_group_begin + BirthRank(*r_paren_);
    // Move partitions into the group.
    group.Children().assign(std::make_move_iterator(args_begin),
                            std::make_move_iterator(args_end));
    for (auto& node : group.Children()) {
      verible::AdjustIndentationAbsolute(&node, arguments_indentation);
    }
    // Remove leftover entries of all grouped partitions except the first.
    paren_group_->Children().erase(args_begin + 1, args_end);

    // Move the group into first grouped partition's place.
    *args_begin = std::move(group);

    argument_list_ = &*args_begin;
    r_paren_ = NextSibling(*argument_list_);
  }

  void MoveRightParenToArgumentList() {
    {
      r_paren_->Value().SetIndentationSpaces(
          argument_list_->Value().IndentationSpaces());
      const auto r_paren_iter =
          paren_group_->Children().begin() + BirthRank(*r_paren_);
      argument_list_->Value().SpanUpToToken(
          r_paren_->Value().TokensRange().end());
      argument_list_->Children().push_back(std::move(*r_paren_));
      r_paren_ = &argument_list_->Children().back();
      paren_group_->Children().erase(r_paren_iter);
    }
    if (!PartitionIsForcedIntoNewLine(*r_paren_)) {
      // We want to avoid wrapping just before `)`. It would be best to use
      // token's break_penalty in Layout Optimizer, but that's a task for
      // future.
      // So far, use hacky heuristic: merge short partitions (things
      // like `);`) and group longer ones (anything with comments).
      const auto r_paren_tokens = r_paren_->Value().TokensRange();
      if (is_leaf(*r_paren_) &&
          std::none_of(r_paren_tokens.begin(), r_paren_tokens.end(),
                       [](const PreFormatToken& t) {
                         return IsComment(verilog_tokentype(t.TokenEnum()));
                       })) {
        // Merge
        verible::MergeLeafIntoPreviousLeaf(r_paren_);
        r_paren_ = &argument_list_->Children().back();
      } else {
        // Group
        auto& last_argument = *PreviousSibling(*r_paren_);
        auto group = TokenPartitionTree(
            verible::UnwrappedLine(last_argument.Value().IndentationSpaces(),
                                   last_argument.Value().TokensRange().begin(),
                                   PartitionPolicyEnum::kJuxtaposition));
        group.Value().SpanUpToToken(r_paren_->Value().TokensRange().end());
        group.Children().reserve(2);
        group.Children().push_back(std::move(last_argument));
        group.Children().push_back(std::move(*r_paren_));
        argument_list_->Children().erase(argument_list_->Children().end() - 1);
        argument_list_->Children().back() = std::move(group);
        r_paren_ = &argument_list_->Children().back();
      }
    }
  }

  void GroupIdentifierCommentsAndLeftParen() {
    const bool r_paren_is_in_arg_list = (r_paren_->Parent() == argument_list_);
    auto group = TokenPartitionTree(
        verible::UnwrappedLine(main_node_->Value().IndentationSpaces(),
                               identifier_->Value().TokensRange().begin(),
                               PartitionPolicyEnum::kJuxtaposition));
    group.Value().SpanUpToToken(l_paren_->Value().TokensRange().end());

    verible::AdjustIndentationAbsolute(paren_group_,
                                       main_node_->Value().IndentationSpaces());

    paren_group_->Value().SpanBackToToken(group.Value().TokensRange().begin());

    const auto old_identifier_iter =
        identifier_->Parent()->Children().begin() + BirthRank(*identifier_);
    const auto l_paren_index = BirthRank(*l_paren_);
    auto nodes_to_group = verible::iterator_range(
        paren_group_->Children().begin(),
        paren_group_->Children().begin() + l_paren_index + 1);

    const auto nodes_count = l_paren_index + 1 + 1;  // + 1 for identifier
    group.Children().reserve(nodes_count);
    // Move partitions into the group.
    group.Children().push_back(std::move(*identifier_));
    group.Children().insert(group.Children().end(),
                            std::make_move_iterator(nodes_to_group.begin()),
                            std::make_move_iterator(nodes_to_group.end()));
    // Remove leftover entries of all grouped partitions except:
    // * First paren_group's child: will be reused as a group node.
    // * The identifier: removing it will invalidate iterators; done later.
    paren_group_->Children().erase(nodes_to_group.begin() + 1,
                                   nodes_to_group.end());

    // Move the group into first grouped partition's place.
    *nodes_to_group.begin() = std::move(group);

    // Remove identifier
    main_node_->Children().erase(old_identifier_iter);

    HoistOnlyChildPartition(main_node_);

    paren_group_ = main_node_;
    identifier_ = nullptr;
    l_paren_ = &paren_group_->Children().front();
    if (argument_list_) {
      argument_list_ = NextSibling(*l_paren_);
      r_paren_ = r_paren_is_in_arg_list ? &argument_list_->Children().back()
                                        : NextSibling(*argument_list_);
    } else {
      r_paren_ = &paren_group_->Children().back();
    }
  }

  void MergeIdentifierAndLeftParen() {
    const bool r_paren_is_in_arg_list = (r_paren_->Parent() == argument_list_);
    CHECK_EQ(NextLeaf(*identifier_), l_paren_);
    CHECK(!PartitionIsForcedIntoNewLine(*l_paren_));
    verible::AdjustIndentationAbsolute(paren_group_,
                                       main_node_->Value().IndentationSpaces());
    verible::MergeLeafIntoNextLeaf(identifier_);
    HoistOnlyChildPartition(main_node_);

    paren_group_ = main_node_;
    identifier_ = nullptr;
    l_paren_ = &paren_group_->Children().front();
    if (argument_list_) {
      argument_list_ = NextSibling(*l_paren_);
      r_paren_ = r_paren_is_in_arg_list ? &argument_list_->Children().back()
                                        : NextSibling(*argument_list_);
    } else {
      r_paren_ = &paren_group_->Children().back();
    }
  }

  void GroupCommentsAndLeftParen() {
    // Group comments + '('
    auto group = TokenPartitionTree(
        verible::UnwrappedLine(paren_group_->Value().IndentationSpaces(),
                               paren_group_->Value().TokensRange().begin(),
                               PartitionPolicyEnum::kWrap));
    group.Value().SpanUpToToken(l_paren_->Value().TokensRange().end());

    const auto l_paren_index = BirthRank(*l_paren_);
    const auto paren_group_begin = paren_group_->Children().begin();
    auto nodes_to_group = verible::iterator_range(
        paren_group_begin, paren_group_begin + l_paren_index + 1);

    // Move partitions into the group.
    group.Children().assign(std::make_move_iterator(nodes_to_group.begin()),
                            std::make_move_iterator(nodes_to_group.end()));

    // Remove leftover entries of all grouped partitions except:
    // * First paren_group's child: will be reused as a group node.
    paren_group_->Children().erase(nodes_to_group.begin() + 1,
                                   nodes_to_group.end());

    // Move the group into first grouped partition's place.
    *nodes_to_group.begin() = std::move(group);

    l_paren_ = &(*nodes_to_group.begin());

    if (argument_list_) {
      argument_list_ = NextSibling(*l_paren_);
      r_paren_ = is_nested_ ? &argument_list_->Children().back()
                            : NextSibling(*argument_list_);
    } else {
      r_paren_ = &paren_group_->Children().back();
    }
  }

  void GroupLeftParenAndArgumentList() {
    auto old_argument_list_iter =
        paren_group_->Children().begin() + BirthRank(*argument_list_);

    const auto group_policy =
        PartitionIsForcedIntoNewLine(*argument_list_)
            ? PartitionPolicyEnum::kStack
            : PartitionPolicyEnum::kJuxtapositionOrIndentedStack;

    auto group = TokenPartitionTree(verible::UnwrappedLine(
        l_paren_->Value().IndentationSpaces(),
        l_paren_->Value().TokensRange().begin(), group_policy));
    group.Value().SpanUpToToken(argument_list_->Value().TokensRange().end());
    AdoptSubtree(group, std::move(*l_paren_), std::move(*argument_list_));

    *l_paren_ = std::move(group);
    paren_group_->Children().erase(old_argument_list_iter);

    l_paren_ = nullptr;
    argument_list_ = nullptr;
  }

  const FormatStyle& style_;
  TokenPartitionTree* const main_node_;

  // Subnodes of main_node_. Initialized by FindInitialPartitions().
  // Tree modifications invalidate pointers, so keeping pointers here instead
  // of passing them to each method allows for more readable code.
  TokenPartitionTree* identifier_ = nullptr;
  TokenPartitionTree* paren_group_ = nullptr;
  TokenPartitionTree* argument_list_ = nullptr;
  TokenPartitionTree* l_paren_ = nullptr;
  TokenPartitionTree* r_paren_ = nullptr;
  TokenPartitionTree* semicolon_ = nullptr;

  static bool IsNested(const TokenPartitionTree& macro_call_node) {
    auto* paren_group = FindDirectChild(
        &macro_call_node, OriginTagIs{NodeTag(NodeEnum::kParenGroup)});
    if (!paren_group) return false;
    return paren_group->Value().IndentationSpaces() ==
           macro_call_node.Value().IndentationSpaces();
  }

  const bool is_nested_;
};

static void IndentBetweenUVMBeginEndMacros(TokenPartitionTree* partition_ptr,
                                           int indentation_spaces) {
  auto& partition = *partition_ptr;
  // Indent elements between UVM begin/end macro calls
  unsigned int uvm_level = 1;
  std::vector<TokenPartitionTree*> uvm_range;

  // Search backwards for matching _begin.
  for (auto* itr = PreviousSibling(partition); itr;
       itr = PreviousSibling(*itr)) {
    VLOG(4) << "Scanning previous sibling:\n" << *itr;
    const auto macroId =
        LeftmostDescendant(*itr).Value().TokensRange().front().Text();
    VLOG(4) << "macro id: " << macroId;

    // Indent only uvm macros
    if (!absl::StartsWith(macroId, "`uvm_")) {
      continue;
    }

    // Count uvm indentation level
    if (absl::EndsWith(macroId, "_end")) {
      uvm_level++;
    } else if (absl::EndsWith(macroId, "_begin")) {
      uvm_level--;
    }

    // Break before indenting matching _begin macro
    if (uvm_level == 0) {
      break;
    }

    uvm_range.push_back(itr);
  }

  // Found matching _begin-_end macros
  if ((uvm_level == 0) && !uvm_range.empty()) {
    VLOG(4) << "Found matching uvm-begin/end macros";
    for (auto* itr : uvm_range) {
      // Indent uvm macros inside `uvm.*begin - `uvm.*end
      verible::AdjustIndentationRelative(itr, +indentation_spaces);
    }
  }
}

static const SyntaxTreeNode* GetAssignedExpressionFromDataDeclaration(
    const verible::Symbol& data_declaration) {
  const auto* instance_list =
      GetInstanceListFromDataDeclaration(data_declaration);
  if (!instance_list || instance_list->children().empty()) return nullptr;

  const auto& variable_or_gate = *instance_list->children().front();
  if (variable_or_gate.Tag().kind != verible::SymbolKind::kNode) return nullptr;

  const verible::Symbol* trailing_assign;
  if (variable_or_gate.Tag() == verible::NodeTag(NodeEnum::kRegisterVariable)) {
    trailing_assign =
        GetTrailingExpressionFromRegisterVariable(variable_or_gate);
  } else if (variable_or_gate.Tag() ==
             verible::NodeTag(NodeEnum::kVariableDeclarationAssignment)) {
    trailing_assign =
        GetTrailingExpressionFromVariableDeclarationAssign(variable_or_gate);
  } else {
    return nullptr;
  }
  if (!trailing_assign) return nullptr;

  const verible::Symbol* expression = verible::GetSubtreeAsSymbol(
      *trailing_assign, NodeEnum::kTrailingAssign, 1);
  if (!expression ||
      expression->Tag() != verible::NodeTag(NodeEnum::kExpression))
    return nullptr;

  return &verible::SymbolCastToNode(*expression);
}

// This phase is strictly concerned with reshaping token partitions,
// and occurs on the return path of partition tree construction.
void TreeUnwrapper::ReshapeTokenPartitions(
    const SyntaxTreeNode& node, const FormatStyle& style,
    TokenPartitionTree* recent_partition) {
  const auto tag = static_cast<NodeEnum>(node.Tag().tag);
  VLOG(3) << __FUNCTION__ << " node: " << tag;
  auto& partition = *recent_partition;
  VLOG(4) << "before reshaping " << tag << ":\n"
          << VerilogPartitionPrinter(partition);

  // Few node types that need to skip hoisting at the end of this function set
  // this flag to true.
  bool skip_singleton_hoisting = false;

  // Tips, when making reshaping decisions based on subtrees:
  //   * Manipulate the partition *incrementally* and as close to the
  //     corresponding node enum case that produced it as possible.
  //     In otherwords, minimize the depth of examination needed to
  //     make a reshaping decision.  If there is insufficient information to
  //     make a decision, that would be a good reason to defer to a parent node.
  //   * Prefer to examine the SyntaxTreeNode& node instead of the token
  //     partition tree because the token partition tree may include
  //     EOL-comments as nodes.  Use/create CST functions to abstract away
  //     the precise structural details.
  //   * Altering the indentation and partition policy itself is allowed,
  //     even though they were set during the
  //     SetIndentationsAndCreatePartitions() phase.

  // post-creation token partition adjustments
  switch (tag) {
    // Note: this is also being applied to variable declaration lists,
    // which may want different handling than instantiations.
    case NodeEnum::kDataDeclaration: {
      AttachTrailingSemicolonToPreviousPartition(&partition);
      auto& data_declaration_partition = partition;
      auto& children = data_declaration_partition.Children();
      CHECK(!children.empty());

      // TODO(fangism): fuse qualifiers (if any) with type partition

      // The instances/variable declaration list is always in last position.
      auto& instance_list_partition = children.back();
      if (  // TODO(fangism): get type and qualifiers from declaration node,
            // and check whether type node is implicit, using CST functions.
          verible::BirthRank(instance_list_partition) == 0) {
        VLOG(4) << "No qualifiers and type is implicit";
        // This means there are no qualifiers and type was implicit,
        // so no partition precedes this.
        // Use the declaration (parent) level's indentation.
        verible::AdjustIndentationAbsolute(
            &instance_list_partition,
            data_declaration_partition.Value().IndentationSpaces());
        HoistOnlyChildPartition(&instance_list_partition);
      } else if (GetInstanceListFromDataDeclaration(node)->children().size() ==
                 1) {
        VLOG(4) << "Instance list has only one child, singleton.";

        // Undo the indentation of the only instance in the hoisted subtree.
        verible::AdjustIndentationRelative(&instance_list_partition,
                                           -style.wrap_spaces);
        VLOG(4) << "After un-indenting, instance list:\n"
                << instance_list_partition;

        // Reshape type-instance partitions.
        auto* instance_type_partition =
            ABSL_DIE_IF_NULL(PreviousSibling(children.back()));
        VLOG(4) << "instance type:\n" << *instance_type_partition;

        if (instance_type_partition == &children.front()) {
          // data_declaration_partition now consists of exactly:
          //   instance_type_partition, instance_list_partition (single
          //   instance)

          // Flatten these (which will invalidate their references).
          std::vector<size_t> offsets;
          FlattenOnlyChildrenWithChildren(data_declaration_partition, &offsets);
          // This position in the flattened result will be merged.
          const size_t fuse_position = offsets.back() - 1;

          // Join the rightmost of instance_type_partition with the leftmost of
          // instance_list_partition.  Keep the type's indentation.
          // This can yield an intermediate partition that contains:
          // ") instance_name (".
          MergeConsecutiveSiblings(&data_declaration_partition, fuse_position);
        } else {
          // There is a qualifier before instance_type_partition.
          FlattenOnlyChildrenWithChildren(data_declaration_partition);
        }
      } else {
        VLOG(4) << "None of the special cases apply.";
      }

      // Handle variable declaration with an assignment

      const auto* assigned_expr =
          GetAssignedExpressionFromDataDeclaration(node);
      if (!assigned_expr || assigned_expr->children().empty()) break;

      AttachOpeningBraceToDeclarationsAssignmentOperator(&partition);

      // Special handling for assignment of a string concatenation

      const auto* concat_expr_symbol = assigned_expr->children().front().get();
      if (concat_expr_symbol->Tag() !=
          verible::NodeTag(NodeEnum::kConcatenationExpression))
        break;

      const auto* open_range_list_symbol =
          verible::SymbolCastToNode(*concat_expr_symbol).children()[1].get();
      if (open_range_list_symbol->Tag() !=
          verible::NodeTag(NodeEnum::kOpenRangeList))
        break;

      const auto& open_range_list =
          verible::SymbolCastToNode(*open_range_list_symbol);

      if (std::all_of(
              open_range_list.children().cbegin(),
              open_range_list.children().cend(),
              [](const verible::SymbolPtr& sym) {
                if (sym->Tag() == verible::NodeTag(NodeEnum::kExpression)) {
                  const auto& expr = verible::SymbolCastToNode(*sym.get());
                  return !expr.children().empty() &&
                         expr.children().front()->Tag() ==
                             verible::LeafTag(
                                 verilog_tokentype::TK_StringLiteral);
                }
                return (sym->Kind() == verible::SymbolKind::kLeaf);
              })) {
        auto& assigned_value_partition =
            data_declaration_partition.Children()[1];
        partition.Value().SetPartitionPolicy(
            PartitionPolicyEnum::kAppendFittingSubPartitions);
        assigned_value_partition.Value().SetPartitionPolicy(
            PartitionPolicyEnum::kAlwaysExpand);
      }

      break;
    }

    // For these cases, the leading sub-partition is merged into its next
    // relative.  This is useful for constructs that are repeatedly prefixed
    // with attributes, but otherwise maintain the same subpartition shape.
    case NodeEnum::kForwardDeclaration:
      // partition consists of (example):
      //   [pure virtual]
      //   [task ... ] (task header/prototype)
      // Push the qualifiers down.
    case NodeEnum::kDPIExportItem:
    case NodeEnum::kDPIImportItem:
      // partition consists of (example):
      //   [import "DPI-C"]
      //   [function ... ] (task header/prototype)
      // Push the "import..." down.
      {
        if (partition.Children().size() > 1) {
          verible::MergeLeafIntoNextLeaf(&partition.Children().front());
          AttachTrailingSemicolonToPreviousPartition(&partition);
        }
        break;
      }
    case NodeEnum::kBindDirective: {
      AttachTrailingSemicolonToPreviousPartition(&partition);

      // Take advantage here that preceding data declaration partition
      // was already shaped.
      auto& target_instance_partition = partition;
      auto& children = target_instance_partition.Children();
      // Attach ')' to the instance name
      verible::MergeLeafIntoNextLeaf(PreviousSibling(children.back()));

      verible::AdjustIndentationRelative(&children.back(), -style.wrap_spaces);
      break;
    }
    case NodeEnum::kStatement: {
      // This handles cases like macro-calls followed by a semicolon.
      AttachTrailingSemicolonToPreviousPartition(&partition);
      break;
    }
    case NodeEnum::kModuleHeader: {
      // Allow empty ports to appear as "();"
      if (partition.Children().size() >= 2) {
        auto& last = partition.Children().back();
        auto& last_prev = *ABSL_DIE_IF_NULL(PreviousSibling(last));
        if (PartitionStartsWithCloseParen(last) &&
            PartitionEndsWithOpenParen(last_prev)) {
          verible::MergeLeafIntoPreviousLeaf(&last);
        }
      }
      // If there were any parameters or ports at all, expand.
      // TODO(fangism): This should be done by inspecting the CST node,
      // instead of the partition structure.
      if (partition.Children().size() > 2) {
        partition.Value().SetPartitionPolicy(
            PartitionPolicyEnum::kAlwaysExpand);
      }
      break;
    }

    case NodeEnum::kClassHeader: {
      // Allow empty parameters to appear as "#();"
      if (partition.Children().size() >= 2) {
        auto& last = partition.Children().back();
        auto& last_prev = *ABSL_DIE_IF_NULL(PreviousSibling(last));
        if (PartitionStartsWithCloseParen(last) &&
            PartitionEndsWithOpenParen(last_prev)) {
          verible::MergeLeafIntoPreviousLeaf(&last);
        }
      }
      break;
    }

      // The following partitions may end up with a trailing ");" subpartition
      // and want to attach it to the item that preceded it.
    case NodeEnum::kClassConstructorPrototype:
    case NodeEnum::kFunctionHeader:
    case NodeEnum::kFunctionPrototype:
    case NodeEnum::kTaskHeader:
    case NodeEnum::kTaskPrototype: {
      auto& last = RightmostDescendant(partition);
      if (PartitionIsCloseParenSemi(last)) {
        verible::MergeLeafIntoPreviousLeaf(&last);
      }
      break;
    }
    case NodeEnum::kReferenceCallBase: {
      const auto& subnode = verible::SymbolCastToNode(*node.children().back());
      if (subnode.MatchesTagAnyOf({NodeEnum::kMethodCallExtension,
                                   NodeEnum::kFunctionCall,
                                   NodeEnum::kRandomizeMethodCallExtension})) {
        if (partition.Value().PartitionPolicy() ==
            PartitionPolicyEnum::kAppendFittingSubPartitions) {
          auto& last = RightmostDescendant(partition);
          if (PartitionStartsWithCloseParen(last) ||
              PartitionStartsWithSemicolon(last)) {
            verible::MergeLeafIntoPreviousLeaf(&last);
          }
        }
      }
      break;
    }

    case NodeEnum::kMacroCall: {
      const auto policy = partition.Value().PartitionPolicy();
      if (policy == PartitionPolicyEnum::kStack) {
        MacroCallReshaper(style, &partition).Reshape();
        break;
      }
      if (MacroCallArgsIsEmpty(*GetMacroCallArgs(node))) {
        // If there are no call args, join the name, '(' and ')' together.
        partition.Children().clear();
      } else {
        // Merge closing parenthesis into last argument partition
        // Test for ')' and MacroCallCloseToEndLine because macros
        // use its own token 'MacroCallCloseToEndLine'
        auto& last = RightmostDescendant(partition);
        if (PartitionStartsWithCloseParen(last) ||
            PartitionIsCloseParenSemi(last)) {
          auto& token = last.Value().TokensRange().front();
          if (token.before.break_decision ==
              verible::SpacingOptions::MustWrap) {
            auto* group = verible::GroupLeafWithPreviousLeaf(&last);
            group->Value().SetPartitionPolicy(PartitionPolicyEnum::kStack);
          } else {
            verible::MergeLeafIntoPreviousLeaf(&last);
          }
        }
      }
      break;
    }

    case NodeEnum::kRandomizeFunctionCall:
    case NodeEnum::kSystemTFCall: {
      // Function/system calls don't always have it's own section.
      // So before we do any adjuments we check that.
      // We're checking for partition policy because those two policies
      // force own partition section.
      const auto policy = partition.Value().PartitionPolicy();
      if (policy == PartitionPolicyEnum::kAppendFittingSubPartitions) {
        auto& last = RightmostDescendant(partition);
        if (PartitionStartsWithCloseParen(last) ||
            PartitionStartsWithSemicolon(last)) {
          auto& token = last.Value().TokensRange().front();
          if (token.before.break_decision ==
              verible::SpacingOptions::MustWrap) {
            auto* group = verible::GroupLeafWithPreviousLeaf(&last);
            group->Value().SetPartitionPolicy(PartitionPolicyEnum::kStack);
          } else {
            verible::MergeLeafIntoPreviousLeaf(&last);
          }
        }
      } else if (policy == PartitionPolicyEnum::kStack) {
        MacroCallReshaper(style, &partition).Reshape();
      }
      break;
    }

    case NodeEnum::kAssertionVariableDeclarationList: {
      AttachTrailingSemicolonToPreviousPartition(&partition);
      break;
    }

    case NodeEnum::kArgumentList: {
      SetCommentLinePartitionAsAlreadyFormatted(&partition);
      AttachSeparatorsToListElementPartitions(&partition);
      break;
    }

    case NodeEnum::kMacroArgList: {
      SetCommentLinePartitionAsAlreadyFormatted(&partition);
      AttachSeparatorsToListElementPartitions(&partition);
      break;
    }

    case NodeEnum::kParenGroup: {
      SetCommentLinePartitionAsAlreadyFormatted(&partition);
      break;
    }

    case NodeEnum::kGenerateIfHeader:
    case NodeEnum::kIfHeader: {
      // Fix indentation in case of e.g. function calls inside if headers
      // TODO(fangism): This should be done smarter (using CST) or removed
      //     after better handling of function calls inside expressions
      //     e.g. kBinaryExpression, kUnaryPrefixExpression...
      if (partition.Children().size() > 1) {
        auto if_header_partition_iter = std::find_if(
            partition.Children().begin(), partition.Children().end(),
            [](const TokenPartitionTree& n) {
              const auto* origin = n.Value().Origin();
              return origin && origin->Tag() ==
                                   verible::LeafTag(verilog_tokentype::TK_if);
            });
        if (if_header_partition_iter == partition.Children().end()) break;

        // Adjust indentation of all partitions following if header recursively
        for (auto& child : make_range(if_header_partition_iter + 1,
                                      partition.Children().end())) {
          verible::AdjustIndentationRelative(&child, style.wrap_spaces);
        }
      }
      break;
    }

      // The following cases handle reshaping around if/else/begin/end.
    case NodeEnum::kAssertionClause:
    case NodeEnum::kAssumeClause:
    case NodeEnum::kCoverStatement:
    case NodeEnum::kWaitStatement:
    case NodeEnum::kAssertPropertyClause:
    case NodeEnum::kAssumePropertyClause:
    case NodeEnum::kExpectPropertyClause:
    case NodeEnum::kCoverPropertyStatement:
    case NodeEnum::kCoverSequenceStatement:
    case NodeEnum::kIfClause:
    case NodeEnum::kGenerateIfClause: {
      ReshapeIfClause(node, &partition);
      break;
    }
    case NodeEnum::kGenerateElseClause:
    case NodeEnum::kElseClause: {
      ReshapeElseClause(node, &partition);
      break;
    }

    case NodeEnum::kAssertionStatement:
      // Contains a kAssertionClause and possibly a kElseClause
    case NodeEnum::kAssumeStatement:
      // Contains a kAssumeClause and possibly a kElseClause
    case NodeEnum::kAssertPropertyStatement:
      // Contains a kAssertPropertyClause and possibly a kElseClause
    case NodeEnum::kAssumePropertyStatement:
      // Contains a kAssumePropertyClause and possibly a kElseClause
    case NodeEnum::kExpectPropertyStatement:
      // Contains a kExpectPropertyClause and possibly a kElseClause
    case NodeEnum::kConditionalStatement:
      // Contains a kIfClause and possibly a kElseClause
    case NodeEnum::kConditionalGenerateConstruct:
      // Contains a kGenerateIfClause and possibly a kGenerateElseClause
      {
        ReshapeConditionalConstruct(node, &partition);
        break;
      }

    case NodeEnum::kPreprocessorDefine: {
      auto& last = RightmostDescendant(partition);
      // TODO(fangism): why does test fail without this clause?
      if (PartitionStartsWithCloseParen(last)) {
        verible::MergeLeafIntoPreviousLeaf(&last);
      }
      break;
    }

    case NodeEnum::kConstraintDeclaration: {
      // TODO(fangism): kConstraintSet should be handled similarly with {}
      if (partition.Children().size() == 2) {
        auto& last = RightmostDescendant(partition);
        if (PartitionIsCloseBrace(last)) {
          verible::MergeLeafIntoPreviousLeaf(&last);
        }
      }
      break;
    }

    case NodeEnum::kConstraintBlockItemList: {
      HoistOnlyChildPartition(&partition);

      // Alwyas expand constraint(s) blocks with braces inside them
      const auto& uwline = partition.Value();
      const auto& ftokens = uwline.TokensRange();
      auto found = std::find_if(ftokens.begin(), ftokens.end(),
                                [](const verible::PreFormatToken& token) {
                                  return token.TokenEnum() == '{';
                                });
      if (found != ftokens.end()) {
        VLOG(4) << "Found brace group, forcing expansion";
        partition.Value().SetPartitionPolicy(
            PartitionPolicyEnum::kAlwaysExpand);
      }
      break;
    }

      // This group of cases is temporary: simplify these during the
      // rewrite/refactor of this function.
      // See search-anchor: STATEMENT_TYPES
    case NodeEnum::kNetVariableAssignment:           // e.g. x=y
    case NodeEnum::kBlockingAssignmentStatement:     // id=expr
    case NodeEnum::kNonblockingAssignmentStatement:  // dest <= src;
    case NodeEnum::kAssignModifyStatement:           // id+=expr
    {
      VLOG(4) << "before moving semicolon:\n" << partition;
      AttachTrailingSemicolonToPreviousPartition(&partition);
      // RHS may have been further partitioned, e.g. a macro call.
      auto& children = partition.Children();
      if (children.size() == 2 &&
          verible::is_leaf(children.front()) /* left side */) {
        verible::MergeLeafIntoNextLeaf(&children.front());
        VLOG(4) << "after merge leaf (left-into-right):\n" << partition;
      }
      break;
    }
    case NodeEnum::kProceduralTimingControlStatement: {
      std::vector<size_t> offsets;
      FlattenOnlyChildrenWithChildren(partition, &offsets);
      VLOG(4) << "before moving semicolon:\n" << partition;
      AttachTrailingSemicolonToPreviousPartition(&partition);
      // Check body, for kSeqBlock, merge 'begin' with previous sibling
      if (const auto* tbody = GetProceduralTimingControlStatementBody(node);
          tbody != nullptr && NodeIsBeginEndBlock(*tbody)) {
        verible::MergeConsecutiveSiblings(&partition, offsets[1] - 1);
        VLOG(4) << "after merge siblings:\n" << partition;
      }
      break;
    }
    case NodeEnum::kProceduralContinuousAssignmentStatement:
    case NodeEnum::kProceduralContinuousForceStatement:
    case NodeEnum::kContinuousAssignmentStatement: {  // e.g. assign a=0, b=2;
      // TODO(fangism): group into above similar assignment statement cases?
      //   Cannot easily move now due to multiple-assignments.
      FlattenOnlyChildrenWithChildren(partition);
      VLOG(4) << "after flatten:\n" << partition;
      AttachTrailingSemicolonToPreviousPartition(&partition);
      AttachSeparatorsToListElementPartitions(&partition);
      // Merge the 'assign' keyword with the (first) x=y assignment.
      // TODO(fangism): reshape for multiple assignments.
      verible::MergeLeafIntoNextLeaf(&partition.Children().front());
      VLOG(4) << "after merging 'assign':\n" << partition;
      AdjustSubsequentPartitionsIndentation(&partition, style.wrap_spaces);
      VLOG(4) << "after adjusting partitions indentation:\n" << partition;
      break;
    }
    case NodeEnum::kForSpec: {
      // This applies to loop statements and loop generate constructs.
      // There are two 'partitions' with ';'.
      // Merge those with their predecessor sibling partitions.
      auto& children = partition.Children();
      const auto iter1 = std::find_if(children.begin(), children.end(),
                                      PartitionStartsWithSemicolon);
      CHECK(iter1 != children.end());
      const auto iter2 =
          std::find_if(iter1 + 1, children.end(), PartitionStartsWithSemicolon);
      CHECK(iter2 != children.end());
      const int dist1 = std::distance(children.begin(), iter1);
      const int dist2 = std::distance(children.begin(), iter2);
      VLOG(4) << "kForSpec got ';' at child " << dist1 << " and " << dist2;
      // Merge from back-to-front to keep indices valid.
      if (dist2 > 0 && (dist2 - dist1 > 1)) {
        verible::MergeLeafIntoPreviousLeaf(&*iter2);
      }
      if (dist1 > 0) {
        verible::MergeLeafIntoPreviousLeaf(&*iter1);
      }
      break;
    }
    case NodeEnum::kLoopGenerateConstruct:
    case NodeEnum::kForLoopStatement:
    case NodeEnum::kForeverLoopStatement:
    case NodeEnum::kRepeatLoopStatement:
    case NodeEnum::kWhileLoopStatement:
    case NodeEnum::kForeachLoopStatement:
    case NodeEnum::kLabeledStatement:
    case NodeEnum::kCaseItem:
    case NodeEnum::kDefaultItem:
    case NodeEnum::kCaseInsideItem:
    case NodeEnum::kCasePatternItem:
    case NodeEnum::kGenerateCaseItem:
    // case NodeEnum::kAlwaysStatement:  // handled differently below
    // TODO(fangism): always,initial,final should be handled the same way
    case NodeEnum::kInitialStatement:
    case NodeEnum::kFinalStatement: {
      // Check if 'initial' is separated from 'begin' by EOL_COMMENT. If so,
      // adjust indentation and do not merge leaf into previous leaf.
      const verible::UnwrappedLine& unwrapped_line = partition.Value();
      verible::FormatTokenRange tokenrange = unwrapped_line.TokensRange();
      auto token_tmp = tokenrange.begin();
      if (token_tmp->TokenEnum() == TK_initial &&
          (++token_tmp)->TokenEnum() == TK_EOL_COMMENT &&
          (++token_tmp)->TokenEnum() == TK_begin) {
        AdjustIndentationRelative(
            &partition.Children()[(partition.Children().size() - 1)],
            style.indentation_spaces);
        break;
      }

      // In these cases, merge the 'begin' partition of the statement block
      // with the preceding keyword or header partition.
      if (NodeIsBeginEndBlock(
              verible::SymbolCastToNode(*node.children().back()))) {
        auto& seq_block_partition = partition.Children().back();
        VLOG(4) << "block partition: " << seq_block_partition;
        auto& begin_partition = LeftmostDescendant(seq_block_partition);
        VLOG(4) << "begin partition: " << begin_partition;
        CHECK(is_leaf(begin_partition));
        verible::MergeLeafIntoPreviousLeaf(&begin_partition);
        VLOG(4) << "after merging 'begin' to predecessor:\n" << partition;
        // Flatten only the statement block so that the control partition
        // can retain its own partition policy.
        FlattenOneChild(partition, verible::BirthRank(seq_block_partition));
      }
      break;
    }
    case NodeEnum::kDoWhileLoopStatement: {
      if (const auto* dw = GetDoWhileStatementBody(node);
          dw != nullptr && NodeIsBeginEndBlock(*dw)) {
        // between do... and while (...);
        auto& seq_block_partition = partition.Children()[1];

        // merge "do" <- "begin"
        auto& begin_partition = LeftmostDescendant(seq_block_partition);
        verible::MergeLeafIntoPreviousLeaf(&begin_partition);

        // merge "end" -> "while"
        auto& end_partition = RightmostDescendant(seq_block_partition);
        verible::MergeLeafIntoNextLeaf(&end_partition);

        // Flatten only the statement block so that the control partition
        // can retain its own partition policy.
        FlattenOneChild(partition, verible::BirthRank(seq_block_partition));
      }
      break;
    }

    case NodeEnum::kAlwaysStatement: {
      if (GetSubtreeAsNode(node, tag, node.children().size() - 1)
              ->MatchesTagAnyOf({NodeEnum::kProceduralTimingControlStatement,
                                 NodeEnum::kSeqBlock})) {
        // Merge 'always' keyword with next sibling, and adjust subtree indent.
        verible::MergeLeafIntoNextLeaf(&partition.Children().front());
        verible::AdjustIndentationAbsolute(
            &partition.Children().front(),
            partition.Value().IndentationSpaces());
        VLOG(4) << "after merging 'always':\n" << partition;
      }
      break;
    }

    case NodeEnum::kMacroGenericItem: {
      const auto* token = GetMacroGenericItemId(node);
      if (token && absl::StartsWith(token->text(), "`uvm_") &&
          absl::EndsWith(token->text(), "_end")) {
        VLOG(4) << "Found `uvm_*_end macro call";
        IndentBetweenUVMBeginEndMacros(&partition, style.indentation_spaces);
      }
      break;
    }

    case NodeEnum::kGateInstanceRegisterVariableList:
      // parent: kDataDeclaration
      skip_singleton_hoisting = true;
      [[fallthrough]];
    case NodeEnum::kActualParameterByNameList:
    case NodeEnum::kDistributionItemList:
    case NodeEnum::kEnumNameList:
    case NodeEnum::kFormalParameterList:
    case NodeEnum::kOpenRangeList:
    case NodeEnum::kPortActualList:
    case NodeEnum::kPortDeclarationList:
    case NodeEnum::kPortList:
    case NodeEnum::kVariableDeclarationAssignmentList:
    case NodeEnum::kMacroFormalParameterList: {
      AttachSeparatorsToListElementPartitions(&partition);
      break;
    }

    case NodeEnum::kModportDeclaration: {
      AttachSeparatorsToListElementPartitions(&partition);
      break;
    }

    case NodeEnum::kExpressionList:
    case NodeEnum::kUntagged: {
      AttachSeparatorsToListElementPartitions(&partition);
      skip_singleton_hoisting = true;
      break;
    }

    case NodeEnum::kParamDeclaration: {
      AttachTrailingSemicolonToPreviousPartition(&partition);
      AttachOpeningBraceToDeclarationsAssignmentOperator(&partition);
      break;
    }

    case NodeEnum::kAssignmentPattern: {
      FlattenOnlyChildrenWithChildren(partition);
      break;
    }

    case NodeEnum::kPatternExpression: {
      if (partition.Children().size() >= 3) {
        auto& colon = partition.Children()[1];
        AttachSeparatorToPreviousOrNextPartition(&colon);
      }
      FlattenOnlyChildrenWithChildren(partition);
      AttachOpeningBraceToDeclarationsAssignmentOperator(&partition);
      break;
    }

    default:
      break;
  }

  // In the majority of cases, automatically hoist singletons.
  // A few node types, however, will wish to delay the hoisting change,
  // so that the parent node can make reshaping decisions based on the
  // child node's original unhoisted form.
  if (!skip_singleton_hoisting) {
    HoistOnlyChildPartition(&partition);
  }

  VLOG(4) << "after reshaping " << tag << ":\n"
          << VerilogPartitionPrinter(partition);
  VLOG(3) << "end of " << __FUNCTION__ << " node: " << tag;
}

// Visitor to determine which leaf enum function to call
void TreeUnwrapper::Visit(const verible::SyntaxTreeLeaf& leaf) {
  VLOG(3) << __FUNCTION__ << " leaf: " << VerboseToken(leaf.get());
  const verilog_tokentype tag = verilog_tokentype(leaf.Tag().tag);

  // Catch up on any non-whitespace tokens that fall between the syntax tree
  // leaves, such as comments and attributes, stopping at the current leaf.
  CatchUpToCurrentLeaf(leaf.get());
  VLOG(4) << "Visit leaf: after CatchUp";

  // Possibly start new partition (without advancing token iterator).
  UpdateInterLeafScanner(tag);

  // Sanity check that NextUnfilteredToken() is aligned to the current leaf.
  CHECK_EQ(NextUnfilteredToken()->text().begin(), leaf.get().text().begin());

  // Start a new partition in the following cases.
  // In most other cases, do nothing.
  if (IsPreprocessorControlFlow(tag)) {
    VLOG(4) << "handling preprocessor control flow token";
    StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, &leaf);
    CurrentUnwrappedLine().SetIndentationSpaces(0);
  } else if (IsEndKeyword(tag)) {
    VLOG(4) << "handling end* keyword";
    StartNewUnwrappedLine(PartitionPolicyEnum::kAlwaysExpand, &leaf);
  }

  auto& partition = *ABSL_DIE_IF_NULL(CurrentTokenPartition());
  VLOG(4) << "before adding token " << VerboseToken(leaf.get()) << ":\n"
          << VerilogPartitionPrinter(partition);

  // Advances NextUnfilteredToken(), and extends CurrentUnwrappedLine().
  // Should be equivalent to AdvanceNextUnfilteredToken().
  AddTokenToCurrentUnwrappedLine();

  // Make sure that newly extended unwrapped line has origin symbol
  // FIXME: Pretty sure that this should be handled in an other way,
  //    e.g. in common/formatting/tree_unwrapper.cc similarly
  //    to StartNewUnwrappedLine()
  if (CurrentUnwrappedLine().Origin() == nullptr &&
      CurrentUnwrappedLine().TokensRange().size() == 1) {
    CurrentUnwrappedLine().SetOrigin(&leaf);
  }

  // Look-ahead to any trailing comments that are associated with this leaf,
  // up to a newline.
  LookAheadBeyondCurrentLeaf();

  VLOG(4) << "before reshaping " << VerboseToken(leaf.get()) << ":\n"
          << VerilogPartitionPrinter(partition);

  // Post-token-handling token partition adjustments:
  switch (leaf.Tag().tag) {
    case PP_else: {
      // Do not allow non-comment tokens on the same line as `else
      // (comments were handled above)
      StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, &leaf);
      break;
    }
    default:
      break;
  }

  VLOG(4) << "after reshaping " << VerboseToken(leaf.get()) << ":\n"
          << VerilogPartitionPrinter(partition);
  VLOG(3) << "end of " << __FUNCTION__ << " leaf: " << VerboseToken(leaf.get());
}

// Specialized node visitors

void TreeUnwrapper::VisitNewUnwrappedLine(const SyntaxTreeNode& node) {
  StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, &node);
  TraverseChildren(node);
}

void TreeUnwrapper::VisitNewUnindentedUnwrappedLine(
    const SyntaxTreeNode& node) {
  StartNewUnwrappedLine(PartitionPolicyEnum::kFitOnLineElseExpand, &node);
  // Force the current line to be unindented without losing track of where
  // the current indentation level is for children.
  CurrentUnwrappedLine().SetIndentationSpaces(0);
  TraverseChildren(node);
}

}  // namespace formatter
}  // namespace verilog
