Skip to content

Fix #8349: Improve phpdoc parsing performance of huge stub files#5089

Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-lqn35f7
Closed

Fix #8349: Improve phpdoc parsing performance of huge stub files#5089
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-lqn35f7

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When PHPStan processes a large stub file (like WordPress stubs with thousands of function declarations), FileTypeMapper::createPhpDocNodeMap() parses every PHPDoc comment in the file through PhpDocStringResolver::resolve(). However, during name scope map creation, the parsed PHPDoc nodes are only used to extract @template tags and type alias names (@phpstan-type, @phpstan-import-type, etc.). For files where most PHPDocs only contain @param/@return/@var tags, this parsing work is wasted.

This PR makes the PHPDoc parsing lazy: doc comments are only parsed during name scope map creation if they contain template or type-alias related tags, detected via fast str_contains() checks on the raw string.

Changes

  • Added shouldParseDocComment() method to src/Type/FileTypeMapper.php that checks if a doc comment contains any of the tag patterns that require parsing during name scope map creation: @template, -template (for @phpstan-template etc.), @phpstan-type, @psalm-type, @phan-type, import-type (for @phpstan-import-type etc.)
  • Modified createPhpDocNodeMap() to only call $this->phpDocStringResolver->resolve($docComment) when shouldParseDocComment() returns true
  • Added testLargeStubFileLazyPhpDocParsing() test in tests/PHPStan/Type/FileTypeMapperTest.php that generates a 10,000-function stub file and verifies template type resolution still works correctly, with a timing assertion that catches the performance regression

Root cause

FileTypeMapper::createPhpDocNodeMap() eagerly parsed all PHPDoc comments in a file to build the name scope map, even though only template tags and type alias names are needed at this stage. For large stub files with thousands of entries, this unnecessary parsing dominated the processing time. The fix adds a fast pre-filter that checks the raw doc comment string for relevant tag patterns before invoking the full PHPDoc parser.

Test

Added testLargeStubFileLazyPhpDocParsing in FileTypeMapperTest which:

  1. Generates a temporary PHP file with 10,000 function stubs (each with complex @param/@return PHPDocs) plus a @template class
  2. Calls FileTypeMapper::getResolvedPhpDoc() and verifies template type resolution works correctly
  3. Asserts the operation completes in under 3 seconds (without the optimization it takes ~4+ seconds)

Fixes phpstan/phpstan#8349

- Skip PHPDoc string parsing during FileTypeMapper name scope map creation
  for doc comments that don't contain @template or type-alias tags
- During createPhpDocNodeMap(), only template tags and type alias names are
  extracted from PHPDocs, so comments without these tags don't need parsing
- Uses fast str_contains() checks on the raw doc comment string to decide
  whether to invoke the full PHPDoc parser
- For a file with 10,000 function stubs, reduces processing time from ~4s
  to ~2s by avoiding ~10,000 unnecessary PhpDocStringResolver::resolve() calls
- Added performance regression test in FileTypeMapperTest
@staabm staabm closed this Feb 27, 2026
@staabm staabm deleted the create-pull-request/patch-lqn35f7 branch February 27, 2026 18:04
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