"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function isCall(node) { // Older versions of Ruby didn't have a @period ripper event, so we need to // explicitly cast to any here. if (node === "::" || node === ".") { return true; } return node.type === "@period"; } // If you have a simple block that only calls a method on the single required // parameter that is passed to it, then you can replace that block with the // simpler `Symbol#to_proc`. Meaning, it would go from: // // [1, 2, 3].map { |i| i.to_s } // // to: // // [1, 2, 3].map(&:to_s) // // This works with `do` blocks as well. function toProc(path, node) { const [variables, blockContents] = node.body; // Ensure that there are variables being passed to this block. const params = variables && variables.body[0]; if (!params) { return null; } // Ensure there is one and only one parameter, and that it is required. const reqParams = params.body[0]; const otherParams = params.body.slice(1); if (!Array.isArray(reqParams) || reqParams.length !== 1 || otherParams.some(Boolean)) { return null; } let statements; if (blockContents.type === "bodystmt") { // We’re in a `do` block const blockStatements = blockContents.body[0]; const rescueElseEnsure = blockContents.body.slice(1); // You can’t use the to_proc shortcut if you’re rescuing if (rescueElseEnsure.some(Boolean)) { return null; } statements = blockStatements; } else { // We’re in a brace block statements = blockContents; } // Ensure the block contains only one statement if (statements.body.length !== 1) { return null; } // Ensure that statement is a call and that it has no comments attached const [statement] = statements.body; if (statement.type !== "call" || statement.comments) { return null; } // Ensure the call is a method of the block argument const [varRef, call, method] = statement.body; if (varRef.type !== "var_ref" || varRef.body[0].body !== reqParams[0].body || !isCall(call) || method === "call" || method.type !== "@ident") { return null; } // Ensure that we're not inside of a hash that is being passed to a key that // corresponds to `:if` or `:unless` to avoid problems with callbacks with // Rails. For more context, see: // https://github.com/prettier/plugin-ruby/issues/449 let assocNode = null; if (path.getValue().type === "method_add_block") { assocNode = path.getParentNode(); } else { assocNode = path.getParentNode(2); } if (assocNode && assocNode.type === "assoc_new") { const [key] = assocNode.body; if (key.type === "@label" && ["if:", "unless:"].includes(key.body)) { return null; } if (key.type === "symbol_literal" && ["if", "unless"].includes(key.body[0].body)) { return null; } } return `&:${method.body}`; } exports.default = toProc;