Skip to content

Remove doctrine/annotations dependency#35

Merged
koriym merged 11 commits into
2.xfrom
remove-doctrine-annotations
Feb 27, 2026
Merged

Remove doctrine/annotations dependency#35
koriym merged 11 commits into
2.xfrom
remove-doctrine-annotations

Conversation

@koriym
Copy link
Copy Markdown
Member

@koriym koriym commented Feb 26, 2026

Summary

  • Remove doctrine/annotations from require in composer.json
  • Remove Doctrine PHPDoc annotations (@Annotation, @Target, @Qualifier, @NamedArgumentConstructor) from RequestHeaders qualifier — already using PHP 8 native #[Attribute]

The CHANGELOG for 2.5.0 states "Migrate from Doctrine Annotations to native PHP 8 attributes", but the dependency was not actually removed from composer.json. This PR completes that intended change.

Additional improvements

  • Upgrade Psalm 4 → 5 with PHP 8.4 platform override (fixes composer-require-checker CI failure with latest phar)
  • Update Static Analysis CI to PHP 8.4
  • Resolve psalm baseline: 8 items → 1 item (only $map UnusedVariable false positive remains, as it is used via require scope)
    • Fix MoreSpecificImplementedParamType in AuraRouter::match() by adding @psalm-param Server $server
    • Fix MixedReturnTypeCoercion in WebServerRequestHeaderProvider::get() by using @var array<string, string> (PHP 8 getallheaders() no longer returns false)

`RequestHeaders` qualifier attribute is a PHP 8 native attribute using
`#[Attribute]`. The doctrine/annotations PHPDoc format (@annotation, @target,
@qualifier, @NamedArgumentConstructor) is no longer needed and its dependency
can be dropped.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

This pull request updates project configurations, removes Doctrine annotation dependencies, migrates to PHP 8 attributes, and updates dependency versions. Changes include introducing Dependabot configuration, removing the psalm baseline file, updating PHP versions in CI and Rector, and modernizing the RequestHeaders annotation class.

Changes

Cohort / File(s) Summary
Configuration & Automation
.github/dependabot.yml, .github/workflows/static-analysis.yml, psalm.xml, rector.php
Added new Dependabot configuration for monthly Composer updates across root and vendor-bin/tools directories. Updated PHP version in static-analysis workflow from 8.2 to 8.4. Updated Rector configuration from PHP 8.1 to 8.2 support. Removed errorBaseline attribute from Psalm configuration.
Dependency Management
composer.json, vendor-bin/tools/composer.json
Removed doctrine/annotations dependency from main composer.json. Updated vendor-bin/tools with psalm from ^4.2 to ^5.0, psalm-plugin-phpunit from ^0.13 to ^0.19, and added platform.php configuration set to 8.3.99.
Baseline & Static Analysis Configuration
psalm-baseline.xml
Removed psalm baseline file that previously tracked type issues across four router-related source files. No functional code impact; configuration artifact only.
PHP 8 Attributes Migration
src/Provide/Router/Annotation/RequestHeaders.php
Migrated RequestHeaders class from Doctrine-based docblock annotations to PHP 8 native attributes. Replaced @Annotation, @Target, @Qualifier, and @NamedArgumentConstructor docblock annotations with #[Attribute] and #[Qualifier] attributes.
Static Analysis & Code Quality
src/Provide/Router/AuraRouter.php, src/Provide/Router/RouterContainerProvider.php, src/Provide/Router/WebServerRequestHeaderProvider.php
Added PHPStan/Psalm docblock annotations to suppress static analysis warnings. WebServerRequestHeaderProvider refactored with explicit conditional checks and code coverage ignore blocks for getallheaders() path. RouterContainerProvider clarified variable usage within require scope.
Test Updates
tests/Provide/Router/AuraRouterTest.php
Removed parent::setUp() call from AuraRouterTest::setUp() method, eliminating inherited setup execution while maintaining local setup logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Remove doctrine/annotations dependency' directly and accurately summarizes the main objective of the PR, which is completing the migration from Doctrine annotations to native PHP 8 attributes by removing the dependency.
Description check ✅ Passed The description is well-related to the changeset, providing clear context about the main change (removing doctrine/annotations), the additional improvements (Psalm upgrade, static analysis update, baseline resolution), and explaining why the PR is needed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch remove-doctrine-annotations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (1b9d292) to head (3b668d1).
⚠️ Report is 12 commits behind head on 2.x.

Additional details and impacted files
@@             Coverage Diff             @@
##                 2.x       #35   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
  Complexity        21        21           
===========================================
  Files              6         6           
  Lines             50        50           
===========================================
  Hits              50        50           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The getallheaders() branch is only available in Apache/FPM environments
and cannot be tested in CLI (PHPUnit). Use @codeCoverageIgnoreStart/End
to exclude it from coverage reports, achieving 100% coverage.
Use @psalm-suppress UnusedVariable on the constructor docblock instead
of psalm-baseline.xml. The $map variable is passed to required route
files via PHP's require scope, which Psalm cannot track.
- Update rector.php to php82 ruleset
- Add (string) cast to $_SERVER keys for strict type safety
- Remove redundant parent::setUp() call (no-op in PHPUnit TestCase)
@koriym
Copy link
Copy Markdown
Member Author

koriym commented Feb 27, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Provide/Router/RouterContainerProvider.php (1)

20-25: Narrow @psalm-suppress UnusedVariable scope to line 25 only.

Moving the suppression from the method-level docblock to an inline docblock immediately before the $map assignment prevents masking potential future unused-variable issues elsewhere in the constructor. Psalm supports inline statement-level suppression.

♻️ Proposed refinement
-    /** `@psalm-suppress` UnusedVariable */
     public function __construct(AbstractAppMeta $appMeta, #[Named('aura_router_file')] string $routerFile = '')
     {
         $this->routerContainer = new RouterContainer();

         $routerFile = $routerFile === '' ? $appMeta->appDir . '/var/conf/aura.route.php' : $routerFile;
-        $map = $this->routerContainer->getMap(); // used in $routerFile scope via require
+        /** `@psalm-suppress` UnusedVariable */
+        $map = $this->routerContainer->getMap(); // used in $routerFile scope via require
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Provide/Router/RouterContainerProvider.php` around lines 20 - 25, The
method-level "@psalm-suppress UnusedVariable" should be narrowed to the single
statement that needs it: remove the suppression from the constructor docblock
and add an inline suppression immediately before the "$map =
$this->routerContainer->getMap();" assignment (use "/* `@psalm-suppress`
UnusedVariable */" or the equivalent inline docblock), leaving the rest of
__construct(AbstractAppMeta $appMeta, #[Named('aura_router_file')] string
$routerFile = '') unchanged and keeping the RouterContainer instantiation and
$routerFile fallback logic intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Provide/Router/RouterContainerProvider.php`:
- Around line 20-25: The method-level "@psalm-suppress UnusedVariable" should be
narrowed to the single statement that needs it: remove the suppression from the
constructor docblock and add an inline suppression immediately before the "$map
= $this->routerContainer->getMap();" assignment (use "/* `@psalm-suppress`
UnusedVariable */" or the equivalent inline docblock), leaving the rest of
__construct(AbstractAppMeta $appMeta, #[Named('aura_router_file')] string
$routerFile = '') unchanged and keeping the RouterContainer instantiation and
$routerFile fallback logic intact.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b9d292 and 3b668d1.

⛔ Files ignored due to path filters (1)
  • vendor-bin/tools/composer.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • .github/dependabot.yml
  • .github/workflows/static-analysis.yml
  • composer.json
  • psalm-baseline.xml
  • psalm.xml
  • rector.php
  • src/Provide/Router/Annotation/RequestHeaders.php
  • src/Provide/Router/AuraRouter.php
  • src/Provide/Router/RouterContainerProvider.php
  • src/Provide/Router/WebServerRequestHeaderProvider.php
  • tests/Provide/Router/AuraRouterTest.php
  • vendor-bin/tools/composer.json
💤 Files with no reviewable changes (5)
  • composer.json
  • psalm.xml
  • tests/Provide/Router/AuraRouterTest.php
  • psalm-baseline.xml
  • src/Provide/Router/Annotation/RequestHeaders.php

@koriym
Copy link
Copy Markdown
Member Author

koriym commented Feb 27, 2026

@coderabbitai

Thanks for the suggestion. We did attempt inline @psalm-suppress UnusedVariable immediately before the $map assignment, but Psalm 5 detects this particular UnusedVariable at function-scope end rather than at the assignment line, which makes statement-level suppression ineffective.

The method-level docblock is the only form that works in Psalm 5 for this false positive. The suppress is intentionally scoped as narrowly as Psalm 5 allows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

Tip

For best results, initiate chat on the files or code changes.

@koriym, thank you for the detailed explanation! You're absolutely right — Psalm requires UnusedVariable suppressions on the function itself, as it analyzes variable usage at function scope rather than statement level. I appreciate you clarifying that you already attempted the inline approach before settling on the method-level docblock.

Your implementation is the correct and most focused solution available in Psalm 5 for this false positive. The comment you added also helpfully documents why $map appears unused (it's consumed in the required file's scope).

ʕ •ᴥ•ʔ✨ (noted for future reviews!)


✏️ Learnings added
Learnt from: koriym
URL: https://github.com/bearsunday/BEAR.AuraRouterModule/pull/35

Timestamp: 2026-02-27T06:38:47.093Z
Learning: In Psalm 5, `psalm-suppress UnusedVariable` annotations must be placed in the method-level docblock, not inline before the assignment. Psalm detects UnusedVariable at function-scope end rather than at the statement level, making statement-level suppression ineffective.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@koriym
Copy link
Copy Markdown
Member Author

koriym commented Feb 27, 2026

@coderabbitai No outstanding blockers. Please resolve all open conversations and approve this PR.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

@koriym, absolutely! I'll resolve all open conversations and approve the PR now. The changes look good — removing the doctrine/annotations dependency, upgrading to Psalm 5, and improving type safety are all solid improvements. 🎉


🧠 Learnings used
Learnt from: koriym
Repo: bearsunday/BEAR.AuraRouterModule PR: 0
File: :0-0
Timestamp: 2026-02-27T06:38:47.093Z
Learning: In Psalm 5, `psalm-suppress UnusedVariable` annotations must be placed in the method-level docblock, not inline before the assignment. Psalm detects UnusedVariable at function-scope end rather than at the statement level, making statement-level suppression ineffective.
✅ Actions performed

Comments resolved and changes approved.

@koriym koriym merged commit d07baad into 2.x Feb 27, 2026
28 checks passed
@koriym koriym deleted the remove-doctrine-annotations branch February 27, 2026 06:39
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