diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 451985f5..ebc68e3a 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -535,6 +535,9 @@ function needsParens(path, options) { case "ClassExpression": return parent.type === "ExportDefaultDeclaration"; + + case "OptionalMemberExpression": + return parent.type === "MemberExpression"; } return false; diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 164d54ed..a85e7327 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -4251,6 +4251,7 @@ function printMemberChain(path, options, print) { } else if (isMemberish(node)) { printedNodes.unshift({ node: node, + needsParens: pathNeedsParens(path, options), printed: comments.printComments( path, () => @@ -4449,7 +4450,23 @@ function printMemberChain(path, options, print) { groups.length >= 2 && !groups[1][0].node.comments && shouldNotWrap(groups); function printGroup(printedGroup) { - return concat(printedGroup.map(tuple => tuple.printed)); + const result = []; + for (let i = 0; i < printedGroup.length; i++) { + // Checks if the next node (i.e. the parent node) needs parens + // and print accordingl y + if (printedGroup[i + 1] && printedGroup[i + 1].needsParens) { + result.push( + "(", + printedGroup[i].printed, + printedGroup[i + 1].printed, + ")" + ); + i++; + } else { + result.push(printedGroup[i].printed); + } + } + return concat(result); } function printIndentedGroup(groups) { diff --git a/tests/optional_chaining/__snapshots__/jsfmt.spec.js.snap b/tests/optional_chaining/__snapshots__/jsfmt.spec.js.snap index 7fc92414..5f5a07fd 100644 --- a/tests/optional_chaining/__snapshots__/jsfmt.spec.js.snap +++ b/tests/optional_chaining/__snapshots__/jsfmt.spec.js.snap @@ -12,11 +12,16 @@ a?.(); a?.[++x]; a?.b.c(++x).d; a?.b[3].c?.(x).d; +a?.b.c; (a?.b).c; a?.b?.c; delete a?.b; a?.b[3].c?.(x).d.e?.f[3].g?.(y).h; + +(a?.b).c(); + +(a?.b)?.c.d?.e; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var street = user.address?.street; var fooValue = myForm.querySelector("input[name=foo]")?.value; @@ -30,9 +35,14 @@ a?.[++x]; a?.b.c(++x).d; a?.b[3].c?.(x).d; a?.b.c; +(a?.b).c; a?.b?.c; delete a?.b; a?.b[3].c?.(x).d.e?.f[3].g?.(y).h; +(a?.b).c(); + +a?.b?.c.d?.e; + `; diff --git a/tests/optional_chaining/chaining.js b/tests/optional_chaining/chaining.js index 378cfd97..f69ad26e 100644 --- a/tests/optional_chaining/chaining.js +++ b/tests/optional_chaining/chaining.js @@ -9,8 +9,13 @@ a?.(); a?.[++x]; a?.b.c(++x).d; a?.b[3].c?.(x).d; +a?.b.c; (a?.b).c; a?.b?.c; delete a?.b; a?.b[3].c?.(x).d.e?.f[3].g?.(y).h; + +(a?.b).c(); + +(a?.b)?.c.d?.e;