src/nodes/hashes.js in prettier-0.20.1 vs src/nodes/hashes.js in prettier-0.21.0

- old
+ new

@@ -5,22 +5,13 @@ indent, join, line, literalline } = require("../prettier"); -const { prefix, skipAssignIndent } = require("../utils"); -const nodeDive = (node, steps) => { - let current = node; +const { nodeDive, prefix, skipAssignIndent } = require("../utils"); - steps.forEach((step) => { - current = current[step]; - }); - - return current; -}; - // When attempting to convert a hash rocket into a hash label, you need to take // care because only certain patterns are allowed. Ruby source says that they // have to match keyword arguments to methods, but don't specify what that is. // After some experimentation, it looks like it's: // @@ -63,10 +54,49 @@ default: return concat([labelDoc, " =>"]); } }; +function printHash(path, { addTrailingCommas }, print) { + const hashNode = path.getValue(); + + // Hashes normally have a single assoclist_from_args child node. If it's + // missing, then it means we're dealing with an empty hash, so we can just + // exit here and print. + if (hashNode.body[0] === null) { + return "{}"; + } + + // Here we get a reference to the printed assoclist_from_args child node, + // which handles printing all of the key-value pairs of the hash. We're + // wrapping it in an array in case we need to append a trailing comma. + const assocDocs = [path.call(print, "body", 0)]; + + // Here we get a reference to the last key-value pair's value node, in order + // to check if we're dealing with a heredoc. If we are, then the trailing + // comma printing is handled from within the assoclist_from_args node + // printing, because the trailing comma has to go after the heredoc + // declaration. + const assocNodes = hashNode.body[0].body[0]; + const lastAssocValueNode = assocNodes[assocNodes.length - 1].body[1]; + + // If we're adding a trailing comma and the last key-value pair's value node + // is not a heredoc node, then we can safely append the extra comma if the + // hash ends up getting printed on multiple lines. + if (addTrailingCommas && lastAssocValueNode.type !== "heredoc") { + assocDocs.push(ifBreak(",", "")); + } + + return group( + concat([ + "{", + indent(concat([line, concat(assocDocs)])), + concat([line, "}"]) + ]) + ); +} + module.exports = { assoc_new: (path, opts, print) => { const valueDoc = path.call(print, "body", 1); const parts = [makeLabel(path, opts, print, ["body", 0])]; @@ -87,61 +117,31 @@ assocNodes.forEach((assocNode, index) => { const isInner = index !== assocNodes.length - 1; const valueNode = assocNode.body[1]; - const isStraightHeredoc = valueNode && valueNode.type === "heredoc"; - const isSquigglyHeredoc = - valueNode && - valueNode.type === "string_literal" && - valueNode.body[0].type === "heredoc"; - - if (isStraightHeredoc || isSquigglyHeredoc) { - const heredocSteps = isStraightHeredoc - ? ["body", 1] - : ["body", 1, "body", 0]; - const { beging, ending } = nodeDive(assocNode, heredocSteps); - + if (valueNode && valueNode.type === "heredoc") { assocDocs.push( makeLabel(path, opts, print, ["body", 0, index, "body", 0]), " ", - beging, + valueNode.beging, isInner || addTrailingCommas ? "," : "", literalline, - concat( - path.map.apply( - path, - [print, "body", 0, index].concat(heredocSteps).concat("body") - ) - ), - ending, + concat(path.map(print, "body", 0, index, "body", 1, "body")), + valueNode.ending, isInner ? line : "" ); } else { assocDocs.push(path.call(print, "body", 0, index)); if (isInner) { assocDocs.push(concat([",", line])); - } else if (addTrailingCommas) { - assocDocs.push(ifBreak(",", "")); } } }); return group(concat(assocDocs)); }, bare_assoc_hash: (path, opts, print) => group(join(concat([",", line]), path.map(print, "body", 0))), - hash: (path, opts, print) => { - if (path.getValue().body[0] === null) { - return "{}"; - } - - return group( - concat([ - "{", - indent(concat([line, concat(path.map(print, "body"))])), - concat([line, "}"]) - ]) - ); - } + hash: printHash };