From 7cc52da144a31ddce4ff29b37a8ae3107e58e44c Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 22 Mar 2021 22:57:03 +0800 Subject: [PATCH] Simplified `printGenerically` (#10557) Co-authored-by: Georgii Dolzhykov --- changelog_unreleased/api/10557.md | 35 ++++ docs/plugins.md | 17 +- src/language-css/printer-postcss.js | 38 ++-- src/language-graphql/printer-graphql.js | 96 +++++----- src/language-handlebars/printer-glimmer.js | 18 +- src/language-html/printer-html.js | 4 +- src/language-js/print/angular.js | 22 +-- src/language-js/print/array.js | 4 +- src/language-js/print/assignment.js | 16 +- src/language-js/print/binaryish.js | 8 +- src/language-js/print/block.js | 2 +- src/language-js/print/call-arguments.js | 18 +- src/language-js/print/call-expression.js | 8 +- src/language-js/print/class.js | 12 +- src/language-js/print/flow.js | 16 +- src/language-js/print/function-parameters.js | 2 +- src/language-js/print/function.js | 31 ++-- src/language-js/print/interface.js | 8 +- src/language-js/print/jsx.js | 60 ++---- src/language-js/print/member-chain.js | 2 +- src/language-js/print/member.js | 4 +- src/language-js/print/misc.js | 10 +- src/language-js/print/module.js | 16 +- src/language-js/print/object.js | 2 +- src/language-js/print/property.js | 8 +- src/language-js/print/statement.js | 4 +- src/language-js/print/template-literal.js | 4 +- src/language-js/print/ternary.js | 24 +-- src/language-js/print/type-annotation.js | 24 +-- src/language-js/print/type-parameters.js | 18 +- src/language-js/print/typescript.js | 120 +++++------- src/language-js/printer-estree-json.js | 14 +- src/language-js/printer-estree.js | 175 ++++++++---------- src/language-markdown/printer-markdown.js | 14 +- src/language-yaml/print/block.js | 2 +- .../print/flow-mapping-sequence.js | 2 +- src/language-yaml/print/mapping-item.js | 4 +- src/language-yaml/printer-yaml.js | 31 ++-- src/main/ast-to-doc.js | 124 +++++++------ 39 files changed, 483 insertions(+), 534 deletions(-) create mode 100644 changelog_unreleased/api/10557.md diff --git a/changelog_unreleased/api/10557.md b/changelog_unreleased/api/10557.md new file mode 100644 index 000000000..3e2afefcb --- /dev/null +++ b/changelog_unreleased/api/10557.md @@ -0,0 +1,35 @@ +#### Simplified `print` callback (#10557 by @fisker) + +The third argument of the `print` method of plugin printers (the `print` callback) has been updated. Its first argument can be a string or an array of strings now. + +To print the current node, call `print` without arguments: + +```diff + function print(path, options, print) { + const parts = []; + path.each((childPath) => { +- parts.push(print(childPath)); ++ parts.push(print()); + }, "children"); + return parts; + } +``` + +To print a property of the current node, use `"property"` or `["property"]`: + +```diff + function print(path, options, print) { +- return path.call(print, "property"); ++ return print("property"); + } +``` + +To print a sub-property of the current node, use `["property1", "property2"]`: + +```diff + function print(path, options, print) { + // print `node.child.child` +- return path.call(print, "child", "child"); ++ return print(["child", "child"]); + } +``` diff --git a/docs/plugins.md b/docs/plugins.md index 52b710b82..201d386b1 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -176,21 +176,28 @@ function print( path: AstPath, options: object, // Recursively print a child node - print: (path: AstPath) => Doc + print: (selector?: string | number | Array | AstPath) => Doc ): Doc; ``` -The `print` function is passed a `path` object, which can be used to access nodes in the AST via `path.getValue()`. It is also passed a persistent `options` object (which contains global options and which a plugin may mutate), and a `print` function used for making recursive calls. A basic `print` function might be as follows: +The `print` function is passed the following parameters: + +- **`path`**: An object, which can be used to access nodes in the AST. It’s a stack-like data structure that maintains the current state of the recursion. It is called “path” because it represents the path to the current node from the root of the AST. The current node is returned by `path.getValue()`. +- **`options`**: A persistent object, which contains global options and which a plugin may mutate to store contextual data. +- **`print`**: A callback for printing sub-nodes. This function contains the core printing logic that consists of steps whose implementation is provided by plugins. In particular, it calls the printer’s `print` function and passes itself to it. Thus, the two `print` functions – the one from the core and the one from the plugin – call each other while descending down the AST recursively. + +Here’s a simplified example to give an idea of what a typical implementation of `print` looks like: ```js -const { builders } = require("prettier").doc; +const { join } = require("prettier").doc.builders; function print(path, options, print) { const node = path.getValue(); if (Array.isArray(node)) { - return builders.concat(path.map(print)); + return join(", ", path.map(print)); } + return node.value; } ``` @@ -206,7 +213,7 @@ function embed( // Path to the current AST node path: AstPath, // Print a node with the current printer - print: (path: AstPath) => Doc, + print: (selector?: string | number | Array | AstPath) => Doc, // Parse and print some text using a different parser. // You should set `options.parser` to specify which parser to use. textToDoc: (text: string, options: object) => Doc, diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js index 04a444456..11632ceed 100644 --- a/src/language-css/printer-postcss.js +++ b/src/language-css/printer-postcss.js @@ -115,7 +115,7 @@ function genericPrint(path, options, print) { } case "css-rule": { return [ - path.call(print, "selector"), + print("selector"), node.important ? " !important" : "", node.nodes ? [ @@ -143,8 +143,8 @@ function genericPrint(path, options, print) { const isColon = trimmedBetween === ":"; let value = hasComposesNode(node) - ? removeLines(path.call(print, "value")) - : path.call(print, "value"); + ? removeLines(print("value")) + : print("value"); if (!isColon && lastLineHasInlineComment(trimmedBetween)) { value = indent([hardline, dedent(value)]); @@ -157,7 +157,7 @@ function genericPrint(path, options, print) { trimmedBetween, node.extend ? "" : " ", isLessParser(options) && node.extend && node.selector - ? ["extend(", path.call(print, "selector"), ")"] + ? ["extend(", print("selector"), ")"] : "", value, node.raws.important @@ -201,7 +201,7 @@ function genericPrint(path, options, print) { if (isLessParser(options)) { if (node.mixin) { return [ - path.call(print, "selector"), + print("selector"), node.important ? " !important" : "", isTemplatePlaceholderNodeWithoutSemiColon ? "" : ";", ]; @@ -210,7 +210,7 @@ function genericPrint(path, options, print) { if (node.function) { return [ node.name, - path.call(print, "params"), + print("params"), isTemplatePlaceholderNodeWithoutSemiColon ? "" : ";", ]; } @@ -220,7 +220,7 @@ function genericPrint(path, options, print) { "@", node.name, ": ", - node.value ? path.call(print, "value") : "", + node.value ? print("value") : "", node.raws.between.trim() ? node.raws.between.trim() + " " : "", node.nodes ? [ @@ -261,14 +261,14 @@ function genericPrint(path, options, print) { ? hardline : " " : " ", - path.call(print, "params"), + print("params"), ] : "", - node.selector ? indent([" ", path.call(print, "selector")]) : "", + node.selector ? indent([" ", print("selector")]) : "", node.value ? group([ " ", - path.call(print, "value"), + print("value"), isSCSSControlDirectiveNode(node) ? hasParensAroundNode(node) ? " " @@ -312,7 +312,7 @@ function genericPrint(path, options, print) { if (node.type === "media-query" && node.value === "") { return; } - parts.push(print(childPath)); + parts.push(print()); }, "nodes"); return group(indent(join(line, parts))); @@ -505,7 +505,7 @@ function genericPrint(path, options, print) { // postcss-values-parser case "value-value": case "value-root": { - return path.call(print, "group"); + return print("group"); } case "value-comment": { return options.originalText.slice(locStart(node), locEnd(node)); @@ -834,9 +834,9 @@ function genericPrint(path, options, print) { node.groups[0].groups[0].value.startsWith("data:"))) ) { return [ - node.open ? path.call(print, "open") : "", + node.open ? print("open") : "", join(",", path.map(print, "groups")), - node.close ? path.call(print, "close") : "", + node.close ? print("close") : "", ]; } @@ -862,14 +862,14 @@ function genericPrint(path, options, print) { const printed = group( [ - node.open ? path.call(print, "open") : "", + node.open ? print("open") : "", indent([ softline, join( [",", line], path.map((childPath) => { const node = childPath.getValue(); - const printed = print(childPath); + const printed = print(); // Key/Value pair in open paren already indented if ( @@ -899,7 +899,7 @@ function genericPrint(path, options, print) { : "" ), softline, - node.close ? path.call(print, "close") : "", + node.close ? print("close") : "", ], { shouldBreak: isSCSSMapItem && !isKey, @@ -914,7 +914,7 @@ function genericPrint(path, options, print) { insideAtRuleNode(path, "supports") && isMediaAndSupportsKeywords(node) ? " " : "", - path.call(print, "group"), + print("group"), ]; } case "value-paren": { @@ -989,7 +989,7 @@ function printNodeSequence(path, options, print) { options.originalText.slice(locStart(childNode), locEnd(childNode)) ); } else { - parts.push(print(pathChild)); + parts.push(print()); } if (i !== nodes.length - 1) { diff --git a/src/language-graphql/printer-graphql.js b/src/language-graphql/printer-graphql.js index a8bee421f..4e34eab8f 100644 --- a/src/language-graphql/printer-graphql.js +++ b/src/language-graphql/printer-graphql.js @@ -21,7 +21,7 @@ function genericPrint(path, options, print) { case "Document": { const parts = []; path.each((pathChild, index, definitions) => { - parts.push(print(pathChild)); + parts.push(print()); if (index !== definitions.length - 1) { parts.push(hardline); if ( @@ -38,7 +38,7 @@ function genericPrint(path, options, print) { const hasName = Boolean(node.name); return [ hasOperation ? node.operation : "", - hasOperation && hasName ? [" ", path.call(print, "name")] : "", + hasOperation && hasName ? [" ", print("name")] : "", isNonEmptyArray(node.variableDefinitions) ? group([ "(", @@ -55,13 +55,13 @@ function genericPrint(path, options, print) { : "", printDirectives(path, print, node), node.selectionSet ? (!hasOperation && !hasName ? "" : " ") : "", - path.call(print, "selectionSet"), + print("selectionSet"), ]; } case "FragmentDefinition": { return [ "fragment ", - path.call(print, "name"), + print("name"), isNonEmptyArray(node.variableDefinitions) ? group([ "(", @@ -77,10 +77,10 @@ function genericPrint(path, options, print) { ]) : "", " on ", - path.call(print, "typeCondition"), + print("typeCondition"), printDirectives(path, print, node), " ", - path.call(print, "selectionSet"), + print("selectionSet"), ]; } case "SelectionSet": { @@ -102,8 +102,8 @@ function genericPrint(path, options, print) { } case "Field": { return group([ - node.alias ? [path.call(print, "alias"), ": "] : "", - path.call(print, "name"), + node.alias ? [print("alias"), ": "] : "", + print("name"), node.arguments.length > 0 ? group([ "(", @@ -123,7 +123,7 @@ function genericPrint(path, options, print) { : "", printDirectives(path, print, node), node.selectionSet ? " " : "", - path.call(print, "selectionSet"), + print("selectionSet"), ]); } case "Name": { @@ -157,7 +157,7 @@ function genericPrint(path, options, print) { return "null"; } case "Variable": { - return ["$", path.call(print, "name")]; + return ["$", print("name")]; } case "ListValue": { return group([ @@ -188,13 +188,13 @@ function genericPrint(path, options, print) { } case "ObjectField": case "Argument": { - return [path.call(print, "name"), ": ", path.call(print, "value")]; + return [print("name"), ": ", print("value")]; } case "Directive": { return [ "@", - path.call(print, "name"), + print("name"), node.arguments.length > 0 ? group([ "(", @@ -216,15 +216,15 @@ function genericPrint(path, options, print) { } case "NamedType": { - return path.call(print, "name"); + return print("name"); } case "VariableDefinition": { return [ - path.call(print, "variable"), + print("variable"), ": ", - path.call(print, "type"), - node.defaultValue ? [" = ", path.call(print, "defaultValue")] : "", + print("type"), + node.defaultValue ? [" = ", print("defaultValue")] : "", printDirectives(path, print, node), ]; } @@ -232,11 +232,11 @@ function genericPrint(path, options, print) { case "ObjectTypeExtension": case "ObjectTypeDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", node.kind === "ObjectTypeExtension" ? "extend " : "", "type ", - path.call(print, "name"), + print("name"), node.interfaces.length > 0 ? [" implements ", ...printInterfaces(path, options, print)] : "", @@ -263,9 +263,9 @@ function genericPrint(path, options, print) { case "FieldDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", - path.call(print, "name"), + print("name"), node.arguments.length > 0 ? group([ "(", @@ -284,18 +284,18 @@ function genericPrint(path, options, print) { ]) : "", ": ", - path.call(print, "type"), + print("type"), printDirectives(path, print, node), ]; } case "DirectiveDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", "directive ", "@", - path.call(print, "name"), + print("name"), node.arguments.length > 0 ? group([ "(", @@ -322,11 +322,11 @@ function genericPrint(path, options, print) { case "EnumTypeExtension": case "EnumTypeDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", node.kind === "EnumTypeExtension" ? "extend " : "", "enum ", - path.call(print, "name"), + print("name"), printDirectives(path, print, node), node.values.length > 0 @@ -351,21 +351,21 @@ function genericPrint(path, options, print) { case "EnumValueDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", - path.call(print, "name"), + print("name"), printDirectives(path, print, node), ]; } case "InputValueDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? (node.description.block ? hardline : line) : "", - path.call(print, "name"), + print("name"), ": ", - path.call(print, "type"), - node.defaultValue ? [" = ", path.call(print, "defaultValue")] : "", + print("type"), + node.defaultValue ? [" = ", print("defaultValue")] : "", printDirectives(path, print, node), ]; } @@ -373,11 +373,11 @@ function genericPrint(path, options, print) { case "InputObjectTypeExtension": case "InputObjectTypeDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", node.kind === "InputObjectTypeExtension" ? "extend " : "", "input ", - path.call(print, "name"), + print("name"), printDirectives(path, print, node), node.fields.length > 0 ? [ @@ -422,17 +422,17 @@ function genericPrint(path, options, print) { } case "OperationTypeDefinition": { - return [path.call(print, "operation"), ": ", path.call(print, "type")]; + return [print("operation"), ": ", print("type")]; } case "InterfaceTypeExtension": case "InterfaceTypeDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", node.kind === "InterfaceTypeExtension" ? "extend " : "", "interface ", - path.call(print, "name"), + print("name"), node.interfaces.length > 0 ? [" implements ", ...printInterfaces(path, options, print)] : "", @@ -458,32 +458,28 @@ function genericPrint(path, options, print) { } case "FragmentSpread": { - return [ - "...", - path.call(print, "name"), - printDirectives(path, print, node), - ]; + return ["...", print("name"), printDirectives(path, print, node)]; } case "InlineFragment": { return [ "...", - node.typeCondition ? [" on ", path.call(print, "typeCondition")] : "", + node.typeCondition ? [" on ", print("typeCondition")] : "", printDirectives(path, print, node), " ", - path.call(print, "selectionSet"), + print("selectionSet"), ]; } case "UnionTypeExtension": case "UnionTypeDefinition": { return group([ - path.call(print, "description"), + print("description"), node.description ? hardline : "", group([ node.kind === "UnionTypeExtension" ? "extend " : "", "union ", - path.call(print, "name"), + print("name"), printDirectives(path, print, node), node.types.length > 0 ? [ @@ -502,21 +498,21 @@ function genericPrint(path, options, print) { case "ScalarTypeExtension": case "ScalarTypeDefinition": { return [ - path.call(print, "description"), + print("description"), node.description ? hardline : "", node.kind === "ScalarTypeExtension" ? "extend " : "", "scalar ", - path.call(print, "name"), + print("name"), printDirectives(path, print, node), ]; } case "NonNullType": { - return [path.call(print, "type"), "!"]; + return [print("type"), "!"]; } case "ListType": { - return ["[", path.call(print, "type"), "]"]; + return ["[", print("type"), "]"]; } default: @@ -546,7 +542,7 @@ function printSequence(sequencePath, options, print) { const count = sequencePath.getValue().length; return sequencePath.map((path, i) => { - const printed = print(path); + const printed = print(); if ( isNextLineEmpty(options.originalText, path.getValue(), locEnd) && diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js index f15a231ba..b01e12796 100644 --- a/src/language-handlebars/printer-glimmer.js +++ b/src/language-handlebars/printer-glimmer.js @@ -179,7 +179,7 @@ function print(path, options, print) { ).quote : ""; - const valueDoc = path.call(print, "value"); + const valueDoc = print("value"); return [ node.name, @@ -198,7 +198,7 @@ function print(path, options, print) { return join(line, path.map(print, "pairs")); } case "HashPair": { - return [node.key, "=", path.call(print, "value")]; + return [node.key, "=", print("value")]; } case "TextNode": { /* if `{{my-component}}` (or any text containing "{{") @@ -460,7 +460,7 @@ function printChildren(path, options, print) { } return path.map((childPath, childIndex) => { - const printedChild = print(childPath, options, print); + const printedChild = print(); if (childIndex === 0 && options.htmlWhitespaceSensitivity === "ignore") { return [softline, printedChild]; @@ -587,14 +587,14 @@ function printCloseBlock(path, print, options) { return [ escape, printClosingBlockOpeningMustache(node), - path.call(print, "path"), + print("path"), printClosingBlockClosingMustache(node), ]; } return [ printClosingBlockOpeningMustache(node), - path.call(print, "path"), + print("path"), printClosingBlockClosingMustache(node), ]; } @@ -626,7 +626,7 @@ function printProgram(path, print, options) { return ""; } - const program = path.call(print, "program"); + const program = print("program"); if (options.htmlWhitespaceSensitivity === "ignore") { return indent([hardline, program]); @@ -638,7 +638,7 @@ function printProgram(path, print, options) { function printInverse(path, print, options) { const node = path.getValue(); - const inverse = path.call(print, "inverse"); + const inverse = print("inverse"); const printed = options.htmlWhitespaceSensitivity === "ignore" ? [hardline, inverse] @@ -768,7 +768,7 @@ function printPathAndParams(path, print) { } function printPath(path, print) { - return path.call(print, "path"); + return print("path"); } function printParams(path, print) { @@ -781,7 +781,7 @@ function printParams(path, print) { } if (node.hash && node.hash.pairs.length > 0) { - const hash = path.call(print, "hash"); + const hash = print("hash"); parts.push(hash); } diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index fa4930359..553329d0f 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -546,7 +546,7 @@ function printChildren(path, options, print) { ]; } - return print(childPath); + return print(); } function printBetweenLine(prevNode, nextNode) { @@ -666,7 +666,7 @@ function printAttributes(path, options, print) { options.originalText.slice(locStart(attribute), locEnd(attribute)), literalline ) - : print(attributePath); + : print(); }, "attrs"); const forceNotToBreakAttrContent = diff --git a/src/language-js/print/angular.js b/src/language-js/print/angular.js index f4a8bb754..aac03f3ec 100644 --- a/src/language-js/print/angular.js +++ b/src/language-js/print/angular.js @@ -13,7 +13,7 @@ function printAngular(path, options, print) { switch (node.type) { case "NGRoot": return [ - path.call(print, "node"), + print("node"), !hasComment(node.node) ? "" : " //" + getComments(node.node)[0].value.trimEnd(), @@ -26,9 +26,7 @@ function printAngular(path, options, print) { [";", line], path.map( (childPath) => - hasNgSideEffect(childPath) - ? print(childPath) - : ["(", print(childPath), ")"], + hasNgSideEffect(childPath) ? print() : ["(", print(), ")"], "expressions" ) ) @@ -45,7 +43,7 @@ function printAngular(path, options, print) { : isNgForOf(childPath.getValue(), index, node) ? " " : [";", line], - print(childPath), + print(), ], "body" ); @@ -55,8 +53,8 @@ function printAngular(path, options, print) { : JSON.stringify(node.name); case "NGMicrosyntaxExpression": return [ - path.call(print, "expression"), - node.alias === null ? "" : [" as ", path.call(print, "alias")], + print("expression"), + node.alias === null ? "" : [" as ", print("alias")], ]; case "NGMicrosyntaxKeyedExpression": { const index = path.getName(); @@ -72,19 +70,19 @@ function printAngular(path, options, print) { parentNode.body[index - 1].key.name === "then")) && parentNode.body[0].type === "NGMicrosyntaxExpression"); return [ - path.call(print, "key"), + print("key"), shouldNotPrintColon ? " " : ": ", - path.call(print, "expression"), + print("expression"), ]; } case "NGMicrosyntaxLet": return [ "let ", - path.call(print, "key"), - node.value === null ? "" : [" = ", path.call(print, "value")], + print("key"), + node.value === null ? "" : [" = ", print("value")], ]; case "NGMicrosyntaxAs": - return [path.call(print, "key"), " as ", path.call(print, "alias")]; + return [print("key"), " as ", print("alias")]; } } diff --git a/src/language-js/print/array.js b/src/language-js/print/array.js index 0f06dae53..5d07163b5 100644 --- a/src/language-js/print/array.js +++ b/src/language-js/print/array.js @@ -147,7 +147,7 @@ function printArrayItems(path, options, printPath, print) { let separatorParts = []; path.each((childPath) => { - printedElements.push(separatorParts, group(print(childPath))); + printedElements.push(separatorParts, group(print())); separatorParts = [",", line]; if ( @@ -167,7 +167,7 @@ function printArrayItemsConcisely(path, options, print, trailingComma) { path.each((childPath, i, elements) => { const isLast = i === elements.length - 1; - parts.push([print(childPath), isLast ? trailingComma : ","]); + parts.push([print(), isLast ? trailingComma : ","]); if (!isLast) { parts.push( diff --git a/src/language-js/print/assignment.js b/src/language-js/print/assignment.js index 139a7e3a7..a72c952ae 100644 --- a/src/language-js/print/assignment.js +++ b/src/language-js/print/assignment.js @@ -27,10 +27,7 @@ function printAssignment( ) { const layout = chooseLayout(path, options, leftDoc, rightPropertyName); - const rightDoc = path.call( - (p) => print(p, { assignmentLayout: layout }), - rightPropertyName - ); + const rightDoc = print(rightPropertyName, { assignmentLayout: layout }); switch (layout) { // First break after operator, then the sides are broken independently on their own lines @@ -74,21 +71,14 @@ function printAssignmentExpression(path, options, print) { path, options, print, - path.call(print, "left"), + print("left"), [" ", node.operator], "right" ); } function printVariableDeclarator(path, options, print) { - return printAssignment( - path, - options, - print, - path.call(print, "id"), - " =", - "init" - ); + return printAssignment(path, options, print, print("id"), " =", "init"); } function chooseLayout(path, options, leftDoc, rightPropertyName) { diff --git a/src/language-js/print/binaryish.js b/src/language-js/print/binaryish.js index 01848d327..632b14829 100644 --- a/src/language-js/print/binaryish.js +++ b/src/language-js/print/binaryish.js @@ -217,7 +217,7 @@ function printBinaryishExpressions( ), ]; } else { - parts.push(group(path.call(print, "left"))); + parts.push(group(print("left"))); } const shouldInline = shouldInlineLogicalExpression(node); @@ -243,12 +243,12 @@ function printBinaryishExpressions( : ""; const right = shouldInline - ? [operator, " ", path.call(print, "right"), rightSuffix] + ? [operator, " ", print("right"), rightSuffix] : [ lineBeforeOperator ? line : "", operator, lineBeforeOperator ? " " : line, - path.call(print, "right"), + print("right"), rightSuffix, ]; @@ -285,7 +285,7 @@ function printBinaryishExpressions( } } else { // Our stopping case. Simply print the node normally. - parts.push(group(print(path))); + parts.push(group(print())); } return parts; diff --git a/src/language-js/print/block.js b/src/language-js/print/block.js index 46c5f714f..d120564a2 100644 --- a/src/language-js/print/block.js +++ b/src/language-js/print/block.js @@ -75,7 +75,7 @@ function printBlockBody(path, options, print) { // Babel 6 if (nodeHasDirectives) { path.each((childPath, index, directives) => { - parts.push(print(childPath)); + parts.push(print()); if (index < directives.length - 1 || nodeHasBody || nodeHasComment) { parts.push(hardline); if (isNextLineEmpty(childPath.getValue(), options)) { diff --git a/src/language-js/print/call-arguments.js b/src/language-js/print/call-arguments.js index 77e5aa492..d87bf8b1b 100644 --- a/src/language-js/print/call-arguments.js +++ b/src/language-js/print/call-arguments.js @@ -48,13 +48,7 @@ function printCallArguments(path, options, print) { // useEffect(() => { ... }, [foo, bar, baz]) if (isReactHookCallWithDepsArray(args)) { - return [ - "(", - path.call(print, "arguments", 0), - ", ", - path.call(print, "arguments", 1), - ")", - ]; + return ["(", print(["arguments", 0]), ", ", print(["arguments", 1]), ")"]; } // func( @@ -76,8 +70,8 @@ function printCallArguments(path, options, print) { } let shouldBreak = false; - iterateFunctionParametersPath(argPath, (parameterPath) => { - shouldBreak = shouldBreak || willBreak(print(parameterPath)); + iterateFunctionParametersPath(argPath, () => { + shouldBreak = shouldBreak || willBreak(print()); }); return shouldBreak; @@ -90,7 +84,7 @@ function printCallArguments(path, options, print) { const printedArguments = []; iterateCallArgumentsPath(path, (argPath, index) => { const arg = argPath.getNode(); - const parts = [print(argPath)]; + const parts = [print()]; if (index === lastArgIndex) { // do nothing @@ -150,7 +144,7 @@ function printCallArguments(path, options, print) { if (shouldGroupFirst && i === 0) { printedExpanded = [ [ - print(argPath, { expandFirstArg: true }), + print([], { expandFirstArg: true }), printedArguments.length > 1 ? "," : "", hasEmptyLineFollowingFirstArg ? hardline : line, hasEmptyLineFollowingFirstArg ? hardline : "", @@ -161,7 +155,7 @@ function printCallArguments(path, options, print) { if (shouldGroupLast && i === args.length - 1) { printedExpanded = [ ...printedArguments.slice(0, -1), - print(argPath, { expandLastArg: true }), + print([], { expandLastArg: true }), ]; } }); diff --git a/src/language-js/print/call-expression.js b/src/language-js/print/call-expression.js index 8146c5b8d..81962434e 100644 --- a/src/language-js/print/call-expression.js +++ b/src/language-js/print/call-expression.js @@ -41,12 +41,12 @@ function printCallExpression(path, options, print) { (!isNew && isTestCall(node, parentNode))) ) { const printed = []; - iterateCallArgumentsPath(path, (argPath) => { - printed.push(print(argPath)); + iterateCallArgumentsPath(path, () => { + printed.push(print()); }); return [ isNew ? "new " : "", - path.call(print, "callee"), + print("callee"), optional, printFunctionTypeParameters(path, options, print), "(", @@ -83,7 +83,7 @@ function printCallExpression(path, options, print) { const contents = [ isNew ? "new " : "", - isDynamicImport ? "import" : path.call(print, "callee"), + isDynamicImport ? "import" : print("callee"), optional, isIdentifierWithFlowAnnotation ? `/*:: ${node.callee.trailingComments[0].value.slice(2).trim()} */` diff --git a/src/language-js/print/class.js b/src/language-js/print/class.js index f7f04dce3..aaaa80fba 100644 --- a/src/language-js/print/class.js +++ b/src/language-js/print/class.js @@ -40,16 +40,16 @@ function printClass(path, options, print) { const extendsParts = []; if (node.id) { - partsGroup.push(" ", path.call(print, "id")); + partsGroup.push(" ", print("id")); } - partsGroup.push(path.call(print, "typeParameters")); + partsGroup.push(print("typeParameters")); if (node.superClass) { const printed = [ "extends ", printSuperClass(path, options, print), - path.call(print, "superTypeParameters"), + print("superTypeParameters"), ]; const printedWithComments = path.call( (superClass) => printComments(superClass, printed, options), @@ -81,7 +81,7 @@ function printClass(path, options, print) { parts.push(...partsGroup, ...extendsParts); } - parts.push(" ", path.call(print, "body")); + parts.push(" ", print("body")); return parts; } @@ -137,7 +137,7 @@ function printList(path, options, print, listName) { } function printSuperClass(path, options, print) { - const printed = path.call(print, "superClass"); + const printed = print("superClass"); const parent = path.getParentNode(); if (parent.type === "AssignmentExpression") { return group( @@ -202,7 +202,7 @@ function printClassProperty(path, options, print) { parts.push("readonly "); } if (node.variance) { - parts.push(path.call(print, "variance")); + parts.push(print("variance")); } parts.push( printPropertyKey(path, options, print), diff --git a/src/language-js/print/flow.js b/src/language-js/print/flow.js index ef0cb40be..a64563810 100644 --- a/src/language-js/print/flow.js +++ b/src/language-js/print/flow.js @@ -27,27 +27,27 @@ function printFlow(path, options, print) { case "DeclareFunction": return printFlowDeclaration(path, [ "function ", - path.call(print, "id"), + print("id"), node.predicate ? " " : "", - path.call(print, "predicate"), + print("predicate"), semi, ]); case "DeclareModule": return printFlowDeclaration(path, [ "module ", - path.call(print, "id"), + print("id"), " ", - path.call(print, "body"), + print("body"), ]); case "DeclareModuleExports": return printFlowDeclaration(path, [ "module.exports", ": ", - path.call(print, "typeAnnotation"), + print("typeAnnotation"), semi, ]); case "DeclareVariable": - return printFlowDeclaration(path, ["var ", path.call(print, "id"), semi]); + return printFlowDeclaration(path, ["var ", print("id"), semi]); case "DeclareOpaqueType": return printFlowDeclaration(path, printOpaqueType(path, options, print)); case "DeclareInterface": @@ -78,13 +78,13 @@ function printFlow(path, options, print) { return printTupleType(path, options, print); case "GenericTypeAnnotation": return [ - path.call(print, "id"), + print("id"), printTypeParameters(path, options, print, "typeParameters"), ]; // Type Annotations for Facebook Flow, typically stripped out or // transformed away before printing. case "TypeAnnotation": - return path.call(print, "typeAnnotation"); + return print("typeAnnotation"); } } diff --git a/src/language-js/print/function-parameters.js b/src/language-js/print/function-parameters.js index d8a6e3c17..e80c7add1 100644 --- a/src/language-js/print/function-parameters.js +++ b/src/language-js/print/function-parameters.js @@ -65,7 +65,7 @@ function printFunctionParameters( if (isLastParameter && functionNode.rest) { printed.push("..."); } - printed.push(print(parameterPath)); + printed.push(print()); if (isLastParameter) { return; } diff --git a/src/language-js/print/function.js b/src/language-js/print/function.js index 9318700b7..0331e6bb8 100644 --- a/src/language-js/print/function.js +++ b/src/language-js/print/function.js @@ -69,7 +69,7 @@ function printFunctionDeclaration(path, print, options, expandArg) { } if (node.id) { - parts.push(path.call(print, "id")); + parts.push(print("id")); } const parametersDoc = printFunctionParameters( @@ -91,7 +91,7 @@ function printFunctionDeclaration(path, print, options, expandArg) { returnTypeDoc, ]), node.body ? " " : "", - path.call(print, "body") + print("body") ); if (options.semi && (node.declare || !node.body)) { @@ -134,7 +134,7 @@ function printMethod(path, options, print) { path.call((path) => printMethodInternal(path, options, print), "value") ); } else { - parts.push(path.call(print, "value")); + parts.push(print("value")); } return parts; @@ -157,7 +157,7 @@ function printMethodInternal(path, options, print) { ]; if (node.body) { - parts.push(" ", path.call(print, "body")); + parts.push(" ", print("body")); } else { parts.push(options.semi ? ";" : ""); } @@ -174,7 +174,7 @@ function printArrowFunctionSignature(path, options, print, args) { } if (shouldPrintParamsWithoutParens(path, options)) { - parts.push(path.call(print, "params", 0)); + parts.push(print(["params", 0])); } else { parts.push( group([ @@ -257,7 +257,7 @@ function printArrowFunctionExpression(path, options, print, args) { const body = []; let chainShouldBreak = false; - (function rec(path) { + (function rec() { const doc = printArrowFunctionSignature(path, options, print, args); if (signatures.length === 0) { signatures.push(doc); @@ -278,12 +278,12 @@ function printArrowFunctionExpression(path, options, print, args) { node.body.type !== "ArrowFunctionExpression" || (args && args.expandLastArg) ) { - body.unshift(path.call((bodyPath) => print(bodyPath, args), "body")); + body.unshift(print("body", args)); } else { node = node.body; path.call(rec, "body"); } - })(path); + })(); if (signatures.length > 1) { return printArrowChain( @@ -390,7 +390,7 @@ function shouldPrintParamsWithoutParens(path, options) { function printReturnType(path, print, options) { const node = path.getValue(); - const returnType = path.call(print, "returnType"); + const returnType = print("returnType"); if ( node.returnType && @@ -409,7 +409,7 @@ function printReturnType(path, print, options) { if (node.predicate) { // The return type will already add the colon, but otherwise we // need to do it ourselves - parts.push(node.returnType ? " " : ": ", path.call(print, "predicate")); + parts.push(node.returnType ? " " : ": ", print("predicate")); } return parts; @@ -423,12 +423,7 @@ function printReturnAndThrowArgument(path, options, print) { if (node.argument) { if (returnArgumentHasLeadingComment(options, node.argument)) { - parts.push([ - " (", - indent([hardline, path.call(print, "argument")]), - hardline, - ")", - ]); + parts.push([" (", indent([hardline, print("argument")]), hardline, ")"]); } else if ( isBinaryish(node.argument) || node.argument.type === "SequenceExpression" @@ -436,13 +431,13 @@ function printReturnAndThrowArgument(path, options, print) { parts.push( group([ ifBreak(" (", " "), - indent([softline, path.call(print, "argument")]), + indent([softline, print("argument")]), softline, ifBreak(")"), ]) ); } else { - parts.push(" ", path.call(print, "argument")); + parts.push(" ", print("argument")); } } diff --git a/src/language-js/print/interface.js b/src/language-js/print/interface.js index 21a887c8b..d8bfcd0d4 100644 --- a/src/language-js/print/interface.js +++ b/src/language-js/print/interface.js @@ -28,11 +28,7 @@ function printInterface(path, options, print) { const extendsParts = []; if (node.type !== "InterfaceTypeAnnotation") { - partsGroup.push( - " ", - path.call(print, "id"), - path.call(print, "typeParameters") - ); + partsGroup.push(" ", print("id"), print("typeParameters")); } const shouldIndentOnlyHeritageClauses = @@ -69,7 +65,7 @@ function printInterface(path, options, print) { parts.push(...partsGroup, ...extendsParts); } - parts.push(" ", path.call(print, "body")); + parts.push(" ", print("body")); return group(parts); } diff --git a/src/language-js/print/jsx.js b/src/language-js/print/jsx.js index ec8b2f4bf..57150c9b2 100644 --- a/src/language-js/print/jsx.js +++ b/src/language-js/print/jsx.js @@ -60,20 +60,17 @@ function printJsxElementInternal(path, options, print) { const node = path.getValue(); if (node.type === "JSXElement" && isEmptyJsxElement(node)) { - return [ - path.call(print, "openingElement"), - path.call(print, "closingElement"), - ]; + return [print("openingElement"), print("closingElement")]; } const openingLines = node.type === "JSXElement" - ? path.call(print, "openingElement") - : path.call(print, "openingFragment"); + ? print("openingElement") + : print("openingFragment"); const closingLines = node.type === "JSXElement" - ? path.call(print, "closingElement") - : path.call(print, "closingFragment"); + ? print("closingElement") + : print("closingFragment"); if ( node.children.length === 1 && @@ -360,7 +357,7 @@ function printJsxChildren( parts.push("", jsxWhitespace); } } else { - const printedChild = print(childPath); + const printedChild = print(); parts.push(printedChild); const next = children[i + 1]; @@ -473,7 +470,7 @@ function maybeWrapJsxElementInParens(path, elem, options) { function printJsxAttribute(path, options, print) { const node = path.getValue(); const parts = []; - parts.push(path.call(print, "name")); + parts.push(print("name")); if (node.value) { let res; @@ -489,7 +486,7 @@ function printJsxAttribute(path, options, print) { final = final.slice(1, -1).replace(new RegExp(quote, "g"), escape); res = [quote, final, quote]; } else { - res = path.call(print, "value"); + res = print("value"); } parts.push("=", res); } @@ -517,17 +514,12 @@ function printJsxExpressionContainer(path, options, print) { isBinaryish(node.expression))))); if (shouldInline) { - return group([ - "{", - path.call(print, "expression"), - lineSuffixBoundary, - "}", - ]); + return group(["{", print("expression"), lineSuffixBoundary, "}"]); } return group([ "{", - indent([softline, path.call(print, "expression")]), + indent([softline, print("expression")]), softline, lineSuffixBoundary, "}", @@ -543,12 +535,7 @@ function printJsxOpeningElement(path, options, print) { // Don't break self-closing elements with no attributes and no comments if (node.selfClosing && node.attributes.length === 0 && !nameHasComments) { - return [ - "<", - path.call(print, "name"), - path.call(print, "typeParameters"), - " />", - ]; + return ["<", print("name"), print("typeParameters"), " />"]; } // don't break up opening elements with a single long text attribute @@ -572,8 +559,8 @@ function printJsxOpeningElement(path, options, print) { ) { return group([ "<", - path.call(print, "name"), - path.call(print, "typeParameters"), + print("name"), + print("typeParameters"), " ", ...path.map(print, "attributes"), node.selfClosing ? " />" : ">", @@ -613,10 +600,9 @@ function printJsxOpeningElement(path, options, print) { return group( [ "<", - path.call(print, "name"), - path.call(print, "typeParameters"), - - indent(path.map((attr) => [line, print(attr)], "attributes")), + print("name"), + print("typeParameters"), + indent(path.map(() => [line, print()], "attributes")), node.selfClosing ? line : bracketSameLine ? ">" : softline, node.selfClosing ? "/>" : bracketSameLine ? "" : ">", ], @@ -630,7 +616,7 @@ function printJsxClosingElement(path, options, print) { parts.push(" { - const printed = ["...", print(p)]; + const printed = ["...", print()]; const node = p.getValue(); if (!hasComment(node) || !willPrintOwnComments(p)) { return printed; @@ -718,15 +704,9 @@ function printJsx(path, options, print) { case "JSXIdentifier": return String(node.name); case "JSXNamespacedName": - return join(":", [ - path.call(print, "namespace"), - path.call(print, "name"), - ]); + return join(":", [print("namespace"), print("name")]); case "JSXMemberExpression": - return join(".", [ - path.call(print, "object"), - path.call(print, "property"), - ]); + return join(".", [print("object"), print("property")]); case "JSXSpreadAttribute": return printJsxSpreadAttribute(path, options, print); case "JSXSpreadChild": { diff --git a/src/language-js/print/member-chain.js b/src/language-js/print/member-chain.js index 6040db191..017d17a59 100644 --- a/src/language-js/print/member-chain.js +++ b/src/language-js/print/member-chain.js @@ -135,7 +135,7 @@ function printMemberChain(path, options, print) { } else { printedNodes.unshift({ node, - printed: print(path), + printed: print(), }); } } diff --git a/src/language-js/print/member.js b/src/language-js/print/member.js index d87339377..93bc9a995 100644 --- a/src/language-js/print/member.js +++ b/src/language-js/print/member.js @@ -33,7 +33,7 @@ function printMemberExpression(path, options, print) { !isMemberExpression(parent)); return [ - path.call(print, "object"), + print("object"), shouldInline ? printMemberLookup(path, options, print) : group(indent([softline, printMemberLookup(path, options, print)])), @@ -41,7 +41,7 @@ function printMemberExpression(path, options, print) { } function printMemberLookup(path, options, print) { - const property = path.call(print, "property"); + const property = print("property"); const node = path.getValue(); const optional = printOptionalToken(path); diff --git a/src/language-js/print/misc.js b/src/language-js/print/misc.js index 6bfd54cff..417f55188 100644 --- a/src/language-js/print/misc.js +++ b/src/language-js/print/misc.js @@ -28,10 +28,10 @@ function printOptionalToken(path) { function printFunctionTypeParameters(path, options, print) { const fun = path.getValue(); if (fun.typeArguments) { - return path.call(print, "typeArguments"); + return print("typeArguments"); } if (fun.typeParameters) { - return path.call(print, "typeParameters"); + return print("typeParameters"); } return ""; } @@ -53,17 +53,17 @@ function printTypeAnnotation(path, options, print) { parentNode.type === "DeclareFunction" && parentNode.id === node; if (isFlowAnnotationComment(options.originalText, node.typeAnnotation)) { - return [" /*: ", path.call(print, "typeAnnotation"), " */"]; + return [" /*: ", print("typeAnnotation"), " */"]; } return [ isFunctionDeclarationIdentifier ? "" : isDefinite ? "!: " : ": ", - path.call(print, "typeAnnotation"), + print("typeAnnotation"), ]; } function printBindExpressionCallee(path, options, print) { - return ["::", path.call(print, "callee")]; + return ["::", print("callee")]; } function printTypeScriptModifiers(path, options, print) { diff --git a/src/language-js/print/module.js b/src/language-js/print/module.js index 4719e3880..a32b495ed 100644 --- a/src/language-js/print/module.js +++ b/src/language-js/print/module.js @@ -78,7 +78,7 @@ function printExportDeclaration(path, options, print) { } if (declaration) { - parts.push(" ", path.call(print, "declaration")); + parts.push(" ", print("declaration")); } else { parts.push( exportKind === "type" ? " type" : "", @@ -112,7 +112,7 @@ function printExportAllDeclaration(path, options, print) { parts.push(" *"); if (exported) { - parts.push(" as ", path.call(print, "exported")); + parts.push(" as ", print("exported")); } parts.push( @@ -163,7 +163,7 @@ function printModuleSource(path, options, print) { if (!shouldNotPrintSpecifiers(node, options)) { parts.push(" from"); } - parts.push(" ", path.call(print, "source")); + parts.push(" ", print("source")); return parts; } @@ -182,7 +182,7 @@ function printModuleSpecifiers(path, options, print) { const standaloneSpecifiers = []; const groupedSpecifiers = []; - path.each((specifierPath) => { + path.each(() => { const specifierType = path.getValue().type; if ( specifierType === "ExportNamespaceSpecifier" || @@ -190,12 +190,12 @@ function printModuleSpecifiers(path, options, print) { specifierType === "ImportNamespaceSpecifier" || specifierType === "ImportDefaultSpecifier" ) { - standaloneSpecifiers.push(print(specifierPath)); + standaloneSpecifiers.push(print()); } else if ( specifierType === "ExportSpecifier" || specifierType === "ImportSpecifier" ) { - groupedSpecifiers.push(print(specifierPath)); + groupedSpecifiers.push(print()); } else { /* istanbul ignore next */ throw new Error( @@ -297,7 +297,7 @@ function printModuleSpecifier(path, options, print) { ) { left = "*"; } else if (node[leftSideProperty]) { - left = path.call(print, leftSideProperty); + left = print(leftSideProperty); } if ( @@ -306,7 +306,7 @@ function printModuleSpecifier(path, options, print) { // import {a as a} from '.' !hasSameLoc(node[leftSideProperty], node[rightSideProperty])) ) { - right = path.call(print, rightSideProperty); + right = print(rightSideProperty); } parts.push(left, left && right ? " as " : "", right); diff --git a/src/language-js/print/object.js b/src/language-js/print/object.js index 61f73a41d..ac66f587d 100644 --- a/src/language-js/print/object.js +++ b/src/language-js/print/object.js @@ -103,7 +103,7 @@ function printObject(path, options, print) { const node = childPath.getValue(); propsAndLoc.push({ node, - printed: print(childPath), + printed: print(), loc: locStart(node), }); }, field); diff --git a/src/language-js/print/property.js b/src/language-js/print/property.js index 9601e6eb2..b598c2c93 100644 --- a/src/language-js/print/property.js +++ b/src/language-js/print/property.js @@ -17,7 +17,7 @@ function printPropertyKey(path, options, print) { const node = path.getNode(); if (node.computed) { - return ["[", path.call(print, "key"), "]"]; + return ["[", print("key"), "]"]; } const parent = path.getParentNode(); @@ -25,7 +25,7 @@ function printPropertyKey(path, options, print) { // flow has `Identifier` key, other parsers use `PrivateIdentifier` (ESTree) or `PrivateName` if (node.type === "ClassPrivateProperty" && key.type === "Identifier") { - return ["#", path.call(print, "key")]; + return ["#", print("key")]; } if (options.quoteProps === "consistent" && !needsQuoteProps.has(parent)) { @@ -86,13 +86,13 @@ function printPropertyKey(path, options, print) { ); } - return path.call(print, "key"); + return print("key"); } function printProperty(path, options, print) { const node = path.getValue(); if (node.shorthand) { - return path.call(print, "value"); + return print("value"); } return printAssignment( diff --git a/src/language-js/print/statement.js b/src/language-js/print/statement.js index a737ed5af..76365ec21 100644 --- a/src/language-js/print/statement.js +++ b/src/language-js/print/statement.js @@ -35,7 +35,7 @@ function printStatementSequence(path, options, print, property) { return; } - const printed = print(path); + const printed = print(); // in no-semi mode, prepend statement with semicolon if it might break ASI // don't prepend the only JSX element in a program with semicolon @@ -46,7 +46,7 @@ function printStatementSequence(path, options, print, property) { statementNeedsASIProtection(path, options) ) { if (hasComment(node, CommentCheckFlags.Leading)) { - parts.push(print(path, { needsSemi: true })); + parts.push(print([], { needsSemi: true })); } else { parts.push(";", printed); } diff --git a/src/language-js/print/template-literal.js b/src/language-js/print/template-literal.js index 9e42c5cf3..cfa61da53 100644 --- a/src/language-js/print/template-literal.js +++ b/src/language-js/print/template-literal.js @@ -61,7 +61,7 @@ function printTemplateLiteral(path, print, options) { path.each((childPath) => { const i = childPath.getName(); - parts.push(print(childPath)); + parts.push(print()); if (i < expressions.length) { // For a template literal of the following form: @@ -202,7 +202,7 @@ function printJestEachTemplateLiteral(path, options, print) { function printTemplateExpression(path, print) { const node = path.getValue(); - let printed = print(path); + let printed = print(); if (hasComment(node)) { printed = group([indent([softline, printed]), softline]); } diff --git a/src/language-js/print/ternary.js b/src/language-js/print/ternary.js index 91202114f..4bd00ade0 100644 --- a/src/language-js/print/ternary.js +++ b/src/language-js/print/ternary.js @@ -116,14 +116,8 @@ function printTernaryTest(path, options, print) { const parent = path.getParentNode(); const printed = isConditionalExpression - ? path.call(print, "test") - : [ - path.call(print, "checkType"), - " ", - "extends", - " ", - path.call(print, "extendsType"), - ]; + ? print("test") + : [print("checkType"), " ", "extends", " ", print("extendsType")]; /** * a * ? b @@ -275,12 +269,12 @@ function printTernary(path, options, print) { parts.push( " ? ", isNil(consequentNode) - ? path.call(print, consequentNodePropertyName) - : wrap(path.call(print, consequentNodePropertyName)), + ? print(consequentNodePropertyName) + : wrap(print(consequentNodePropertyName)), " : ", alternateNode.type === node.type || isNil(alternateNode) - ? path.call(print, alternateNodePropertyName) - : wrap(path.call(print, alternateNodePropertyName)) + ? print(alternateNodePropertyName) + : wrap(print(alternateNodePropertyName)) ); } else { // normal mode @@ -288,13 +282,13 @@ function printTernary(path, options, print) { line, "? ", consequentNode.type === node.type ? ifBreak("", "(") : "", - align(2, path.call(print, consequentNodePropertyName)), + align(2, print(consequentNodePropertyName)), consequentNode.type === node.type ? ifBreak("", ")") : "", line, ": ", alternateNode.type === node.type - ? path.call(print, alternateNodePropertyName) - : align(2, path.call(print, alternateNodePropertyName)), + ? print(alternateNodePropertyName) + : align(2, print(alternateNodePropertyName)), ]; parts.push( parent.type !== node.type || diff --git a/src/language-js/print/type-annotation.js b/src/language-js/print/type-annotation.js index 0b8972dfa..9f67f3cf9 100644 --- a/src/language-js/print/type-annotation.js +++ b/src/language-js/print/type-annotation.js @@ -56,18 +56,14 @@ function printOpaqueType(path, options, print) { const semi = options.semi ? ";" : ""; const node = path.getValue(); const parts = []; - parts.push( - "opaque type ", - path.call(print, "id"), - path.call(print, "typeParameters") - ); + parts.push("opaque type ", print("id"), print("typeParameters")); if (node.supertype) { - parts.push(": ", path.call(print, "supertype")); + parts.push(": ", print("supertype")); } if (node.impltype) { - parts.push(" = ", path.call(print, "impltype")); + parts.push(" = ", print("impltype")); } parts.push(semi); @@ -82,11 +78,7 @@ function printTypeAlias(path, options, print) { if (node.declare) { parts.push("declare "); } - parts.push( - "type ", - path.call(print, "id"), - path.call(print, "typeParameters") - ); + parts.push("type ", print("id"), print("typeParameters")); const rightPropertyName = node.type === "TSTypeAliasDeclaration" ? "typeAnnotation" : "right"; return [ @@ -169,7 +161,7 @@ function printUnionType(path, options, print) { // // comment // | child2 const printed = path.map((typePath) => { - let printedType = print(typePath); + let printedType = print(); if (!shouldHug) { printedType = align(2, printedType); } @@ -264,9 +256,9 @@ function printFunctionType(path, options, print) { node.returnType || node.predicate || node.typeAnnotation ? [ isArrowFunctionTypeAnnotation ? " => " : ": ", - path.call(print, "returnType"), - path.call(print, "predicate"), - path.call(print, "typeAnnotation"), + print("returnType"), + print("predicate"), + print("typeAnnotation"), ] : ""; diff --git a/src/language-js/print/type-parameters.js b/src/language-js/print/type-parameters.js index 343cef382..f9aeaa334 100644 --- a/src/language-js/print/type-parameters.js +++ b/src/language-js/print/type-parameters.js @@ -26,7 +26,7 @@ function printTypeParameters(path, options, print, paramsKey) { // for TypeParameterDeclaration typeParameters is a single node if (!Array.isArray(node[paramsKey])) { - return path.call(print, paramsKey); + return print(paramsKey); } const grandparent = path.getNode(2); @@ -97,14 +97,14 @@ function printTypeParameter(path, options, print) { const parts = []; const parent = path.getParentNode(); if (parent.type === "TSMappedType") { - parts.push("[", path.call(print, "name")); + parts.push("[", print("name")); if (node.constraint) { - parts.push(" in ", path.call(print, "constraint")); + parts.push(" in ", print("constraint")); } if (parent.nameType) { parts.push( " as ", - path.callParent((path) => path.call(print, "nameType")) + path.callParent(() => print("nameType")) ); } parts.push("]"); @@ -112,21 +112,21 @@ function printTypeParameter(path, options, print) { } if (node.variance) { - parts.push(path.call(print, "variance")); + parts.push(print("variance")); } - parts.push(path.call(print, "name")); + parts.push(print("name")); if (node.bound) { - parts.push(": ", path.call(print, "bound")); + parts.push(": ", print("bound")); } if (node.constraint) { - parts.push(" extends ", path.call(print, "constraint")); + parts.push(" extends ", print("constraint")); } if (node.default) { - parts.push(" = ", path.call(print, "default")); + parts.push(" = ", print("default")); } return parts; diff --git a/src/language-js/print/typescript.js b/src/language-js/print/typescript.js index c49a818e9..7ed4214e7 100644 --- a/src/language-js/print/typescript.js +++ b/src/language-js/print/typescript.js @@ -62,31 +62,31 @@ function printTypescript(path, options, print) { const castGroup = group([ "<", - indent([softline, path.call(print, "typeAnnotation")]), + indent([softline, print("typeAnnotation")]), softline, ">", ]); const exprContents = [ ifBreak("("), - indent([softline, path.call(print, "expression")]), + indent([softline, print("expression")]), softline, ifBreak(")"), ]; if (shouldBreakAfterCast) { return conditionalGroup([ - [castGroup, path.call(print, "expression")], + [castGroup, print("expression")], [castGroup, group(exprContents, { shouldBreak: true })], - [castGroup, path.call(print, "expression")], + [castGroup, print("expression")], ]); } - return group([castGroup, path.call(print, "expression")]); + return group([castGroup, print("expression")]); } case "TSDeclareFunction": return printFunctionDeclaration(path, print, options); case "TSExportAssignment": - return ["export = ", path.call(print, "expression"), semi]; + return ["export = ", print("expression"), semi]; case "TSModuleBlock": return printBlock(path, options, print); case "TSInterfaceBody": @@ -95,7 +95,7 @@ function printTypescript(path, options, print) { case "TSTypeAliasDeclaration": return printTypeAlias(path, options, print); case "TSQualifiedName": - return join(".", [path.call(print, "left"), path.call(print, "right")]); + return join(".", [print("left"), print("right")]); case "TSAbstractMethodDefinition": case "TSDeclareMethod": return printClassMethod(path, options, print); @@ -103,10 +103,10 @@ function printTypescript(path, options, print) { return printClassProperty(path, options, print); case "TSInterfaceHeritage": case "TSExpressionWithTypeArguments": // Babel AST - parts.push(path.call(print, "expression")); + parts.push(print("expression")); if (node.typeParameters) { - parts.push(path.call(print, "typeParameters")); + parts.push(print("typeParameters")); } return parts; @@ -114,22 +114,19 @@ function printTypescript(path, options, print) { return printTemplateLiteral(path, print, options); case "TSNamedTupleMember": return [ - path.call(print, "label"), + print("label"), node.optional ? "?" : "", ": ", - path.call(print, "elementType"), + print("elementType"), ]; case "TSRestType": - return ["...", path.call(print, "typeAnnotation")]; + return ["...", print("typeAnnotation")]; case "TSOptionalType": - return [path.call(print, "typeAnnotation"), "?"]; + return [print("typeAnnotation"), "?"]; case "TSInterfaceDeclaration": return printInterface(path, options, print); case "TSClassImplements": - return [ - path.call(print, "expression"), - path.call(print, "typeParameters"), - ]; + return [print("expression"), print("typeParameters")]; case "TSTypeParameterDeclaration": case "TSTypeParameterInstantiation": return printTypeParameters(path, options, print, "params"); @@ -138,7 +135,7 @@ function printTypescript(path, options, print) { case "TypeParameter": return printTypeParameter(path, options, print); case "TypeofTypeAnnotation": - return ["typeof ", path.call(print, "argument")]; + return ["typeof ", print("argument")]; case "TSAbstractKeyword": return "abstract"; case "TSAsyncKeyword": @@ -168,11 +165,7 @@ function printTypescript(path, options, print) { case "TSIntrinsicKeyword": return "intrinsic"; case "TSAsExpression": { - parts.push( - path.call(print, "expression"), - " as ", - path.call(print, "typeAnnotation") - ); + parts.push(print("expression"), " as ", print("typeAnnotation")); const parent = path.getParentNode(); if ( (isCallExpression(parent) && parent.callee === node) || @@ -183,7 +176,7 @@ function printTypescript(path, options, print) { return parts; } case "TSArrayType": - return [path.call(print, "elementType"), "[]"]; + return [print("elementType"), "[]"]; case "TSPropertySignature": { if (node.export) { parts.push("export "); @@ -204,12 +197,12 @@ function printTypescript(path, options, print) { ); if (node.typeAnnotation) { - parts.push(": ", path.call(print, "typeAnnotation")); + parts.push(": ", print("typeAnnotation")); } // This isn't valid semantically, but it's in the AST so we can print it. if (node.initializer) { - parts.push(" = ", path.call(print, "initializer")); + parts.push(" = ", print("initializer")); } return parts; @@ -228,11 +221,11 @@ function printTypescript(path, options, print) { parts.push("readonly "); } - parts.push(path.call(print, "parameter")); + parts.push(print("parameter")); return parts; case "TSTypeQuery": - return ["typeof ", path.call(print, "exprName")]; + return ["typeof ", print("exprName")]; case "TSIndexSignature": { const parent = path.getParentNode(); @@ -263,36 +256,31 @@ function printTypescript(path, options, print) { "[", node.parameters ? parametersGroup : "", node.typeAnnotation ? "]: " : "]", - node.typeAnnotation ? path.call(print, "typeAnnotation") : "", + node.typeAnnotation ? print("typeAnnotation") : "", parent.type === "ClassBody" ? semi : "", ]; } case "TSTypePredicate": return [ node.asserts ? "asserts " : "", - path.call(print, "parameterName"), - node.typeAnnotation ? [" is ", path.call(print, "typeAnnotation")] : "", + print("parameterName"), + node.typeAnnotation ? [" is ", print("typeAnnotation")] : "", ]; case "TSNonNullExpression": - return [path.call(print, "expression"), "!"]; + return [print("expression"), "!"]; case "TSImportType": return [ !node.isTypeOf ? "" : "typeof ", "import(", - path.call(print, node.parameter ? "parameter" : "argument"), + print(node.parameter ? "parameter" : "argument"), ")", - !node.qualifier ? "" : [".", path.call(print, "qualifier")], + !node.qualifier ? "" : [".", print("qualifier")], printTypeParameters(path, options, print, "typeParameters"), ]; case "TSLiteralType": - return path.call(print, "literal"); + return print("literal"); case "TSIndexedAccessType": - return [ - path.call(print, "objectType"), - "[", - path.call(print, "indexType"), - "]", - ]; + return [print("objectType"), "[", print("indexType"), "]"]; case "TSConstructSignatureDeclaration": case "TSCallSignatureDeclaration": case "TSConstructorType": { @@ -319,14 +307,14 @@ function printTypescript(path, options, print) { const isType = node.type === "TSConstructorType"; parts.push( isType ? " => " : ": ", - path.call(print, "returnType"), - path.call(print, "typeAnnotation") + print("returnType"), + print("typeAnnotation") ); } return parts; } case "TSTypeOperator": - return [node.operator, " ", path.call(print, "typeAnnotation")]; + return [node.operator, " ", print("typeAnnotation")]; case "TSMappedType": { const shouldBreak = hasNewlineInRange( options.originalText, @@ -345,12 +333,12 @@ function printTypescript(path, options, print) { ] : "", printTypeScriptModifiers(path, options, print), - path.call(print, "typeParameter"), + print("typeParameter"), node.optional ? getTypeScriptMappedTypeModifier(node.optional, "?") : "", node.typeAnnotation ? ": " : "", - path.call(print, "typeAnnotation"), + print("typeAnnotation"), ifBreak(semi), ]), printDanglingComments(path, options, /* sameIndent */ true), @@ -371,7 +359,7 @@ function printTypescript(path, options, print) { node.abstract ? "abstract " : "", node.declare ? "declare " : "", node.computed ? "[" : "", - path.call(print, "key"), + print("key"), node.computed ? "]" : "", printOptionalToken(path) ); @@ -388,9 +376,7 @@ function printTypescript(path, options, print) { ? "returnType" : "typeAnnotation"; const returnTypeNode = node[returnTypePropertyName]; - const returnTypeDoc = returnTypeNode - ? path.call(print, returnTypePropertyName) - : ""; + const returnTypeDoc = returnTypeNode ? print(returnTypePropertyName) : ""; const shouldGroupParameters = shouldGroupFunctionParameters( node, returnTypeDoc @@ -405,7 +391,7 @@ function printTypescript(path, options, print) { return group(parts); } case "TSNamespaceExportDeclaration": - parts.push("export as namespace ", path.call(print, "id")); + parts.push("export as namespace ", print("id")); if (options.semi) { parts.push(";"); @@ -424,7 +410,7 @@ function printTypescript(path, options, print) { parts.push("const "); } - parts.push("enum ", path.call(print, "id"), " "); + parts.push("enum ", print("id"), " "); if (node.members.length === 0) { parts.push( @@ -448,9 +434,9 @@ function printTypescript(path, options, print) { return parts; case "TSEnumMember": - parts.push(path.call(print, "id")); + parts.push(print("id")); if (node.initializer) { - parts.push(" = ", path.call(print, "initializer")); + parts.push(" = ", print("initializer")); } return parts; case "TSImportEqualsDeclaration": @@ -464,11 +450,7 @@ function printTypescript(path, options, print) { parts.push(node.importKind, " "); } - parts.push( - path.call(print, "id"), - " = ", - path.call(print, "moduleReference") - ); + parts.push(print("id"), " = ", print("moduleReference")); if (options.semi) { parts.push(";"); @@ -476,7 +458,7 @@ function printTypescript(path, options, print) { return group(parts); case "TSExternalModuleReference": - return ["require(", path.call(print, "expression"), ")"]; + return ["require(", print("expression"), ")"]; case "TSModuleDeclaration": { const parent = path.getParentNode(); const isExternalModule = isLiteral(node.id); @@ -514,12 +496,12 @@ function printTypescript(path, options, print) { } } - parts.push(path.call(print, "id")); + parts.push(print("id")); if (bodyIsDeclaration) { - parts.push(path.call(print, "body")); + parts.push(print("body")); } else if (node.body) { - parts.push(" ", group(path.call(print, "body"))); + parts.push(" ", group(print("body"))); } else { parts.push(semi); } @@ -534,7 +516,7 @@ function printTypescript(path, options, print) { return printTernary(path, options, print); case "TSInferType": - return ["infer", " ", path.call(print, "typeParameter")]; + return ["infer", " ", print("typeParameter")]; case "TSIntersectionType": return printIntersectionType(path, options, print); case "TSUnionType": @@ -545,11 +527,11 @@ function printTypescript(path, options, print) { return printTupleType(path, options, print); case "TSTypeReference": return [ - path.call(print, "typeName"), + print("typeName"), printTypeParameters(path, options, print, "typeParameters"), ]; case "TSTypeAnnotation": - return path.call(print, "typeAnnotation"); + return print("typeAnnotation"); case "TSEmptyBodyFunctionExpression": return printMethodInternal(path, options, print); @@ -559,15 +541,15 @@ function printTypescript(path, options, print) { case "TSJSDocUnknownType": return "?"; case "TSJSDocNullableType": - return ["?", path.call(print, "typeAnnotation")]; + return ["?", print("typeAnnotation")]; case "TSJSDocNonNullableType": - return ["!", path.call(print, "typeAnnotation")]; + return ["!", print("typeAnnotation")]; case "TSJSDocFunctionType": return [ "function(", // The parameters could be here, but typescript-estree doesn't convert them anyway (throws an error). "): ", - path.call(print, "typeAnnotation"), + print("typeAnnotation"), ]; } } diff --git a/src/language-js/printer-estree-json.js b/src/language-js/printer-estree-json.js index 105c2ad28..5fa591948 100644 --- a/src/language-js/printer-estree-json.js +++ b/src/language-js/printer-estree-json.js @@ -9,15 +9,14 @@ function genericPrint(path, options, print) { const node = path.getValue(); switch (node.type) { case "JsonRoot": - return [path.call(print, "node"), hardline]; + return [print("node"), hardline]; case "ArrayExpression": { if (node.elements.length === 0) { return "[]"; } const printed = path.map( - (elementPath) => - path.getValue() === null ? "null" : print(elementPath), + () => (path.getValue() === null ? "null" : print()), "elements" ); @@ -41,12 +40,9 @@ function genericPrint(path, options, print) { "}", ]; case "ObjectProperty": - return [path.call(print, "key"), ": ", path.call(print, "value")]; + return [print("key"), ": ", print("value")]; case "UnaryExpression": - return [ - node.operator === "+" ? "" : node.operator, - path.call(print, "argument"), - ]; + return [node.operator === "+" ? "" : node.operator, print("argument")]; case "NullLiteral": return "null"; case "BooleanLiteral": @@ -63,7 +59,7 @@ function genericPrint(path, options, print) { } case "TemplateLiteral": // There is only one `TemplateElement` - return path.call(print, "quasis", 0); + return print(["quasis", 0]); case "TemplateElement": return JSON.stringify(node.value.cooked); default: diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index f8503baf3..47c2864c9 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -168,17 +168,17 @@ function printPathNoParens(path, options, print, args) { switch (node.type) { case "JsExpressionRoot": - return path.call(print, "node"); + return print("node"); case "JsonRoot": - return [path.call(print, "node"), hardline]; + return [print("node"), hardline]; case "File": // Print @babel/parser's InterpreterDirective here so that // leading comments on the `Program` node get printed after the hashbang. if (node.program && node.program.interpreter) { - parts.push(path.call(print, "program", "interpreter")); + parts.push(print(["program", "interpreter"])); } - parts.push(path.call(print, "program")); + parts.push(print("program")); return parts; @@ -201,7 +201,7 @@ function printPathNoParens(path, options, print, args) { parent.body[0] === node ) { return [ - path.call(print, "expression"), + print("expression"), isVueEventBindingExpression(node.expression) ? ";" : "", ]; } @@ -209,7 +209,7 @@ function printPathNoParens(path, options, print, args) { // Do not append semicolon after the only JSX element in a program return [ - path.call(print, "expression"), + print("expression"), isTheOnlyJsxElementInMarkdown(options, path) ? "" : semi, ]; // Babel non-standard node. Used for Closure-style type casts. See postprocess.js. @@ -219,11 +219,11 @@ function printPathNoParens(path, options, print, args) { (node.expression.type === "ObjectExpression" || node.expression.type === "ArrayExpression"); if (shouldHug) { - return ["(", path.call(print, "expression"), ")"]; + return ["(", print("expression"), ")"]; } return group([ "(", - indent([softline, path.call(print, "expression")]), + indent([softline, print("expression")]), softline, ")", ]); @@ -236,16 +236,16 @@ function printPathNoParens(path, options, print, args) { case "LogicalExpression": return printBinaryishExpression(path, options, print); case "AssignmentPattern": - return [path.call(print, "left"), " = ", path.call(print, "right")]; + return [print("left"), " = ", print("right")]; case "OptionalMemberExpression": case "MemberExpression": { return printMemberExpression(path, options, print); } case "MetaProperty": - return [path.call(print, "meta"), ".", path.call(print, "property")]; + return [print("meta"), ".", print("property")]; case "BindExpression": if (node.object) { - parts.push(path.call(print, "object")); + parts.push(print("object")); } parts.push( @@ -272,7 +272,7 @@ function printPathNoParens(path, options, print, args) { case "ObjectTypeSpreadProperty": return [ "...", - path.call(print, "argument"), + print("argument"), printTypeAnnotation(path, options, print), ]; case "FunctionDeclaration": @@ -295,14 +295,14 @@ function printPathNoParens(path, options, print, args) { parts.push("*"); } if (node.argument) { - parts.push(" ", path.call(print, "argument")); + parts.push(" ", print("argument")); } return parts; case "AwaitExpression": { parts.push("await"); if (node.argument) { - parts.push(" ", path.call(print, "argument")); + parts.push(" ", print("argument")); const parent = path.getParentNode(); if ( (isCallExpression(parent) && parent.callee === node) || @@ -338,7 +338,7 @@ function printPathNoParens(path, options, print, args) { case "ExportDefaultSpecifier": return printModuleSpecifier(path, options, print); case "ImportAttribute": - return [path.call(print, "key"), ": ", path.call(print, "value")]; + return [print("key"), ": ", print("value")]; case "Import": return "import"; case "BlockStatement": @@ -358,11 +358,11 @@ function printPathNoParens(path, options, print, args) { return [ node.static ? "static " : "", "[[", - path.call(print, "id"), + print("id"), "]]", printOptionalToken(path), node.method ? "" : ": ", - path.call(print, "value"), + print("value"), ]; case "ObjectExpression": @@ -380,7 +380,7 @@ function printPathNoParens(path, options, print, args) { case "ObjectMethod": return printMethod(path, options, print); case "Decorator": - return ["@", path.call(print, "expression")]; + return ["@", print("expression")]; case "ArrayExpression": case "ArrayPattern": case "TupleExpression": @@ -397,9 +397,9 @@ function printPathNoParens(path, options, print, args) { const parts = []; path.each((expressionPath, index) => { if (index === 0) { - parts.push(print(expressionPath)); + parts.push(print()); } else { - parts.push(",", indent([line, print(expressionPath)])); + parts.push(",", indent([line, print()])); } }, "expressions"); return group(parts); @@ -411,7 +411,7 @@ function printPathNoParens(path, options, print, args) { case "Super": return "super"; case "Directive": - return [path.call(print, "value"), semi]; // Babel 6 + return [print("value"), semi]; // Babel 6 case "DirectiveLiteral": return printDirective(node, options); case "UnaryExpression": @@ -423,20 +423,15 @@ function printPathNoParens(path, options, print, args) { if (hasComment(node.argument)) { parts.push( - group([ - "(", - indent([softline, path.call(print, "argument")]), - softline, - ")", - ]) + group(["(", indent([softline, print("argument")]), softline, ")"]) ); } else { - parts.push(path.call(print, "argument")); + parts.push(print("argument")); } return parts; case "UpdateExpression": - parts.push(path.call(print, "argument"), node.operator); + parts.push(print("argument"), node.operator); if (node.prefix) { parts.reverse(); @@ -446,7 +441,7 @@ function printPathNoParens(path, options, print, args) { case "ConditionalExpression": return printTernary(path, options, print); case "VariableDeclaration": { - const printed = path.map((childPath) => print(childPath), "declarations"); + const printed = path.map(print, "declarations"); // We generally want to terminate all variable declarations with a // semicolon, except when they in the () part of for loops. @@ -491,15 +486,15 @@ function printPathNoParens(path, options, print, args) { case "WithStatement": return group([ "with (", - path.call(print, "object"), + print("object"), ")", - adjustClause(node.body, path.call(print, "body")), + adjustClause(node.body, print("body")), ]); case "IfStatement": { - const con = adjustClause(node.consequent, path.call(print, "consequent")); + const con = adjustClause(node.consequent, print("consequent")); const opening = group([ "if (", - group([indent([softline, path.call(print, "test")]), softline]), + group([indent([softline, print("test")]), softline]), ")", con, ]); @@ -528,7 +523,7 @@ function printPathNoParens(path, options, print, args) { group( adjustClause( node.alternate, - path.call(print, "alternate"), + print("alternate"), node.alternate.type === "IfStatement" ) ) @@ -538,7 +533,7 @@ function printPathNoParens(path, options, print, args) { return parts; } case "ForStatement": { - const body = adjustClause(node.body, path.call(print, "body")); + const body = adjustClause(node.body, print("body")); // We want to keep dangling comments above the loop to stay consistent. // Any comment positioned between the for statement and the parentheses @@ -561,13 +556,13 @@ function printPathNoParens(path, options, print, args) { group([ indent([ softline, - path.call(print, "init"), + print("init"), ";", line, - path.call(print, "test"), + print("test"), ";", line, - path.call(print, "update"), + print("update"), ]), softline, ]), @@ -579,18 +574,18 @@ function printPathNoParens(path, options, print, args) { case "WhileStatement": return group([ "while (", - group([indent([softline, path.call(print, "test")]), softline]), + group([indent([softline, print("test")]), softline]), ")", - adjustClause(node.body, path.call(print, "body")), + adjustClause(node.body, print("body")), ]); case "ForInStatement": return group([ "for (", - path.call(print, "left"), + print("left"), " in ", - path.call(print, "right"), + print("right"), ")", - adjustClause(node.body, path.call(print, "body")), + adjustClause(node.body, print("body")), ]); case "ForOfStatement": @@ -598,15 +593,15 @@ function printPathNoParens(path, options, print, args) { "for", node.await ? " await" : "", " (", - path.call(print, "left"), + print("left"), " of ", - path.call(print, "right"), + print("right"), ")", - adjustClause(node.body, path.call(print, "body")), + adjustClause(node.body, print("body")), ]); case "DoWhileStatement": { - const clause = adjustClause(node.body, path.call(print, "body")); + const clause = adjustClause(node.body, print("body")); const doBody = group(["do", clause]); parts = [doBody]; @@ -617,7 +612,7 @@ function printPathNoParens(path, options, print, args) { } parts.push( "while (", - group([indent([softline, path.call(print, "test")]), softline]), + group([indent([softline, print("test")]), softline]), ")", semi ); @@ -625,12 +620,12 @@ function printPathNoParens(path, options, print, args) { return parts; } case "DoExpression": - return ["do ", path.call(print, "body")]; + return ["do ", print("body")]; case "BreakStatement": parts.push("break"); if (node.label) { - parts.push(" ", path.call(print, "label")); + parts.push(" ", print("label")); } parts.push(semi); @@ -640,7 +635,7 @@ function printPathNoParens(path, options, print, args) { parts.push("continue"); if (node.label) { - parts.push(" ", path.call(print, "label")); + parts.push(" ", print("label")); } parts.push(semi); @@ -648,16 +643,16 @@ function printPathNoParens(path, options, print, args) { return parts; case "LabeledStatement": if (node.body.type === "EmptyStatement") { - return [path.call(print, "label"), ":;"]; + return [print("label"), ":;"]; } - return [path.call(print, "label"), ": ", path.call(print, "body")]; + return [print("label"), ": ", print("body")]; case "TryStatement": return [ "try ", - path.call(print, "block"), - node.handler ? [" ", path.call(print, "handler")] : "", - node.finalizer ? [" finally ", path.call(print, "finalizer")] : "", + print("block"), + node.handler ? [" ", print("handler")] : "", + node.finalizer ? [" finally ", print("finalizer")] : "", ]; case "CatchClause": if (node.param) { @@ -672,24 +667,24 @@ function printPathNoParens(path, options, print, args) { backwards: true, })) ); - const param = path.call(print, "param"); + const param = print("param"); return [ "catch ", parameterHasComments ? ["(", indent([softline, param]), softline, ") "] : ["(", param, ") "], - path.call(print, "body"), + print("body"), ]; } - return ["catch ", path.call(print, "body")]; + return ["catch ", print("body")]; // Note: ignoring n.lexical because it has no printing consequences. case "SwitchStatement": return [ group([ "switch (", - indent([softline, path.call(print, "discriminant")]), + indent([softline, print("discriminant")]), softline, ")", ]), @@ -702,7 +697,7 @@ function printPathNoParens(path, options, print, args) { path.map((casePath, index, cases) => { const caseNode = casePath.getValue(); return [ - print(casePath), + print(), index !== cases.length - 1 && isNextLineEmpty(caseNode, options) ? hardline @@ -717,7 +712,7 @@ function printPathNoParens(path, options, print, args) { ]; case "SwitchCase": { if (node.test) { - parts.push("case ", path.call(print, "test"), ":"); + parts.push("case ", print("test"), ":"); } else { parts.push("default:"); } @@ -758,11 +753,7 @@ function printPathNoParens(path, options, print, args) { case "TemplateLiteral": return printTemplateLiteral(path, print, options); case "TaggedTemplateExpression": - return [ - path.call(print, "tag"), - path.call(print, "typeParameters"), - path.call(print, "quasi"), - ]; + return [print("tag"), print("typeParameters"), print("quasi")]; // These types are unprintable because they serve as abstract // supertypes for other (printable) types. case "Node": @@ -788,12 +779,12 @@ function printPathNoParens(path, options, print, args) { case "MixedTypeAnnotation": return "mixed"; case "ArrayTypeAnnotation": - return [path.call(print, "elementType"), "[]"]; + return [print("elementType"), "[]"]; case "BooleanLiteralTypeAnnotation": return String(node.value); case "EnumDeclaration": - return ["enum ", path.call(print, "id"), " ", path.call(print, "body")]; + return ["enum ", print("id"), " ", print("body")]; case "EnumBooleanBody": case "EnumNumberBody": case "EnumStringBody": @@ -849,17 +840,15 @@ function printPathNoParens(path, options, print, args) { case "EnumNumberMember": case "EnumStringMember": return [ - path.call(print, "id"), + print("id"), " = ", - typeof node.init === "object" - ? path.call(print, "init") - : String(node.init), + typeof node.init === "object" ? print("init") : String(node.init), ]; case "EnumDefaultedMember": - return path.call(print, "id"); + return print("id"); case "FunctionTypeParam": { const name = node.name - ? path.call(print, "name") + ? print("name") : path.getParentNode().this === node ? "this" : ""; @@ -867,7 +856,7 @@ function printPathNoParens(path, options, print, args) { name, printOptionalToken(path), name ? ": " : "", - path.call(print, "typeAnnotation"), + print("typeAnnotation"), ]; } @@ -876,9 +865,9 @@ function printPathNoParens(path, options, print, args) { return printInterface(path, options, print); case "ClassImplements": case "InterfaceExtends": - return [path.call(print, "id"), path.call(print, "typeParameters")]; + return [print("id"), print("typeParameters")]; case "NullableTypeAnnotation": - return ["?", path.call(print, "typeAnnotation")]; + return ["?", print("typeAnnotation")]; case "Variance": { const { kind } = node; assert.ok(kind === "plus" || kind === "minus"); @@ -889,18 +878,18 @@ function printPathNoParens(path, options, print, args) { parts.push("static "); } - parts.push(path.call(print, "value")); + parts.push(print("value")); return parts; case "ObjectTypeIndexer": { return [ - node.variance ? path.call(print, "variance") : "", + node.variance ? print("variance") : "", "[", - path.call(print, "id"), + print("id"), node.id ? ": " : "", - path.call(print, "key"), + print("key"), "]: ", - path.call(print, "value"), + print("value"), ]; } case "ObjectTypeProperty": { @@ -915,15 +904,15 @@ function printPathNoParens(path, options, print, args) { return [ modifier, isGetterOrSetter(node) ? node.kind + " " : "", - node.variance ? path.call(print, "variance") : "", + node.variance ? print("variance") : "", printPropertyKey(path, options, print), printOptionalToken(path), isFunctionNotation(node) ? "" : ": ", - path.call(print, "value"), + print("value"), ]; } case "QualifiedTypeIdentifier": - return [path.call(print, "qualification"), ".", path.call(print, "id")]; + return [print("qualification"), ".", print("id")]; case "StringLiteralTypeAnnotation": return printString(rawText(node), options); case "NumberLiteralTypeAnnotation": @@ -937,7 +926,7 @@ function printPathNoParens(path, options, print, args) { case "TypeCastExpression": { return [ "(", - path.call(print, "expression"), + print("expression"), printTypeAnnotation(path, options, print), ")", ]; @@ -975,7 +964,7 @@ function printPathNoParens(path, options, print, args) { // be either left alone or desugared into AST types that are fully // supported by the pretty-printer. case "DeclaredPredicate": - return ["%checks(", path.call(print, "value"), ")"]; + return ["%checks(", print("value"), ")"]; case "AnyTypeAnnotation": case "TSAnyKeyword": return "any"; @@ -1007,9 +996,9 @@ function printPathNoParens(path, options, print, args) { return "this"; case "PrivateIdentifier": - return ["#", path.call(print, "name")]; + return ["#", print("name")]; case "PrivateName": - return ["#", path.call(print, "id")]; + return ["#", print("id")]; case "InterpreterDirective": parts.push("#!", node.value, hardline); @@ -1021,9 +1010,9 @@ function printPathNoParens(path, options, print, args) { return parts; case "PipelineBareFunction": - return path.call(print, "callee"); + return print("callee"); case "PipelineTopicExpression": - return path.call(print, "expression"); + return print("expression"); case "PipelinePrimaryTopicReference": { parts.push("#"); return parts; diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index 677a05829..6fe7c254c 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -410,9 +410,7 @@ function genericPrint(path, options, print) { " ".repeat(4), printChildren(path, options, print, { processor: (childPath, index) => - index === 0 - ? group([softline, print(childPath)]) - : print(childPath), + index === 0 ? group([softline, print()]) : print(), }) ), nextNode && nextNode.type === "footnoteDefinition" @@ -469,13 +467,13 @@ function printListItem(path, options, print, listPrefix) { printChildren(path, options, print, { processor: (childPath, index) => { if (index === 0 && childPath.getValue().type !== "list") { - return align(" ".repeat(prefix.length), print(childPath)); + return align(" ".repeat(prefix.length), print()); } const alignment = " ".repeat( clamp(options.tabWidth - listPrefix.length, 0, 3) // 4+ will cause indented code block ); - return [alignment, align(alignment, print(childPath))]; + return [alignment, align(alignment, print())]; }, }), ]; @@ -565,7 +563,7 @@ function printTable(path, options, print) { const contents = path.map( (rowPath) => rowPath.map((cellPath, columnIndex) => { - const text = printDocToString(print(cellPath), options).formatted; + const text = printDocToString(print(), options).formatted; const width = getStringWidth(text); columnMaxWidths[columnIndex] = Math.max( columnMaxWidths[columnIndex] || 3, // minimum width = 3 (---, :--, :-:, --:) @@ -691,14 +689,14 @@ function printRoot(path, options, print) { } } - return print(childPath); + return print(); }, }); } function printChildren(path, options, print, events = {}) { const { postprocessor } = events; - const processor = events.processor || ((childPath) => print(childPath)); + const processor = events.processor || (() => print()); const node = path.getValue(); const parts = []; diff --git a/src/language-yaml/print/block.js b/src/language-yaml/print/block.js index fcb603908..9e8e8e615 100644 --- a/src/language-yaml/print/block.js +++ b/src/language-yaml/print/block.js @@ -41,7 +41,7 @@ function printBlock(path, print, options) { } if (hasIndicatorComment(node)) { - parts.push(" ", path.call(print, "indicatorComment")); + parts.push(" ", print("indicatorComment")); } const lineContents = getBlockValueLineContents(node, { diff --git a/src/language-yaml/print/flow-mapping-sequence.js b/src/language-yaml/print/flow-mapping-sequence.js index b5d8152eb..7b7e234ef 100644 --- a/src/language-yaml/print/flow-mapping-sequence.js +++ b/src/language-yaml/print/flow-mapping-sequence.js @@ -43,7 +43,7 @@ function printChildren(path, print, options) { const node = path.getValue(); const parts = path.map( (childPath, index) => [ - print(childPath), + print(), index === node.children.length - 1 ? "" : [ diff --git a/src/language-yaml/print/mapping-item.js b/src/language-yaml/print/mapping-item.js index 8b43bbfe2..7a23e14fc 100644 --- a/src/language-yaml/print/mapping-item.js +++ b/src/language-yaml/print/mapping-item.js @@ -26,7 +26,7 @@ function printMappingItem(node, parentNode, path, print, options) { return ": "; } - const printedKey = path.call(print, "key"); + const printedKey = print("key"); const spaceBeforeColon = needsSpaceInFrontOfMappingValue(node) ? " " : ""; if (isEmptyMappingValue) { @@ -46,7 +46,7 @@ function printMappingItem(node, parentNode, path, print, options) { return ["? ", alignWithSpaces(2, printedKey)]; } - const printedValue = path.call(print, "value"); + const printedValue = print("value"); if (isEmptyMappingKey) { return [": ", alignWithSpaces(2, printedValue)]; } diff --git a/src/language-yaml/printer-yaml.js b/src/language-yaml/printer-yaml.js index 36949d49c..ed60df141 100644 --- a/src/language-yaml/printer-yaml.js +++ b/src/language-yaml/printer-yaml.js @@ -55,13 +55,13 @@ function genericPrint(path, options, print) { const { tag, anchor } = node; if (tag) { - parts.push(path.call(print, "tag")); + parts.push(print("tag")); } if (tag && anchor) { parts.push(" "); } if (anchor) { - parts.push(path.call(print, "anchor")); + parts.push(print("anchor")); } /** @type {Doc} */ @@ -120,7 +120,7 @@ function genericPrint(path, options, print) { isInlineNode(node) ? "" : breakParent, - path.call(print, "trailingComment"), + print("trailingComment"), ]) ); } @@ -140,7 +140,7 @@ function genericPrint(path, options, print) { ) ? hardline : "", - print(path), + print(), ], "endComments" ) @@ -163,11 +163,11 @@ function printNode(node, parentNode, path, options, print) { if (index !== 0) { parts.push(hardline); } - parts.push(print(childPath)); + parts.push(print()); if (shouldPrintDocumentEndMarker(document, nextDocument)) { parts.push(hardline, "..."); if (hasTrailingComment(document)) { - parts.push(" ", path.call(print, "trailingComment")); + parts.push(" ", print("trailingComment")); } } else if (nextDocument && !hasTrailingComment(nextDocument.head)) { parts.push(hardline, "---"); @@ -195,18 +195,18 @@ function printNode(node, parentNode, path, options, print) { ) === "head" ) { if (node.head.children.length > 0 || node.head.endComments.length > 0) { - parts.push(path.call(print, "head")); + parts.push(print("head")); } if (hasTrailingComment(node.head)) { - parts.push(["---", " ", path.call(print, "head", "trailingComment")]); + parts.push(["---", " ", print(["head", "trailingComment"])]); } else { parts.push("---"); } } if (shouldPrintDocumentBody(node)) { - parts.push(path.call(print, "body")); + parts.push(print("body")); } return join(hardline, parts); @@ -325,19 +325,14 @@ function printNode(node, parentNode, path, options, print) { case "blockLiteral": { return printBlock(path, print, options); } + case "mapping": case "sequence": return join(hardline, path.map(print, "children")); case "sequenceItem": - return [ - "- ", - alignWithSpaces(2, !node.content ? "" : path.call(print, "content")), - ]; + return ["- ", alignWithSpaces(2, !node.content ? "" : print("content"))]; case "mappingKey": - return !node.content ? "" : path.call(print, "content"); case "mappingValue": - return !node.content ? "" : path.call(print, "content"); - case "mapping": - return join(hardline, path.map(print, "children")); + return !node.content ? "" : print("content"); case "mappingItem": case "flowMappingItem": { return printMappingItem(node, parentNode, path, print, options); @@ -347,7 +342,7 @@ function printNode(node, parentNode, path, options, print) { case "flowSequence": return printFlowSequence(path, print, options); case "flowSequenceItem": - return path.call(print, "content"); + return print("content"); // istanbul ignore next default: throw new Error(`Unexpected node type ${node.type}`); diff --git a/src/main/ast-to-doc.js b/src/main/ast-to-doc.js index 366628086..eb41c581f 100644 --- a/src/main/ast-to-doc.js +++ b/src/main/ast-to-doc.js @@ -1,6 +1,5 @@ "use strict"; -const assert = require("assert"); const AstPath = require("../common/ast-path"); const { builders: { hardline, addAlignmentToDoc }, @@ -16,14 +15,14 @@ const multiparser = require("./multiparser"); * This is done by descending down the AST recursively. The recursion * involves two functions that call each other: * - * 1. printGenerically(), which is defined as an inner function here. + * 1. mainPrint(), which is defined as an inner function here. * It basically takes care of node caching. * 2. callPluginPrintFunction(), which checks for some options, and * ultimately calls the print() function provided by the plugin. * - * The plugin function will call printGenerically() again for child nodes - * of the current node, which will do its housekeeping, then call the - * plugin function again, and so on. + * The plugin function will call mainPrint() again for child nodes + * of the current node. mainPrint() will do its housekeeping, then call + * the plugin function again, and so on. * * All the while, these functions pass a "path" variable around, which * is a stack-like data structure (AstPath) that maintains the current @@ -38,44 +37,50 @@ function printAstToDoc(ast, options, alignmentSize = 0) { } const cache = new Map(); + const path = new AstPath(ast); - function printGenerically(path, args) { - const node = path.getValue(); + let doc = mainPrint(); - const shouldCache = node && typeof node === "object" && args === undefined; - if (shouldCache && cache.has(node)) { - return cache.get(node); - } - - let doc = callPluginPrintFunction(path, options, printGenerically, args); - - // We let JSXElement print its comments itself because it adds () around - // UnionTypeAnnotation has to align the child without the comments - if ( - !printer.willPrintOwnComments || - !printer.willPrintOwnComments(path, options) - ) { - // printComments will call the plugin print function and check for - // comments to print - doc = printComments(path, doc, options); - } - - if (shouldCache) { - cache.set(node, doc); - } - - return doc; - } - - let doc = printGenerically(new AstPath(ast)); if (alignmentSize > 0) { // Add a hardline to make the indents take effect // It should be removed in index.js format() doc = addAlignmentToDoc([hardline, doc], alignmentSize, options.tabWidth); } + propagateBreaks(doc); return doc; + + function mainPrint(selector, args) { + if (selector === undefined || selector === path) { + return mainPrintInternal(args); + } + + if (Array.isArray(selector)) { + return path.call(() => mainPrintInternal(args), ...selector); + } + + return path.call(() => mainPrintInternal(args), selector); + } + + function mainPrintInternal(args) { + const value = path.getValue(); + + const shouldCache = + value && typeof value === "object" && args === undefined; + + if (shouldCache && cache.has(value)) { + return cache.get(value); + } + + const doc = callPluginPrintFunction(path, options, mainPrint, args); + + if (shouldCache) { + cache.set(value, doc); + } + + return doc; + } } function printPrettierIgnoredNode(node, options) { @@ -99,38 +104,45 @@ function printPrettierIgnoredNode(node, options) { } function callPluginPrintFunction(path, options, printPath, args) { - assert.ok(path instanceof AstPath); - const node = path.getValue(); const { printer } = options; + let doc; + // Escape hatch if (printer.hasPrettierIgnore && printer.hasPrettierIgnore(path)) { - return printPrettierIgnoredNode(node, options); - } + doc = printPrettierIgnoredNode(node, options); + } else { + if (node) { + try { + // Potentially switch to a different parser + doc = multiparser.printSubtree(path, printPath, options, printAstToDoc); + } catch (error) { + /* istanbul ignore if */ + if (process.env.PRETTIER_DEBUG) { + throw error; + } + // Continue with current parser + } + } - if (node) { - try { - // Potentially switch to a different parser - const sub = multiparser.printSubtree( - path, - printPath, - options, - printAstToDoc - ); - if (sub) { - return sub; - } - } catch (error) { - /* istanbul ignore if */ - if (process.env.PRETTIER_DEBUG) { - throw error; - } - // Continue with current parser + if (!doc) { + doc = printer.print(path, options, printPath, args); } } - return printer.print(path, options, printPath, args); + // We let JSXElement print its comments itself because it adds () around + // UnionTypeAnnotation has to align the child without the comments + if ( + !printer.willPrintOwnComments || + !printer.willPrintOwnComments(path, options) + ) { + // printComments will call the plugin print function and check for + // comments to print + doc = printComments(path, doc, options); + } + + return doc; } module.exports = printAstToDoc;