nikic / PHP-Parser

A PHP parser written in PHP
BSD 3-Clause "New" or "Revised" License
16.99k stars 1.09k forks source link

Concatenate more than 2 elements #839

Closed claudiu-cristea closed 2 years ago

claudiu-cristea commented 2 years ago

Initial report https://github.com/rectorphp/rector/issues/7188

Problem

I want concatenate 3 elements:

new Node\Expr\BinaryOp\Concat(new Node\Expr\BinaryOp\Concat(A, B), C)

This produces (A . B) . C, but the parenthesis are useless. It should be, simply, A . B . C

Note that this not related to https://wiki.php.net/rfc/concatenation_precedence, as there it's about precedence of 2 different operators. Plus or minus (+/-) combined with string concatenation (.). That makes total sense. But in this case it's just a trivial left-to-right precedence. It's like 1 + 2 + 3. We don't write (1 + 2) + 3, do we?

Proposal

It should be possible to pass an array of parts (same as Encapsed). However, changing the Concat signature would break backwards compatibility, so my proposal is to create a new ConcatMultiple (or Concatenate?) and deprecate Concat. I would provide a PR if there an agreement on this request.

nikic commented 2 years ago

The pretty printer will produce A . B . C, not (A . B) . C, see e.g. this test: https://github.com/nikic/PHP-Parser/blob/678ccbe0720549c51d30b76d094a117eac819e9e/test/code/prettyPrinter/expr/parentheses.test#L52

nikic commented 2 years ago

Closing this per above comment. Looking at the references PR, you simply nested the concat nodes in the wrong way (they are left-associative, not right-associative).