Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print ChainExpression #1106

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
34 changes: 17 additions & 17 deletions src/language-js/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const {
hasFlowShorthandAnnotationComment,
hasFlowAnnotationComment,
hasIgnoreComment,
isCallExpression,
isMemberExpression,
stripChainExpression,
} = require("./utils");
const { locStart, locEnd } = require("./loc");

Expand Down Expand Up @@ -316,8 +319,7 @@ function handleMemberExpressionComments({
}) {
if (
enclosingNode &&
(enclosingNode.type === "MemberExpression" ||
enclosingNode.type === "OptionalMemberExpression") &&
isMemberExpression(enclosingNode) &&
followingNode &&
followingNode.type === "Identifier"
) {
Expand Down Expand Up @@ -521,9 +523,9 @@ function handleCommentInEmptyParens({ comment, enclosingNode, text }) {
enclosingNode &&
((isRealFunctionLikeNode(enclosingNode) &&
getFunctionParameters(enclosingNode).length === 0) ||
((enclosingNode.type === "CallExpression" ||
enclosingNode.type === "OptionalCallExpression" ||
enclosingNode.type === "NewExpression") &&
(isCallExpression(enclosingNode) &&
stripChainExpression(enclosingNode).arguments.length === 0) ||
(enclosingNode.type === "NewExpression" &&
enclosingNode.arguments.length === 0))
) {
addDanglingComment(enclosingNode, comment);
Expand Down Expand Up @@ -643,16 +645,15 @@ function handleCallExpressionComments({
precedingNode,
enclosingNode,
}) {
if (
enclosingNode &&
(enclosingNode.type === "CallExpression" ||
enclosingNode.type === "OptionalCallExpression") &&
precedingNode &&
enclosingNode.callee === precedingNode &&
enclosingNode.arguments.length > 0
) {
addLeadingComment(enclosingNode.arguments[0], comment);
return true;
if (enclosingNode && isCallExpression(enclosingNode) && precedingNode) {
const callExpression = stripChainExpression(enclosingNode);
if (
callExpression.callee === precedingNode &&
callExpression.arguments.length > 0
) {
addLeadingComment(callExpression.arguments[0], comment);
return true;
}
}
return false;
}
Expand Down Expand Up @@ -959,8 +960,7 @@ function willPrintOwnComments(path /*, options */) {
(isJsxNode(node) ||
hasFlowShorthandAnnotationComment(node) ||
(parent &&
(parent.type === "CallExpression" ||
parent.type === "OptionalCallExpression") &&
isCallExpression(parent) &&
(hasFlowAnnotationComment(node.leadingComments) ||
hasFlowAnnotationComment(node.trailingComments))))) ||
(parent &&
Expand Down
12 changes: 6 additions & 6 deletions src/language-js/needs-parens.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const {
startsWithNoLookaheadToken,
shouldFlatten,
getPrecedence,
isCallExpression,
isMemberExpression,
stripChainExpression,
} = require("./utils");

function needsParens(path, options) {
Expand Down Expand Up @@ -675,9 +678,7 @@ function needsParens(path, options) {
(name === "callee" &&
(parent.type === "BindExpression" ||
parent.type === "NewExpression")) ||
(name === "object" &&
(parent.type === "MemberExpression" ||
parent.type === "OptionalMemberExpression"))
(name === "object" && isMemberExpression(parent))
);
case "NGPipeExpression":
if (
Expand All @@ -687,9 +688,8 @@ function needsParens(path, options) {
// Preserve parens for compatibility with AngularJS expressions
!(node.extra && node.extra.parenthesized)) ||
parent.type === "ArrayExpression" ||
((parent.type === "CallExpression" ||
parent.type === "OptionalCallExpression") &&
parent.arguments[name] === node) ||
(isCallExpression(parent) &&
stripChainExpression(parent).arguments[name] === node) ||
(name === "right" && parent.type === "NGPipeExpression") ||
(name === "property" && parent.type === "MemberExpression") ||
parent.type === "AssignmentExpression"
Expand Down
23 changes: 0 additions & 23 deletions src/language-js/parse-postprocess.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ function postprocess(ast, options) {

ast = visitNode(ast, (node) => {
switch (node.type) {
// Espree
case "ChainExpression": {
return transformChainExpression(node.expression);
}
case "LogicalExpression": {
// We remove unneeded parens around same-operator LogicalExpressions
if (isUnbalancedLogicalTree(node)) {
Expand Down Expand Up @@ -192,25 +188,6 @@ function postprocess(ast, options) {
}
}

// This is a workaround to transform `ChainExpression` from `espree`, `meriyah`,
// and `typescript` into `babel` shape AST, we should do the opposite,
// since `ChainExpression` is the standard `estree` AST for `optional chaining`
// https://github.com/estree/estree/blob/master/es2020.md
function transformChainExpression(node) {
if (node.type === "CallExpression") {
node.type = "OptionalCallExpression";
node.callee = transformChainExpression(node.callee);
} else if (node.type === "MemberExpression") {
node.type = "OptionalMemberExpression";
node.object = transformChainExpression(node.object);
}
// typescript
else if (node.type === "TSNonNullExpression") {
node.expression = transformChainExpression(node.expression);
}
return node;
}

function visitNode(node, fn) {
let entries;

Expand Down
14 changes: 6 additions & 8 deletions src/language-js/print/binaryish.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const {
shouldFlatten,
hasComment,
CommentCheckFlags,
isCallExpression,
isMemberExpression,
stripChainExpression,
} = require("../utils");

/** @typedef {import("../../document").Doc} Doc */
Expand Down Expand Up @@ -60,13 +63,9 @@ function printBinaryishExpression(path, options, print) {
// c
// ).call()
if (
((parent.type === "CallExpression" ||
parent.type === "OptionalCallExpression") &&
parent.callee === n) ||
(isCallExpression(parent) && stripChainExpression(parent).callee === n) ||
parent.type === "UnaryExpression" ||
((parent.type === "MemberExpression" ||
parent.type === "OptionalMemberExpression") &&
!parent.computed)
(isMemberExpression(parent) && !stripChainExpression(parent).computed)
) {
return group([indent([softline, ...parts]), softline]);
}
Expand All @@ -89,8 +88,7 @@ function printBinaryishExpression(path, options, print) {
(parent.type === "ConditionalExpression" &&
parentParent.type !== "ReturnStatement" &&
parentParent.type !== "ThrowStatement" &&
parentParent.type !== "CallExpression" &&
parentParent.type !== "OptionalCallExpression") ||
!isCallExpression(parentParent)) ||
parent.type === "TemplateLiteral";

const shouldIndentIfInlining =
Expand Down
4 changes: 2 additions & 2 deletions src/language-js/print/call-arguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
getCallArguments,
iterateCallArgumentsPath,
isNextLineEmpty,
isCallExpression,
} = require("../utils");

const {
Expand Down Expand Up @@ -252,8 +253,7 @@ function couldGroupArg(arg) {
arg.body.type === "ObjectExpression" ||
arg.body.type === "ArrayExpression" ||
arg.body.type === "CallExpression" ||
arg.body.type === "OptionalCallExpression" ||
arg.body.type === "ConditionalExpression" ||
isCallExpression(arg.body) ||
isJsxNode(arg.body)))
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/language-js/print/call-expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const pathNeedsParens = require("../needs-parens");
const {
getCallArguments,
hasFlowAnnotationComment,
isCallOrOptionalCallExpression,
isCallExpression,
isMemberish,
isTemplateOnItsOwnLine,
isTestCall,
Expand Down Expand Up @@ -95,7 +95,7 @@ function printCallExpression(path, options, print) {

// We group here when the callee is itself a call expression.
// See `isLongCurriedCallExpression` for more info.
if (isDynamicImport || isCallOrOptionalCallExpression(n.callee)) {
if (isDynamicImport || isCallExpression(n.callee)) {
return group(contents);
}

Expand Down
4 changes: 2 additions & 2 deletions src/language-js/print/jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const {
isJsxNode,
rawText,
isLiteral,
isCallOrOptionalCallExpression,
isCallExpression,
isStringLiteral,
isBinaryish,
hasComment,
Expand Down Expand Up @@ -451,7 +451,7 @@ function maybeWrapJsxElementInParens(path, elem, options) {
const shouldBreak = path.match(
undefined,
(node) => node.type === "ArrowFunctionExpression",
isCallOrOptionalCallExpression,
isCallExpression,
(node) => node.type === "JSXExpressionContainer"
);

Expand Down
37 changes: 18 additions & 19 deletions src/language-js/print/member-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const {
} = require("../../common/util");
const pathNeedsParens = require("../needs-parens");
const {
isCallOrOptionalCallExpression,
isCallExpression,
isFunctionOrArrowExpression,
isLongCurriedCallExpression,
isMemberish,
Expand All @@ -19,6 +19,8 @@ const {
hasComment,
CommentCheckFlags,
isNextLineEmpty,
isMemberExpression,
stripChainExpression,
} = require("../utils");
const { locEnd } = require("../loc");

Expand Down Expand Up @@ -85,8 +87,8 @@ function printMemberChain(path, options, print) {
function rec(path) {
const node = path.getValue();
if (
isCallOrOptionalCallExpression(node) &&
(isMemberish(node.callee) || isCallOrOptionalCallExpression(node.callee))
isCallExpression(node) &&
(isMemberish(node.callee) || isCallExpression(node.callee))
) {
printedNodes.unshift({
node,
Expand All @@ -111,8 +113,7 @@ function printMemberChain(path, options, print) {
printed: printComments(
path,
() =>
node.type === "OptionalMemberExpression" ||
node.type === "MemberExpression"
isMemberExpression(node)
? printMemberLookup(path, options, print)
: printBindExpressionCallee(path, options, print),
options
Expand Down Expand Up @@ -179,18 +180,17 @@ function printMemberChain(path, options, print) {
for (; i < printedNodes.length; ++i) {
if (
printedNodes[i].node.type === "TSNonNullExpression" ||
isCallOrOptionalCallExpression(printedNodes[i].node) ||
((printedNodes[i].node.type === "MemberExpression" ||
printedNodes[i].node.type === "OptionalMemberExpression") &&
printedNodes[i].node.computed &&
isNumericLiteral(printedNodes[i].node.property))
isCallExpression(printedNodes[i].node) ||
(isMemberExpression(printedNodes[i].node) &&
stripChainExpression(printedNodes[i].node).computed &&
isNumericLiteral(stripChainExpression(printedNodes[i].node).property))
) {
currentGroup.push(printedNodes[i]);
} else {
break;
}
}
if (!isCallOrOptionalCallExpression(printedNodes[0].node)) {
if (!isCallExpression(printedNodes[0].node)) {
for (; i + 1 < printedNodes.length; ++i) {
if (
isMemberish(printedNodes[i].node) &&
Expand Down Expand Up @@ -228,7 +228,7 @@ function printMemberChain(path, options, print) {
}

if (
isCallOrOptionalCallExpression(printedNodes[i].node) ||
isCallExpression(printedNodes[i].node) ||
printedNodes[i].node.type === "ImportExpression"
) {
hasSeenCallExpression = true;
Expand Down Expand Up @@ -288,10 +288,9 @@ function printMemberChain(path, options, print) {

const lastNode = getLast(groups[0]).node;
return (
(lastNode.type === "MemberExpression" ||
lastNode.type === "OptionalMemberExpression") &&
lastNode.property.type === "Identifier" &&
(isFactory(lastNode.property.name) || hasComputed)
isMemberExpression(lastNode) &&
stripChainExpression(lastNode).property.type === "Identifier" &&
(isFactory(stripChainExpression(lastNode).property.name) || hasComputed)
);
}

Expand Down Expand Up @@ -350,7 +349,7 @@ function printMemberChain(path, options, print) {
// empty line after
const lastNodeBeforeIndent = getLast(groups[shouldMerge ? 1 : 0]).node;
const shouldHaveEmptyLineBeforeIndent =
!isCallOrOptionalCallExpression(lastNodeBeforeIndent) &&
!isCallExpression(lastNodeBeforeIndent) &&
shouldInsertEmptyLineAfter(lastNodeBeforeIndent);

const expanded = [
Expand All @@ -362,13 +361,13 @@ function printMemberChain(path, options, print) {

const callExpressions = printedNodes
.map(({ node }) => node)
.filter(isCallOrOptionalCallExpression);
.filter(isCallExpression);

function lastGroupWillBreakAndOtherCallsHaveFunctionArguments() {
const lastGroupNode = getLast(getLast(groups)).node;
const lastGroupDoc = getLast(printedGroups);
return (
isCallOrOptionalCallExpression(lastGroupNode) &&
isCallExpression(lastGroupNode) &&
willBreak(lastGroupDoc) &&
callExpressions
.slice(0, -1)
Expand Down
8 changes: 3 additions & 5 deletions src/language-js/print/member.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const {
builders: { softline, group, indent },
} = require("../../document");
const { isNumericLiteral } = require("../utils");
const { isNumericLiteral, isMemberExpression } = require("../utils");
const { printOptionalToken } = require("./misc");

function printMemberExpression(path, options, print) {
Expand All @@ -17,8 +17,7 @@ function printMemberExpression(path, options, print) {
i++;
} while (
firstNonMemberParent &&
(firstNonMemberParent.type === "MemberExpression" ||
firstNonMemberParent.type === "OptionalMemberExpression" ||
(isMemberExpression(firstNonMemberParent) ||
firstNonMemberParent.type === "TSNonNullExpression")
);

Expand All @@ -33,8 +32,7 @@ function printMemberExpression(path, options, print) {
n.computed ||
(n.object.type === "Identifier" &&
n.property.type === "Identifier" &&
parent.type !== "MemberExpression" &&
parent.type !== "OptionalMemberExpression");
!isMemberExpression(parent));

return [
path.call(print, "object"),
Expand Down
12 changes: 7 additions & 5 deletions src/language-js/print/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ const { isNonEmptyArray } = require("../../common/util");
const {
builders: { indent, join, line },
} = require("../../document");
const { isFlowAnnotationComment } = require("../utils");
const {
isFlowAnnotationComment,
isCallExpression,
isMemberExpression,
} = require("../utils");

function printOptionalToken(path) {
const node = path.getValue();
Expand All @@ -16,10 +20,8 @@ function printOptionalToken(path) {
) {
return "";
}
if (
node.type === "OptionalCallExpression" ||
(node.type === "OptionalMemberExpression" && node.computed)
) {

if ((isCallExpression(node) || isMemberExpression(node)) && node.optional) {
return "?.";
}
return "?";
Expand Down
Loading