Skip to content

refactor: skip autoload-dev dirs in class discovery#6540

Closed
gharlan wants to merge 2 commits into
6.xfrom
class-discovery-skip-autoload-dev
Closed

refactor: skip autoload-dev dirs in class discovery#6540
gharlan wants to merge 2 commits into
6.xfrom
class-discovery-skip-autoload-dev

Conversation

@gharlan
Copy link
Copy Markdown
Member

@gharlan gharlan commented Jun 1, 2026

ClassDiscovery::getRelevantPaths() treated every non-vendor PSR-4 prefix as project-level code. In a dev install that also pulls in the root package's autoload-dev directories — tests/, and dev tooling such as the custom rector rules under .tools/rector/.

Those classes never carry runtime attributes, so discovering them is pure overhead. Worse, getReflections() calls class_exists() on them, which autoloads dev-only vendor code: touching a Redaxo\Rector\* rule loads its Rector\AbstractRector parent, which triggers rector's scoped vendor autoloader. That scoped vendor ships its own installed.php, so once its loader is registered it shadows InstalledVersions::getRootPackage() (which then returns rector/rector-src with dev=false).

This reads the root composer.json and excludes its autoload-dev PSR-4 directories from discovery, so only runtime-relevant code (core, addons, the project's production autoload) is scanned. In a --no-dev install autoload-dev isn't registered anyway, so this simply aligns dev with prod.

Measured locally: relevant classes dropped 350 → 284, and a cold-cache console migrate no longer registers rector's loader.

ClassDiscovery::getRelevantPaths() treated every non-vendor PSR-4 prefix as
project code, so the root package's autoload-dev directories (tests, dev
tooling such as the custom rector rules under .tools/rector/) were scanned too.
Those classes never carry runtime attributes, so discovering them is wasted
work — and getReflections() calls class_exists() on them, which autoloads
dev-only vendor code: touching a Redaxo\Rector\* rule pulls in its
Rector\AbstractRector parent and thus rector's scoped vendor autoloader.

Read the root composer.json and exclude its autoload-dev PSR-4 directories, so
only runtime-relevant code (core, addons, the project's production autoload) is
scanned. In a --no-dev install autoload-dev is not registered anyway, so this
aligns dev with prod.
@gharlan gharlan added this to the REDAXO 6.0 milestone Jun 1, 2026
@gharlan
Copy link
Copy Markdown
Member Author

gharlan commented Jun 1, 2026

Closing: excluding the root package's autoload-dev dirs is the wrong discriminator — it also drops .tools/project (which carries #[AsTemplate] that discovery must find), not just the rector rules. There's no cheap signal separating dev tooling from the dev app.

The real problem this was meant to mitigate (rector's scoped vendor shadowing InstalledVersions::getRootPackage()) is already handled robustly at the consumer via a dedicated dev-flag lookup, so this discovery change isn't needed.

@gharlan gharlan closed this Jun 1, 2026
@gharlan gharlan deleted the class-discovery-skip-autoload-dev branch June 1, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant