Description
Problem
There is currently no unified command in dev-tools to run static analysis. Each project must manually configure and execute tools like PHPStan or Psalm, which leads to:
- inconsistent workflows across repositories
- duplicated configuration effort
- lack of standardization in CI pipelines
- fragmented developer experience compared to existing commands like ecs and rector
Given that dev-tools already centralizes code style (ecs) and automated refactoring (rector), static analysis is the missing third pillar.
Proposal
Introduce a new command:
composer analyse
Alias:
dev-tools analyse
Goals
Scope (Phase 1)
The initial implementation should focus on PHPStan as the primary engine.
Example usage:
dev-tools analyse
dev-tools analyse --level=8
dev-tools analyse --memory-limit=512M
dev-tools analyse --format=json
dev-tools analyse --configuration=phpstan.neon
Responsibilities
- run PHPStan using project or default configuration
- allow overriding analysis level via --level
- allow memory control via --memory-limit
- support different output formats (table, json, etc.)
- return proper exit codes for CI usage
- provide a first-class integration path for Type Perfect as part of the analysis stack instead of treating it as an unrelated manual setup
Future Extension (Phase 2)
Support additional engines such as Psalm via an extensible interface:
dev-tools analyse --engine=phpstan
dev-tools analyse --engine=psalm
dev-tools analyse --engine=all
Important:
- do NOT assume PHPStan and Psalm are interchangeable
- avoid forcing a shared abstraction that hides important differences
- engine-specific flags should be handled explicitly
Expected Behavior
- running
dev-tools analyse executes static analysis with sensible defaults
- errors are clearly reported in a normalized output
- exit code is non-zero when issues are found
- CLI options override configuration when provided
- Type Perfect can be enabled through the same analysis workflow without manual config archaeology
Implementation Strategy
1. PHPStan wrapper (Phase 1)
use Symfony\Component\Process\Process to execute:
vendor/bin/phpstan analyse
- map CLI options directly:
--level
--memory-limit
--configuration
--error-format
2. Type Perfect integration
- support
rector/type-perfect as an opt-in companion in the analysis flow
- document and/or detect the expected
phpstan/extension-installer setup
- allow enabling the documented Type Perfect groups incrementally (
null_over_false, no_mixed, narrow_param)
- keep this integrated with the analysis command experience rather than a separate one-off command path
3. Output handling
- stream output directly to the console
- optionally normalize or decorate output in future iterations
4. Extensible architecture
Design the command so additional engines can be added without rewriting core logic.
Requirements
- must work out-of-the-box with PHPStan installed
- must fail with a clear error message if PHPStan is missing
- must not require additional configuration for basic usage
- must be deterministic and CI-friendly
- must preserve exit codes from underlying tools
Non-goals
- replacing PHPStan or Psalm configuration systems
- forcing a unified abstraction over fundamentally different analyzers
- auto-installing dependencies
Benefits
- standardizes static analysis across projects
- reduces setup and onboarding time
- improves CI consistency
- aligns with existing dev-tools commands (ecs, rector)
- creates a foundation for future multi-engine analysis
- keeps Type Perfect adoption attached to the static-analysis workflow where it naturally belongs
Additional Context
PHPStan provides native support for CLI options such as level selection and memory limits, making it a natural first choice for integration. Psalm can be added later with a more explicit engine-based model rather than forcing a one-size-fits-all interface.
Additional Rules
Acceptance Criteria
- a new command dev-tools analyse is available and executable via Composer
- the command runs PHPStan by default
- supports at least:
--level
--memory-limit
--configuration
--format (or equivalent PHPStan flag)
- returns non-zero exit code when errors are found
- prints analysis results clearly to the console
- the implementation is extensible to support additional engines (e.g. Psalm) in the future
- Type Perfect support is covered as part of this work, including:
- an explicit integration path for
rector/type-perfect
- documented or validated use of
phpstan/extension-installer
- support for the documented Type Perfect groups (
null_over_false, no_mixed, narrow_param)
- avoiding manual consumer-side config archaeology for the common path
Architecture / Isolation Requirements
- the static analysis logic must be isolated into dedicated classes instead of being implemented directly in the command
- responsibilities must be clearly separated, for example:
- one class for resolving which analysis engine to run
- one class for building the process/command arguments for PHPStan
- one class for executing the analysis process
- one class for handling and formatting output
- the command must act only as an orchestrator and must not contain core business logic
- the design must allow adding new engines (e.g. Psalm) without modifying existing core logic significantly
- the implementation must make it straightforward to extract the analysis logic into an external reusable package in the future
- the core logic must avoid tight coupling to CLI I/O so it can be reused in other contexts
Issue Relation
Description
Problem
There is currently no unified command in dev-tools to run static analysis. Each project must manually configure and execute tools like PHPStan or Psalm, which leads to:
Given that dev-tools already centralizes code style (ecs) and automated refactoring (rector), static analysis is the missing third pillar.
Proposal
Introduce a new command:
composer analyseAlias:
dev-tools analyseGoals
Scope (Phase 1)
The initial implementation should focus on PHPStan as the primary engine.
Example usage:
Responsibilities
Future Extension (Phase 2)
Support additional engines such as Psalm via an extensible interface:
Important:
Expected Behavior
dev-tools analyseexecutes static analysis with sensible defaultsImplementation Strategy
1. PHPStan wrapper (Phase 1)
use
Symfony\Component\Process\Processto execute:vendor/bin/phpstan analyse--level--memory-limit--configuration--error-format2. Type Perfect integration
rector/type-perfectas an opt-in companion in the analysis flowphpstan/extension-installersetupnull_over_false,no_mixed,narrow_param)3. Output handling
4. Extensible architecture
Design the command so additional engines can be added without rewriting core logic.
Requirements
Non-goals
Benefits
Additional Context
PHPStan provides native support for CLI options such as level selection and memory limits, making it a natural first choice for integration. Psalm can be added later with a more explicit engine-based model rather than forcing a one-size-fits-all interface.
Additional Rules
Acceptance Criteria
--level--memory-limit--configuration--format(or equivalent PHPStan flag)rector/type-perfectphpstan/extension-installernull_over_false,no_mixed,narrow_param)Architecture / Isolation Requirements
Issue Relation