Skip to content

Fix three ways a valid PHPDoc is read or written back wrong - #308

Merged
ondrejmirtes merged 1 commit into
2.3.xfrom
fix-parser-discrepancies
Aug 30, 2026
Merged

Fix three ways a valid PHPDoc is read or written back wrong#308
ondrejmirtes merged 1 commit into
2.3.xfrom
fix-parser-discrepancies

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

All three were found by walking the grammars of the PHPDoc language the other way round and asking the parser to read what came out.

  • A nullable type written inside another one was printed as "??Foo", which is no type at all: "?(?Foo)" is read back as the very same thing while "??Foo" is not read at all.

  • What a conditional type asks about lost its parentheses where it needed them: "(?Foo) is Bar ? ... : ..." was printed as "?Foo is Bar ? ... : ...", which reads as a nullable type followed by something the type says nothing about. The printer dropped them for a union and an intersection as well, so "((Foo|Bar) is Baz ? ... )" came back out as "(Foo|Bar is Baz ? ... )".

  • A comment written inside a generic type was left waiting for a node where no attributes are asked for, which is the default: the reading of the whole PHPDoc then gave up with "Comments should already be flushed". TypeParser::parseGeneric() only gave the comments away as part of placing the node, and it only places one where the type it is written after carries a position of its own.

Claude-Session: https://claude.ai/code/session_01GavWEzia8ZVUYEe6JEde9i

All three were found by walking the grammars of the PHPDoc language the
other way round and asking the parser to read what came out.

* A nullable type written inside another one was printed as "??Foo",
  which is no type at all: "?(?Foo)" is read back as the very same
  thing while "??Foo" is not read at all.

* What a conditional type asks about lost its parentheses where it
  needed them: "(?Foo) is Bar ? ... : ..." was printed as
  "?Foo is Bar ? ... : ...", which reads as a nullable type followed by
  something the type says nothing about. The printer dropped them for a
  union and an intersection as well, so "((Foo|Bar) is Baz ? ... )" came
  back out as "(Foo|Bar is Baz ? ... )".

* A comment written inside a generic type was left waiting for a node
  where no attributes are asked for, which is the default: the reading
  of the whole PHPDoc then gave up with "Comments should already be
  flushed". TypeParser::parseGeneric() only gave the comments away as
  part of placing the node, and it only places one where the type it is
  written after carries a position of its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GavWEzia8ZVUYEe6JEde9i
@ondrejmirtes
ondrejmirtes merged commit d551e9e into 2.3.x Aug 30, 2026
59 checks passed
@ondrejmirtes
ondrejmirtes deleted the fix-parser-discrepancies branch August 30, 2026 14:14
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.

1 participant