dist/ruby/nodes/conditionals.js in prettier-2.0.0 vs dist/ruby/nodes/conditionals.js in prettier-2.1.0

- old
+ new

@@ -14,13 +14,13 @@ ["if", "if_mod", "ifop", "unless", "unless_mod"].includes(stmts.body[0].type)); } function printWithAddition(keyword, path, print, breaking) { return [ `${keyword} `, - align(keyword.length + 1, path.call(print, "body", 0)), - indent([softline, path.call(print, "body", 1)]), - [softline, path.call(print, "body", 2)], + align(keyword.length + 1, path.call(print, "pred")), + indent([softline, path.call(print, "stmts")]), + [softline, path.call(print, "cons")], [softline, "end"], breaking ? breakParent : "" ]; } // For the unary `not` operator, we need to explicitly add parentheses to it in @@ -52,56 +52,59 @@ return keyword === "if" ? parts : parts.reverse(); } // Handles ternary nodes. If it does not fit on one line, then we break out into // an if/else statement. Otherwise we remain as a ternary. const printTernary = (path, _opts, print) => { - const [predicate, truthyClause, falsyClause] = path.map(print, "body"); - const ternaryClauses = printTernaryClauses("if", truthyClause, falsyClause); + const predicateDoc = path.call(print, "pred"); + const truthyDoc = path.call(print, "tthy"); + const falsyDoc = path.call(print, "flsy"); return group(ifBreak([ "if ", - align(3, predicate), - indent([softline, truthyClause]), + align(3, predicateDoc), + indent([softline, truthyDoc]), [softline, "else"], - indent([softline, falsyClause]), + indent([softline, falsyDoc]), [softline, "end"] - ], [predicate, " ? ", ...ternaryClauses])); + ], [predicateDoc, " ? ", ...printTernaryClauses("if", truthyDoc, falsyDoc)])); }; exports.printTernary = printTernary; +function isModifier(node) { + return node.type === "if_mod" || node.type === "unless_mod"; +} // Prints an `if_mod` or `unless_mod` node. Because it was previously in the // modifier form, we're guaranteed to not have an additional node, so we can // just work with the predicate and the body. -function printSingle(keyword, modifier = false) { +function printSingle(keyword) { return function printSingleWithKeyword(path, { rubyModifier }, print) { - const [, statementsNode] = path.getValue().body; - const predicateDoc = path.call(print, "body", 0); - const statementsDoc = path.call(print, "body", 1); + const node = path.getValue(); + const predicateDoc = path.call(print, "pred"); + const statementsDoc = path.call(print, isModifier(node) ? "stmt" : "stmts"); const multilineParts = [ `${keyword} `, align(keyword.length + 1, predicateDoc), indent([softline, statementsDoc]), softline, "end" ]; // If we do not allow modifier form conditionals or there are comments // inside of the body of the conditional, then we must print in the // multiline form. - if (!rubyModifier || - (!modifier && statementsNode.body[0].comments)) { + if (!rubyModifier || (!isModifier(node) && node.stmts.body[0].comments)) { return [multilineParts, breakParent]; } const inline = (0, utils_1.inlineEnsureParens)(path, [ - path.call(print, "body", 1), + statementsDoc, ` ${keyword} `, - path.call(print, "body", 0) + predicateDoc ]); - // An expression with a conditional modifier (expression if true), the + // With an expression with a conditional modifier (expression if true), the // conditional body is parsed before the predicate expression, meaning that // if the parser encountered a variable declaration, it would initialize // that variable first before evaluating the predicate expression. That // parse order means the difference between a NameError or not. #591 // https://docs.ruby-lang.org/en/2.0.0/syntax/control_expressions_rdoc.html#label-Modifier+if+and+unless - if (modifier && (0, utils_1.containsAssignment)(statementsNode)) { + if (isModifier(node) && (0, utils_1.containsAssignment)(node.stmt)) { return inline; } return group(ifBreak(multilineParts, inline)); }; } @@ -142,11 +145,11 @@ return false; } const stmt = stmts.body[0]; // If the user is using one of the lower precedence "and" or "or" operators, // then we can't use a ternary expression as it would break the flow control. - if (stmt.type === "binary" && ["and", "or"].includes(stmt.body[1])) { + if (stmt.type === "binary" && ["and", "or"].includes(stmt.op)) { return false; } // Check against the blocklist of statement types that are not allowed to be // a part of a ternary expression. return !noTernary.includes(stmt.type); @@ -155,88 +158,89 @@ // there has to be one and only one "addition" (another clause attached) which // is of the "else" type. Both the body of the main node and the body of the // additional node must have only one statement, and that statement list must // pass the `canTernaryStmts` check. function canTernary(path) { - const [predicate, stmts, addition] = path.getValue().body; - return (!["assign", "opassign", "command_call", "command"].includes(predicate.type) && - addition && - addition.type === "else" && - [stmts, addition.body[0]].every(canTernaryStmts)); + const node = path.getValue(); + return (!["assign", "opassign", "command_call", "command"].includes(node.pred.type) && + node.cons && + node.cons.type === "else" && + canTernaryStmts(node.stmts) && + canTernaryStmts(node.cons.stmts)); } // A normalized print function for both `if` and `unless` nodes. function printConditional(keyword) { - return (path, opts, print) => { + return function printConditionalWithKeyword(path, opts, print) { if (canTernary(path)) { let ternaryParts = [ - path.call(print, "body", 0), + path.call(print, "pred"), " ? ", - ...printTernaryClauses(keyword, path.call(print, "body", 1), path.call(print, "body", 2, "body", 0)) + ...printTernaryClauses(keyword, path.call(print, "stmts"), path.call(print, "cons", "stmts")) ]; if (["binary", "call"].includes(path.getParentNode().type)) { ternaryParts = ["(", ...ternaryParts, ")"]; } return group(ifBreak(printWithAddition(keyword, path, print, false), ternaryParts)); } - const [predicate, statements, addition] = path.getValue().body; + const node = path.getValue(); // If there's an additional clause that wasn't matched earlier, we know we // can't go for the inline option. - if (addition) { + if (node.cons) { return group(printWithAddition(keyword, path, print, true)); } - // If the body of the conditional is empty, then we explicitly have to use the - // block form. - if ((0, utils_1.isEmptyStmts)(statements)) { + // If the body of the conditional is empty, then we explicitly have to use + // the block form. + if ((0, utils_1.isEmptyStmts)(node.stmts)) { return [ `${keyword} `, - align(keyword.length + 1, path.call(print, "body", 0)), + align(keyword.length + 1, path.call(print, "pred")), hardline, "end" ]; } // Two situations in which we need to use the block form: // - // 1. If the predicate of the conditional contains an assignment, then we can't - // know for sure that it doesn't impact the body of the conditional. + // 1. If the predicate of the conditional contains an assignment, then we + // can't know for sure that it doesn't impact the body of the conditional. // - // 2. If the conditional contains just another conditional, then collapsing it - // would result in double modifiers on the same line. - if ((0, utils_1.containsAssignment)(predicate) || - containsSingleConditional(statements)) { + // 2. If the conditional contains just another conditional, then collapsing + // it would result in double modifiers on the same line. + if ((0, utils_1.containsAssignment)(node.pred) || + containsSingleConditional(node.stmts)) { return [ `${keyword} `, - align(keyword.length + 1, path.call(print, "body", 0)), - indent([hardline, path.call(print, "body", 1)]), + align(keyword.length + 1, path.call(print, "pred")), + indent([hardline, path.call(print, "stmts")]), hardline, "end" ]; } return printSingle(keyword)(path, opts, print); }; } const printElse = (path, opts, print) => { - const stmts = path.getValue().body[0]; + const node = path.getValue(); return [ - stmts.body.length === 1 && stmts.body[0].type === "command" + node.stmts.body.length === 1 && node.stmts.body[0].type === "command" ? breakParent : "", "else", - indent([softline, path.call(print, "body", 0)]) + indent([softline, path.call(print, "stmts")]) ]; }; exports.printElse = printElse; const printElsif = (path, opts, print) => { - const [, , addition] = path.getValue().body; + const node = path.getValue(); const parts = [ - group(["elsif ", align("elsif".length - 1, path.call(print, "body", 0))]), - indent([hardline, path.call(print, "body", 1)]) + group(["elsif ", align("elsif".length - 1, path.call(print, "pred"))]), + indent([hardline, path.call(print, "stmts")]) ]; - if (addition) { - parts.push(group([hardline, path.call(print, "body", 2)])); + if (node.cons) { + parts.push(group([hardline, path.call(print, "cons")])); } return group(parts); }; exports.printElsif = printElsif; exports.printIf = printConditional("if"); -exports.printIfModifier = printSingle("if", true); +exports.printIfModifier = printSingle("if"); exports.printUnless = printConditional("unless"); -exports.printUnlessModifier = printSingle("unless", true); +exports.printUnlessModifier = printSingle("unless");