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
};