Skip to content

Replace mpociot/reflection-docblock with barryvdh/reflection-docblock - #1085

Open
s-shiryaev wants to merge 2 commits into
knuckleswtf:v5from
s-shiryaev:fix/reflection-docblock-deprecation
Open

Replace mpociot/reflection-docblock with barryvdh/reflection-docblock#1085
s-shiryaev wants to merge 2 commits into
knuckleswtf:v5from
s-shiryaev:fix/reflection-docblock-deprecation

Conversation

@s-shiryaev

Copy link
Copy Markdown
Contributor

Summary

Scribe's docblock parser, mpociot/reflection-docblock, emits Implicitly marking parameter $x as nullable is deprecated on PHP 8.4+. This PR swaps it for barryvdh/reflection-docblock, which is the same phpDocumentor 2.x codebase, actively maintained, and free of those deprecations.

The old class names are kept working through aliases, so custom strategies do not break — see the section below.

This is the same move as #1049 (erusev/parsedownparsedown/parsedown), for the same reason.

Motivation

The test suite reports two deprecations on PHP 8.4/8.5:

Mpociot\Reflection\DocBlock\Tag::createInstance(): Implicitly marking parameter
$docblock as nullable is deprecated, the explicit nullable type must be used instead

PHPUnit attributes them to UseResponseFileTagTest only because that is where the package's classes happen to be compiled first.

This is a PHP 8.4 issue (Deprecate implicitly nullable parameter types).

In PHP 9 implicitly nullable parameters become a compile-time fatal error, at which point the package stops loading and Scribe stops working entirely.

Why barryvdh/reflection-docblock

It is the same lineage — another fork of phpDocumentor's ReflectionDocBlock 2.x — but a live one, and it is what barryvdh/laravel-ide-helper uses (which requires ^2.4, so the constraint here matches).

Diffing the two sources with the namespace normalized, the changes are purely additive plus the fixes we need:

  • ?DocBlock / ?Location / ?Context everywhere — the deprecations this PR is about
  • preg_split($pattern, $subject, -1, ...) instead of null for the limit argument — a separate PHP 8.1 deprecation
  • new ContextFactory, TemplateTag, SuppressWarningsTag, generics support, DocBlock::deleteTag()

Explicit nullable types landed in v2.2.0, so --prefer-lowest builds are clean too.


⚠️ Backwards compatibility ⚠️

Scribe's strategy API exposes these classes to userland. Custom strategies in the wild type-hint them:

UseApiResourceTags::getApiResourceResponseFromTags(Tag $apiResourceTag, ...)
UseTransformerTags::getTransformerResponseFromTag(Tag $transformerTag, ...)
GetFromDocBlocks::getMetadataFromDocBlock(DocBlock $methodDocBlock, DocBlock $classDocBlock)
RouteDocBlocker::getDocBlocksFromRoute()   // returns DocBlock instances

A bare namespace change would therefore break every custom strategy that does use Mpociot\Reflection\DocBlock\Tag;, in a minor release. To avoid that, src/aliases.php registers an autoloader that aliases the five old class names to the new ones:

spl_autoload_register(function (string $class): void {
    static $aliases = [
        'Mpociot\Reflection\DocBlock'              => Barryvdh\Reflection\DocBlock::class,
        'Mpociot\Reflection\DocBlock\Context'      => Barryvdh\Reflection\DocBlock\Context::class,
        'Mpociot\Reflection\DocBlock\Description'  => Barryvdh\Reflection\DocBlock\Description::class,
        'Mpociot\Reflection\DocBlock\Location'     => Barryvdh\Reflection\DocBlock\Location::class,
        'Mpociot\Reflection\DocBlock\Tag'          => Barryvdh\Reflection\DocBlock\Tag::class,
    ];

    if (isset($aliases[$class])) {
        class_alias($aliases[$class], $class);
    }
});

Existing type hints, instanceof checks and subclasses keep working unchanged — tests/Unit/DocBlockAliasesTest.php covers all five names plus the type-hint case.

It is deliberately an autoloader rather than an eager class_alias() call: if mpociot/reflection-docblock is still installed as some other package's dependency, Composer's own autoloader resolves those names first and this fallback is never reached, so we never shadow the real classes.

📌 Important Notice

This shim is a compatibility measure for the 5.x line only. I'd recommend dropping src/aliases.php (and its entry in the files autoload section) in 6.0, leaving Barryvdh\Reflection\DocBlock{,\Tag} as the only supported type hints.

📝 This must be documented in the 6.0 upgrade guide — users will need to update their imports.


Changes

  • composer.json — replaced mpociot/reflection-docblock: ^1.0.1 with barryvdh/reflection-docblock: ^2.4; registered src/aliases.php in the files autoload section.
  • src/aliases.php (new) — deprecated BC aliases for the five Mpociot\Reflection\* class names, registered as a fallback autoloader.
  • src/ (12 files) — Mpociot\Reflection\…Barryvdh\Reflection\… imports in RouteDocBlocker, ApiResourceResponseTools, GroupedEndpointsFromApp, Tools\Utils, TagStrategyWithFormRequestFallback and the GetFromDocBlocks / GetFromHeaderTag / GetFromResponseFieldTag / UseResponseTag / UseResponseFileTag / UseApiResourceTags / UseTransformerTags strategies. Import-only changes; no logic touched.
  • tests/ (10 files) — the same import change.
  • tests/Unit/DocBlockAliasesTest.php (new) — asserts the legacy class names still resolve to the new classes and that objects Scribe produces still satisfy the old type hints.
  • .github/copilot-instructions.md — updated the dependency reference.

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