Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/formatter.cpp (C++)

Code before:
    chunk.include_in_output = true;
    to_add.append(chunk.dependencies);
    chunk.dependencies.clear();
  }
}

auto Formatter::ShouldIncludeInstByIR(InstId inst_id) -> bool {
  const auto* import_ir = GetCanonicalFileAndInstId(sem_ir_, inst_id).first;
  return include_ir_in_dumps_[import_ir->check_ir_id().index];
}

auto Formatter::ShouldFormatEntity(InstId decl_id, bool is_definition_start)
    -> bool {
  if (!decl_id.has_value()) {
    return true;
  }
  if (!ShouldIncludeInstByIR(decl_id)) {
    return false;
  }

  if (!use_dump_sem_ir_ranges_) {
    return true;
  }

  // When there are dump ranges, ignore imported instructions.
  auto loc_id = sem_ir_->insts().GetCanonicalLocId(decl_id);
  if (loc_id.kind() != LocId::Kind::NodeId) {
    return false;
  }

  const auto& tree_and_subtrees = get_tree_and_subtrees_();

  // This takes the earliest token from either the node or its first postorder
  // child. The first postorder child isn't necessarily the earliest token in
  // the subtree (for example, it can miss modifiers), but finding the earliest
  // token requires walking *all* children, whereas this approach is
  // constant-time.
  auto begin_node_id = *tree_and_subtrees.postorder(loc_id.node_id()).begin();

  // Non-defining declarations will be associated with a `Decl` node.
  // Definitions will have a `DefinitionStart` for which we can use the parent
  // to find the `Definition`, giving a range that includes the definition's
  // body.
  auto end_node_id = loc_id.node_id();
  if (is_definition_start) {
    end_node_id = node_parents_[end_node_id.index];
  }

  Lex::InclusiveTokenRange range = {
      .begin = sem_ir_->parse_tree().node_token(begin_node_id),
      .end = sem_ir_->parse_tree().node_token(end_node_id)};

Review comment (refactor):
Is it possible to move this into parse somewhere in a way that makes it clear that it needs to be defined as true/false when adding new kinds of Nodes, so that Check can then just query it off the NodeKind?

Code after:
    chunk.include_in_output = true;
    to_add.append(chunk.dependencies);
    chunk.dependencies.clear();
  }
}

auto Formatter::ShouldIncludeInstByIR(InstId inst_id) -> bool {
  const auto* import_ir = GetCanonicalFileAndInstId(sem_ir_, inst_id).first;
  return include_ir_in_dumps_[import_ir->check_ir_id().index];
}

// Returns true for a `DefinitionStart` node.
static auto IsDefinitionStart(Parse::NodeKind node_kind) -> bool {
  switch (node_kind) {
    case Parse::NodeKind::BuiltinFunctionDefinitionStart:
    case Parse::NodeKind::ChoiceDefinitionStart:
    case Parse::NodeKind::ClassDefinitionStart:
    case Parse::NodeKind::FunctionDefinitionStart:
    case Parse::NodeKind::ImplDefinitionStart:
    case Parse::NodeKind::InterfaceDefinitionStart:
    case Parse::NodeKind::NamedConstraintDefinitionStart:
      return true;
    default:
      return false;
  }
}

auto Formatter::ShouldFormatEntity(InstId decl_id) -> bool {
  if (!decl_id.has_value()) {
    return true;
  }
  if (!ShouldIncludeInstByIR(decl_id)) {
    return false;
  }

  if (!use_dump_sem_ir_ranges_) {
    return true;
  }

  // When there are dump ranges, ignore imported instructions.
  auto loc_id = sem_ir_->insts().GetCanonicalLocId(decl_id);
  if (loc_id.kind() != LocId::Kind::NodeId) {
    return false;
  }

  const auto& tree_and_subtrees = get_tree_and_subtrees_();

  // This takes the earliest token from either the node or its first postorder
  // child. The first postorder child isn't necessarily the earliest token in
  // the subtree (for example, it can miss modifiers), but finding the earliest
  // token requires walking *all* children, whereas this approach is