Skip to content

Add ExprUsedAsStringNode virtual node emitted when expressions are used as strings#5712

Open
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-wmw6dz2
Open

Add ExprUsedAsStringNode virtual node emitted when expressions are used as strings#5712
phpstan-bot wants to merge 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-wmw6dz2

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

Implements a new ExprUsedAsStringNode virtual node that is emitted whenever an expression is used in a string context. This allows rule authors to hook into a single node type instead of having to handle many different AST node types (Echo_, Print_, Cast\String_, BinaryOp\Concat, InterpolatedString, AssignOp\Concat, InlineHTML) individually.

Changes

  • Added src/Node/ExprUsedAsStringNode.php — new virtual node extending NodeAbstract with getExpression() (the expression being used as string) and getOriginalNode() (the AST node causing the string usage)
  • src/Analyser/NodeScopeResolver.php — emit for each echo expression and for InlineHTML statements (using TypeExpr wrapping a ConstantStringType)
  • src/Analyser/ExprHandler/PrintHandler.php — emit for the print expression
  • src/Analyser/ExprHandler/CastStringHandler.php — emit for (string) cast inner expression
  • src/Analyser/ExprHandler/InterpolatedStringHandler.php — emit for interpolated strings and heredocs
  • src/Analyser/ExprHandler/AssignOpHandler.php — emit for .= concat assignment right-hand side

For concat chains used inside echo/print/cast/.= contexts, a single ExprUsedAsStringNode is emitted wrapping the entire concat expression — solving the issue reporter's complaint about getting multiple rule invocations per line for nested BinaryOp\Concat nodes.

Root cause

There was no unified virtual node for "expression used as string" contexts. Rule authors had to hook into Node::class and use instanceof checks for every relevant AST node type, with special handling needed for BinaryOp\Concat chains to avoid duplicate errors.

Test

Added tests/PHPStan/Rules/ExprUsedAsString/ with:

  • ExprUsedAsStringTestRule.php — test rule that reports each ExprUsedAsStringNode emission
  • ExprUsedAsStringRuleTest.php — verifies correct emission for all covered contexts: echo (single and multi-expression), print, (string) cast, interpolated string, concat assignment, echo with concat chain, heredoc, and inline HTML

Fixes phpstan/phpstan#13008

…used as strings

- Add ExprUsedAsStringNode virtual node class extending NodeAbstract, wrapping the expression being used as string and the original AST node
- Emit from Echo_ statement handler in NodeScopeResolver (one per echo expression)
- Emit from PrintHandler for print expressions
- Emit from CastStringHandler for (string) casts
- Emit from InterpolatedStringHandler for interpolated strings and heredocs
- Emit from AssignOpHandler for .= concat assignment right-hand side
- Emit from NodeScopeResolver for InlineHTML using TypeExpr(ConstantStringType)
- For echo/print of concat chains, a single node is emitted wrapping the entire concat expression
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.

2 participants