Skip to content

Commit f516232

Browse files
authored
fix: correct unary minus/plus/tilde precedence (#1236)
* fix: correct unary minus/plus/tilde precedence * fix: instanceof precedence * fix: instanceof precedence + new tests
1 parent 0f746c8 commit f516232

5 files changed

Lines changed: 214 additions & 49 deletions

File tree

src/ast.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ AST.precedence = {};
151151
["*", "/", "%"],
152152
["!"],
153153
["instanceof"],
154+
["u-", "u+", "u~"],
154155
["cast", "silent"],
155156
["**"],
156157
// TODO: [ (array)
@@ -300,7 +301,9 @@ AST.prototype.resolvePrecedence = function (result, parser) {
300301
// https://github.com/glayzzle/php-parser/issues/75
301302
if (result.what && !result.what.parenthesizedExpression) {
302303
if (result.what.kind === "bin") {
303-
lLevel = AST.precedence[result.type];
304+
// use the unary-specific precedence (u-, u+, u~) which is higher than binary - and +
305+
lLevel =
306+
AST.precedence["u" + result.type] || AST.precedence[result.type];
304307
rLevel = AST.precedence[result.what.type];
305308
if (lLevel && rLevel && rLevel < lLevel) {
306309
buffer = result.what;

test/precedence.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ describe("Test precedence", function () {
6161
});
6262
it("test instanceof", function () {
6363
shouldBeSame("$a instanceof $b && $c", "($a instanceof $b) && $c");
64+
shouldBeSame("$a + $b instanceof $c", "$a + ($b instanceof $c)");
65+
shouldBeSame("$a * $b instanceof $c", "$a * ($b instanceof $c)");
66+
shouldBeSame("-$a instanceof $b", "(-$a) instanceof $b");
67+
shouldBeSame("+$a instanceof $b", "(+$a) instanceof $b");
68+
shouldBeSame("~$a instanceof $b", "(~$a) instanceof $b");
6469
});
6570
it("test <<", function () {
6671
shouldBeSame("1 + 3 << 5", "(1 + 3) << 5");
@@ -124,6 +129,10 @@ describe("Test precedence", function () {
124129
shouldBeSame("6 + !4 + 5", "6 + (!4) + 5");
125130
shouldBeSame("if($a && !$b) {}", "if($a && (!$b)) {}");
126131
});
132+
it("test unary : - (prettier/plugin-php#2501)", function () {
133+
shouldBeSame("5 * -1 + 2", "(5 * (-1)) + 2");
134+
shouldBeSame('5 * -1 . "foo"', '(5 * (-1)) . "foo"');
135+
});
127136
it("test concat", function () {
128137
shouldBeSame('"a"."b"."c"."d"', '((("a"."b")."c")."d")');
129138
});

test/snapshot/__snapshots__/attributes.test.js.snap

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,74 +1591,74 @@ Program {
15911591
"attrs": [
15921592
Attribute {
15931593
"args": [
1594-
Unary {
1595-
"kind": "unary",
1596-
"type": "-",
1597-
"what": Bin {
1594+
Bin {
1595+
"kind": "bin",
1596+
"left": Bin {
15981597
"kind": "bin",
15991598
"left": Bin {
16001599
"kind": "bin",
16011600
"left": Bin {
16021601
"kind": "bin",
1603-
"left": Bin {
1604-
"kind": "bin",
1605-
"left": Number {
1602+
"left": Unary {
1603+
"kind": "unary",
1604+
"type": "-",
1605+
"what": Number {
16061606
"kind": "number",
16071607
"value": "20",
16081608
},
1609-
"right": Unary {
1609+
},
1610+
"right": Bin {
1611+
"kind": "bin",
1612+
"left": Unary {
16101613
"kind": "unary",
1611-
"parenthesizedExpression": true,
16121614
"type": "+",
1613-
"what": Bin {
1614-
"kind": "bin",
1615-
"left": Number {
1616-
"kind": "number",
1617-
"value": "10",
1618-
},
1619-
"right": Number {
1620-
"kind": "number",
1621-
"value": "5",
1622-
},
1623-
"type": "/",
1615+
"what": Number {
1616+
"kind": "number",
1617+
"value": "10",
16241618
},
16251619
},
1626-
"type": "*",
1627-
},
1628-
"right": Number {
1629-
"kind": "number",
1630-
"value": "2",
1620+
"parenthesizedExpression": true,
1621+
"right": Number {
1622+
"kind": "number",
1623+
"value": "5",
1624+
},
1625+
"type": "/",
16311626
},
1632-
"type": "%",
1627+
"type": "*",
16331628
},
1634-
"right": Bin {
1635-
"kind": "bin",
1636-
"left": Number {
1637-
"kind": "number",
1638-
"value": "8",
1639-
},
1640-
"right": Number {
1641-
"kind": "number",
1642-
"value": "2",
1643-
},
1644-
"type": "**",
1629+
"right": Number {
1630+
"kind": "number",
1631+
"value": "2",
16451632
},
1646-
"type": "+",
1633+
"type": "%",
16471634
},
1648-
"right": Unary {
1635+
"right": Bin {
1636+
"kind": "bin",
1637+
"left": Number {
1638+
"kind": "number",
1639+
"value": "8",
1640+
},
1641+
"right": Number {
1642+
"kind": "number",
1643+
"value": "2",
1644+
},
1645+
"type": "**",
1646+
},
1647+
"type": "+",
1648+
},
1649+
"right": Unary {
1650+
"kind": "unary",
1651+
"type": "+",
1652+
"what": Unary {
16491653
"kind": "unary",
1650-
"type": "+",
1651-
"what": Unary {
1652-
"kind": "unary",
1653-
"type": "-",
1654-
"what": Number {
1655-
"kind": "number",
1656-
"value": "2",
1657-
},
1654+
"type": "-",
1655+
"what": Number {
1656+
"kind": "number",
1657+
"value": "2",
16581658
},
16591659
},
1660-
"type": "-",
16611660
},
1661+
"type": "-",
16621662
},
16631663
],
16641664
"kind": "attribute",

test/snapshot/__snapshots__/unary.test.js.snap

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,154 @@ Program {
479479
}
480480
`;
481481

482+
exports[`Test unary precedence over add 1`] = `
483+
Program {
484+
"children": [
485+
ExpressionStatement {
486+
"expression": Bin {
487+
"kind": "bin",
488+
"left": Unary {
489+
"kind": "unary",
490+
"type": "-",
491+
"what": Number {
492+
"kind": "number",
493+
"value": "20",
494+
},
495+
},
496+
"right": Number {
497+
"kind": "number",
498+
"value": "5",
499+
},
500+
"type": "+",
501+
},
502+
"kind": "expressionstatement",
503+
},
504+
],
505+
"errors": [],
506+
"kind": "program",
507+
}
508+
`;
509+
510+
exports[`Test unary precedence over mul 1`] = `
511+
Program {
512+
"children": [
513+
ExpressionStatement {
514+
"expression": Bin {
515+
"kind": "bin",
516+
"left": Unary {
517+
"kind": "unary",
518+
"type": "-",
519+
"what": Number {
520+
"kind": "number",
521+
"value": "20",
522+
},
523+
},
524+
"right": Number {
525+
"kind": "number",
526+
"value": "5",
527+
},
528+
"type": "*",
529+
},
530+
"kind": "expressionstatement",
531+
},
532+
],
533+
"errors": [],
534+
"kind": "program",
535+
}
536+
`;
537+
538+
exports[`Test unary precedence over mul and add 1`] = `
539+
Program {
540+
"children": [
541+
ExpressionStatement {
542+
"expression": Bin {
543+
"kind": "bin",
544+
"left": Bin {
545+
"kind": "bin",
546+
"left": Unary {
547+
"kind": "unary",
548+
"type": "-",
549+
"what": Number {
550+
"kind": "number",
551+
"value": "20",
552+
},
553+
},
554+
"right": Number {
555+
"kind": "number",
556+
"value": "5",
557+
},
558+
"type": "*",
559+
},
560+
"right": Number {
561+
"kind": "number",
562+
"value": "10",
563+
},
564+
"type": "+",
565+
},
566+
"kind": "expressionstatement",
567+
},
568+
],
569+
"errors": [],
570+
"kind": "program",
571+
}
572+
`;
573+
574+
exports[`Test unary precedence with plus 1`] = `
575+
Program {
576+
"children": [
577+
ExpressionStatement {
578+
"expression": Bin {
579+
"kind": "bin",
580+
"left": Unary {
581+
"kind": "unary",
582+
"type": "+",
583+
"what": Number {
584+
"kind": "number",
585+
"value": "20",
586+
},
587+
},
588+
"right": Number {
589+
"kind": "number",
590+
"value": "5",
591+
},
592+
"type": "*",
593+
},
594+
"kind": "expressionstatement",
595+
},
596+
],
597+
"errors": [],
598+
"kind": "program",
599+
}
600+
`;
601+
602+
exports[`Test unary precedence with tilde 1`] = `
603+
Program {
604+
"children": [
605+
ExpressionStatement {
606+
"expression": Bin {
607+
"kind": "bin",
608+
"left": Unary {
609+
"kind": "unary",
610+
"type": "~",
611+
"what": Number {
612+
"kind": "number",
613+
"value": "20",
614+
},
615+
},
616+
"right": Number {
617+
"kind": "number",
618+
"value": "5",
619+
},
620+
"type": "*",
621+
},
622+
"kind": "expressionstatement",
623+
},
624+
],
625+
"errors": [],
626+
"kind": "program",
627+
}
628+
`;
629+
482630
exports[`Test unary simple 1`] = `
483631
Program {
484632
"children": [

test/snapshot/unary.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ describe("Test unary", function () {
2828
["parens (8)", "(~$var);"],
2929
["parens (9)", "(-100);"],
3030
["parens (10)", "-(100);"],
31+
["precedence over mul", "-20 * 5;"],
32+
["precedence over add", "-20 + 5;"],
33+
["precedence over mul and add", "-20 * 5 + 10;"],
34+
["precedence with plus", "+20 * 5;"],
35+
["precedence with tilde", "~20 * 5;"],
3136
])("%s", function (_, code) {
3237
expect(parser.parseEval(code)).toMatchSnapshot();
3338
});

0 commit comments

Comments
 (0)