src/language-js/print/statement.js/printStatementSequence
function printStatementSequence(path, options, print, property) {
  const node = path.getValue();
  const parts = [];
  const isClassBody = node.type === "ClassBody";
  const lastStatement = getLastStatement(node[property]);

  path.each((path, index, statements) => {
    const node = path.getValue();

    // Skip printing EmptyStatement nodes to avoid leaving stray
    // semicolons lying around.
    if (node.type === "EmptyStatement") {
      return;
    }

    const printed = print();

    // in no-semi mode, prepend statement with semicolon if it might break ASI
    // don't prepend the only JSX element in a program with semicolon
    if (
      !options.semi &&
      !isClassBody &&
      !isTheOnlyJsxElementInMarkdown(options, path) &&
      statementNeedsASIProtection(path, options)
    ) {
      if (hasComment(node, CommentCheckFlags.Leading)) {
        parts.push(print([], { needsSemi: true }));
      } else {
        parts.push(";", printed);
      }
    } else {
      parts.push(printed);
    }

    if (
      !options.semi &&
      isClassBody &&
      isClassProperty(node) &&
      // `ClassBody` don't allow `EmptyStatement`,
      // so we can use `statements` to get next node
      shouldPrintSemicolonAfterClassProperty(node, statements[index + 1])
    ) {
      parts.push(";");
    }

    if (node !== lastStatement) {
      parts.push(hardline);

      if (isNextLineEmpty(node, options)) {
        parts.push(hardline);
      }
    }
  }, property);

  return parts;
}