Skip to content

fix: avoid adding parens to static property in new expression#2453

Open
sorafujitani wants to merge 2 commits intoprettier:mainfrom
sorafujitani:issue2441/new-parsed-static-prop
Open

fix: avoid adding parens to static property in new expression#2453
sorafujitani wants to merge 2 commits intoprettier:mainfrom
sorafujitani:issue2441/new-parsed-static-prop

Conversation

@sorafujitani
Copy link

Summary

Fixes #2441

When formatting code like new Yii::$app->class([]), the formatter was incorrectly adding parentheses to produce new Yii::$app()->class([]). This changes the semantics from accessing a static property (Yii::$app) to calling a static method (Yii::$app()).

Changes

  • Added logic in printer.mjs to skip adding parentheses for new expressions when:
    • The new is inside a member chain (parent is a lookup node or call)
    • The constructor has no arguments
    • The original source did not have parentheses
    • The target is a staticlookup (e.g., Yii::$app)

Test plan

@czosel
Copy link
Collaborator

czosel commented Feb 18, 2026

I took a closer look, because the need for options.originalText.charAt( is a bit of a code smell - the AST should contain all the information to tell the two cases apart, but currently it doesn't. Both

new Foo::$bar->baz();

and

new Foo::$bar()->baz();

are parsed like this:

{
  "kind": "expressionstatement",
  "expression": {
    "kind": "call",
    "what": {
      "kind": "propertylookup",
      "what": {
        "kind": "new",
        "what": {
          "kind": "staticlookup",
          "what": {
            "kind": "name",
            "name": "Foo",
            "resolution": "uqn"
          },
          "offset": {
            "kind": "variable",
            "name": "bar",
            "curly": false
          }
        },
        "arguments": []
      },
      "offset": {
        "kind": "identifier",
        "name": "baz"
      }
    },
    "arguments": []
  }
}

While nikic/PHP-Parser parses

new Foo::$bar->baz();

like this:

array(
    0: Stmt_Expression(
        expr: Expr_New(
            class: Expr_PropertyFetch(
                var: Expr_StaticPropertyFetch(
                    class: Name(
                        name: Foo
                    )
                    name: VarLikeIdentifier(
                        name: bar
                    )
                )
                name: Identifier(
                    name: baz
                )
            )
            args: array(
            )
        )
    )
)

and

new Foo::$bar()->baz();

like this:

array(
    0: Stmt_Expression(
        expr: Expr_MethodCall(
            var: Expr_New(
                class: Expr_StaticPropertyFetch(
                    class: Name(
                        name: Foo
                    )
                    name: VarLikeIdentifier(
                        name: bar
                    )
                )
                args: array(
                )
            )
            name: Identifier(
                name: baz
            )
            args: array(
            )
        )
    )
)

So I think this needs to be fixed in the parser, which might even include a bit of a refactor since the general AST structure differes quite a bit between the two parsers (?).

@MasonD
Copy link

MasonD commented Feb 19, 2026

Indeed, the parser itself is incorrect in its handling of the new operator. It might be more illustrative to use parentheses like this:

new (Foo::$bar->baz)();

The above is identical semantically to new Foo::$bar->baz();, but results in the following AST, (new Foo::$bar->baz(); should give this same AST but is bugged)

{
  "kind": "expressionstatement",
  "expression": {
    "kind": "new",
    "what": {
      "kind": "propertylookup",
      "what": {
        "kind": "staticlookup",
        "what": {
          "kind": "name",
          "name": "Foo",
          "resolution": "uqn"
        },
        "offset": {
          "kind": "variable",
          "name": "bar",
          "curly": false
        }
      },
      "offset": {
        "kind": "identifier",
        "name": "baz"
      }
    },
    "arguments": []
  }
}

@czosel
Copy link
Collaborator

czosel commented Feb 19, 2026

Thanks for clarifying @MasonD! I created an issue over at glayzzle/php-parser#1177.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Prettier incorrectly adds parentheses when using new with a static property

3 participants

Comments