message: Skeletonize if statement
diff: @@ -31,27 +31,71 @@ function updateCode(code: Code, selection: Selection): ast.Transformed {
  const { alternate, consequent } = path.node;
  if (alternate) {
  - const nestedStatement = getNestedIfStatementIn(alternate);
  - if (!nestedStatement) return;
  + mergeAlternateWithNestedIf(path, alternate, selection);
  + } else {
  + mergeConsequentWithNestedIf(path, consequent, selection);
  + }
  + }
  + });
  +}
  +function mergeAlternateWithNestedIf(
  + path: ast.NodePath<ast.IfStatement>,
  + alternate: ast.IfStatement["alternate"],
  + selection: Selection
  +) {
  // Since we visit nodes from parent to children, first check
  // if a child would match the selection closer.
  if (hasAlternateChildWhichMatchesSelection(path, selection)) return;
  + if (!alternate) return;
  +
  + const nestedStatement = getNestedIfStatementIn(alternate);
  + if (!nestedStatement) return;
  +
  path.node.alternate = nestedStatement;
  - } else {
  - const nestedIfStatement = getNestedIfStatementIn(consequent);
  + path.stop();
  +}
  +
  +function hasAlternateChildWhichMatchesSelection(
  + path: ast.NodePath,
  + selection: Selection
  +): boolean {
  + let result = false;
  +
  + path.traverse({
  + IfStatement(childPath) {
  + if (!selection.isInsidePath(childPath)) return;
  +
  + const { alternate } = childPath.node;
  + if (!alternate) return;
  +
  + const nestedIfStatement = getNestedIfStatementIn(alternate);
  if (!nestedIfStatement) return;
  - if (nestedIfStatement.alternate) return;
  + result = true;
  + childPath.stop();
  + }
  + });
  +
  + return result;
  +}
  +
  +function mergeConsequentWithNestedIf(
  + path: ast.NodePath<ast.IfStatement>,
  + consequent: ast.IfStatement["consequent"],
  + selection: Selection
  +) {
  // Since we visit nodes from parent to children, first check
  // if a child would match the selection closer.
  if (hasConsequentChildWhichMatchesSelection(path, selection)) return;
  + const nestedIfStatement = getNestedIfStatementIn(consequent);
  + if (!nestedIfStatement) return;
  + if (nestedIfStatement.alternate) return;
  +
  const nestedConsequent = nestedIfStatement.consequent;
  - const nestedConsequentStatements = ast.isBlockStatement(
  - nestedConsequent
  - )
  + const nestedConsequentStatements = ast.isBlockStatement(nestedConsequent)
  ? nestedConsequent.body
  : [nestedConsequent];
  @@ -61,12 +105,9 @@ function updateCode(code: Code, selection: Selection): ast.Transformed {
  nestedIfStatement.test
  );
  path.node.consequent = ast.blockStatement(nestedConsequentStatements);
  - }
  path.stop();
  }
  - });
  -}
  function hasConsequentChildWhichMatchesSelection(
  path: ast.NodePath,
  @@ -93,30 +134,6 @@ function hasConsequentChildWhichMatchesSelection(
  return result;
  }
  -function hasAlternateChildWhichMatchesSelection(
  - path: ast.NodePath,
  - selection: Selection
  -): boolean {
  - let result = false;
  -
  - path.traverse({
  - IfStatement(childPath) {
  - if (!selection.isInsidePath(childPath)) return;
  -
  - const { alternate } = childPath.node;
  - if (!alternate) return;
  -
  - const nestedIfStatement = getNestedIfStatementIn(alternate);
  - if (!nestedIfStatement) return;
  -
  - result = true;
  - childPath.stop();
  - }
  - });
  -
  - return result;
  -}
  -
  function getNestedIfStatementIn(
  statement: ast.Statement
  ): ast.IfStatement | null {
  