Skip to content

Commit a252a41

Browse files
committed
MOD: binaryish
1 parent d6efe85 commit a252a41

File tree

19 files changed

+2051
-62
lines changed

19 files changed

+2051
-62
lines changed

cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@
224224
"posix",
225225
"precache",
226226
"preorder",
227+
"preprocess",
228+
"prerun",
227229
"prettierx",
228230
"progid",
229231
"Pschera",

src/document/printer.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,49 @@ function printDocToString(doc, options) {
697697
};
698698
}
699699

700-
return { formatted: out.join("") };
700+
// MOD: Pull dangling opening parenthesis and empty object, array and string
701+
// literals after binaryish operators followed by newlines up to the previous
702+
// line.
703+
const binaryishExp = new RegExp(
704+
`(${binaryishOperators})${newLine}\\s*((?:\\(|(?:\\{\\}|\\[\\]|['"\`]{2})[);]*)${newLine})`,
705+
"g"
706+
);
707+
const formatted = out.join("").replace(binaryishExp, "$1 $2");
708+
709+
return { formatted };
701710
}
702711

712+
const binaryishOperators = [
713+
// LogicalOperator
714+
"&&",
715+
"||",
716+
"??",
717+
718+
// BinaryOperator
719+
"==",
720+
"!=",
721+
"===",
722+
"!==",
723+
"<",
724+
"<=",
725+
">",
726+
">=",
727+
"<<",
728+
">>",
729+
">>>",
730+
"+",
731+
"-",
732+
"*",
733+
"/",
734+
"%",
735+
"&",
736+
"|",
737+
"^",
738+
"in",
739+
"instanceof",
740+
"..",
741+
]
742+
.map((operator) => `${operator.replaceAll(/[$()*+./?[\\\]^{|}-]/g, "\\$&")}`)
743+
.join("|");
744+
703745
export { printDocToString };

src/language-js/needs-parens.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
shouldFlatten,
2121
startsWithNoLookaheadToken,
2222
} from "./utils/index.js";
23+
import { isParenthesized } from "./utils/is-parenthesized.js";
2324

2425
/**
2526
* @import AstPath from "../common/ast-path.js"
@@ -401,7 +402,11 @@ function needsParens(path, options) {
401402

402403
case "LogicalExpression":
403404
if (node.type === "LogicalExpression") {
404-
return parent.operator !== node.operator;
405+
// MOD: Only add parens to logical expressions if the operator
406+
// precedence dictates it, or if it was parenthesized in the
407+
// original code.
408+
// return parent.operator !== node.operator;
409+
return isParenthesized(node, options);
405410
}
406411
// else fallthrough
407412

@@ -431,7 +436,8 @@ function needsParens(path, options) {
431436
}
432437

433438
if (parentPrecedence < precedence && operator === "%") {
434-
return parentOperator === "+" || parentOperator === "-";
439+
// MOD: No special treatment for modulo
440+
// return parentOperator === "+" || parentOperator === "-";
435441
}
436442

437443
// Add parenthesis when working with bitwise operators
@@ -440,7 +446,7 @@ function needsParens(path, options) {
440446
return true;
441447
}
442448

443-
return false;
449+
return isParenthesized(node, options);
444450
}
445451

446452
default:

src/language-js/print/angular.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { printBinaryishExpression } from "./binaryish.js";
1010

1111
/** @import AstPath from "../../common/ast-path.js" */
1212

13-
function printAngular(path, options, print) {
13+
function printAngular(path, options, print, args) {
1414
const { node } = path;
1515

1616
// Angular nodes always starts with `NG`
@@ -27,7 +27,7 @@ function printAngular(path, options, print) {
2727
: "",
2828
];
2929
case "NGPipeExpression":
30-
return printBinaryishExpression(path, options, print);
30+
return printBinaryishExpression(path, options, print, args);
3131
case "NGChainedExpression":
3232
return group(
3333
join(

src/language-js/print/arrow-function.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ function printArrowFunction(path, options, print, args = {}) {
149149
shouldPutBodyOnSameLine,
150150
});
151151

152+
// MOD: Wrap binaryish multi-line bodies in parens
153+
if (isBinaryish(functionBody)) {
154+
bodyDoc = group([
155+
ifBreak(" ("),
156+
bodyDoc,
157+
softline,
158+
ifBreak(")"),
159+
]);
160+
}
161+
152162
return group([
153163
group(
154164
shouldIndentSignatures

src/language-js/print/assignment.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import {
2+
softline,
3+
hardline,
24
group,
35
indent,
6+
ifBreak,
47
indentIfBreak,
58
line,
69
lineSuffixBoundary,
10+
conditionalGroup,
711
} from "../../document/builders.js";
812
import { canBreak, cleanDoc, willBreak } from "../../document/utils.js";
913
import getStringWidth from "../../utils/get-string-width.js";
@@ -20,7 +24,7 @@ import {
2024
isNumericLiteral,
2125
isObjectProperty,
2226
isStringLiteral,
23-
isUnionType,
27+
isUnionType
2428
} from "../utils/index.js";
2529
import { shouldInlineLogicalExpression } from "./binaryish.js";
2630
import { printCallExpression } from "./call-expression.js";
@@ -42,11 +46,23 @@ function printAssignment(
4246
const rightDoc = rightPropertyName
4347
? print(rightPropertyName, { assignmentLayout: layout })
4448
: "";
49+
const rightNode = path.node[rightPropertyName];
4550

4651
switch (layout) {
4752
// First break after operator, then the sides are broken independently on their own lines
48-
case "break-after-operator":
49-
return group([group(leftDoc), operator, group(indent([line, rightDoc]))]);
53+
case "break-after-operator": {
54+
// // MOD: Wrap multi-line binaryish assignments in parenthesis.
55+
const needsParens = isBinaryish(rightNode);
56+
const rightGroup = needsParens
57+
? group([
58+
ifBreak(" (", " "),
59+
indent([softline, rightDoc]),
60+
softline,
61+
ifBreak(")"),
62+
])
63+
: group(indent([line, rightDoc]));
64+
return group([group(leftDoc), operator, rightGroup]);
65+
}
5066

5167
// First break right-hand side, then left-hand side
5268
case "never-break-after-operator":
@@ -55,13 +71,25 @@ function printAssignment(
5571
// First break right-hand side, then after operator
5672
case "fluid": {
5773
const groupId = Symbol("assignment");
58-
return group([
74+
const grouped = group([
5975
group(leftDoc),
6076
operator,
6177
group(indent(line), { id: groupId }),
6278
lineSuffixBoundary,
6379
indentIfBreak(rightDoc, { groupId }),
6480
]);
81+
// // MOD: Wrap multi-line binaryish assignments in parenthesis.
82+
return isBinaryish(rightNode) &&
83+
!shouldInlineLogicalExpression(path.node, path.parent, options)
84+
? conditionalGroup([
85+
grouped,
86+
group([
87+
group(leftDoc),
88+
operator,
89+
group([" (", indent([hardline, rightDoc]), hardline, ")"]),
90+
]),
91+
])
92+
: grouped
6593
}
6694

6795
case "break-lhs":
@@ -193,7 +221,10 @@ function chooseLayout(path, options, print, leftDoc, rightPropertyName) {
193221
function shouldBreakAfterOperator(path, options, print, hasShortKey) {
194222
const rightNode = path.node;
195223

196-
if (isBinaryish(rightNode) && !shouldInlineLogicalExpression(rightNode)) {
224+
if (
225+
isBinaryish(rightNode) &&
226+
!shouldInlineLogicalExpression(rightNode, path.parent, options)
227+
) {
197228
return true;
198229
}
199230

@@ -213,7 +244,7 @@ function shouldBreakAfterOperator(path, options, print, hasShortKey) {
213244
case "ConditionalExpression": {
214245
if (!options.experimentalTernaries) {
215246
const { test } = rightNode;
216-
return isBinaryish(test) && !shouldInlineLogicalExpression(test);
247+
return isBinaryish(test) && !shouldInlineLogicalExpression(test, rightNode, options);
217248
}
218249
const { consequent, alternate } = rightNode;
219250
return (

0 commit comments

Comments
 (0)