What it does
This analyzer:- Runs PHPStan on your plugin’s
src/directory - Loads PocketMine-MP stubs for accurate type information
- Categorizes errors into specific issue types
- Determines severity based on error characteristics
- Reports results alongside other Retina analyzers
PHPStan is optional. If PHPStan is not installed, Retina will show an informational message and continue with other analyzers.
Installation
Install PHPStan in your plugin as a dev dependency:How it works
1. PHPStan detection
Retina searches for the PHPStan binary in:{plugin}/vendor/bin/phpstan(plugin’s local installation){retina}/vendor/bin/phpstan(Retina’s installation)/usr/local/bin/phpstan(global installation)/usr/bin/phpstan(system installation)- System PATH via
which phpstan
2. Configuration generation
Retina automatically creates a temporary PHPStan configuration with:3. Analysis execution
Retina runs:4. Result parsing
PHPStan’s JSON output is parsed and categorized into Retina issue types:- Undefined variables, methods, classes, functions, properties
- Type mismatches and violations
- Return type errors
- Unused code
- Dead code
- Interface and inheritance violations
- Null safety issues
- And more…
Error categorization
The analyzer maps PHPStan errors to specific categories:Undefined references
Undefined references
Undefined variable: $var→UNDEFINED_VARIABLECall to undefined method→UNDEFINED_METHODClass X not found→UNDEFINED_CLASSAccess to undefined constant→UNDEFINED_CONSTANTFunction X not found→UNDEFINED_FUNCTIONAccess to an undefined property→UNDEFINED_PROPERTY
Type errors
Type errors
expects X, Y given→TYPE_MISMATCHParameter #1 expects X, Y given→PARAMETER_TYPEshould return X but returns Y→RETURN_TYPEreturn statement is missing→MISSING_RETURN
Code quality
Code quality
Unused variable→UNUSED_VARIABLEis never used→UNUSED_VARIABLEDead code→DEAD_CODEUnreachable statement→DEAD_CODE
Object-oriented errors
Object-oriented errors
does not implement interface→INTERFACE_VIOLATIONcannot extend final class→INVALID_INHERITANCEabstract class contains abstract method→ABSTRACT_VIOLATIONCannot instantiate abstract class→INSTANTIATION_ERROR
Visibility and access
Visibility and access
Access to private property→VISIBILITY_VIOLATIONCannot access protected method→VISIBILITY_VIOLATIONStatic call to instance method→STATIC_CALL_ERROR
Null safety
Null safety
on null→NULL_SAFETYmight be null→NULL_SAFETYpossibly null→NULL_SAFETY
Severity determination
PHPStan errors are assigned severity levels:- ERROR - Non-ignorable issues that will cause runtime failures
- WARNING - Issues containing “deprecated”, “unused”, “might”, or “possibly”
- INFO - Suggestions and hints
Analysis levels
PHPStan supports 10 analysis levels (0-9). Control strictness with the--level flag:
retina.yml:
What each level checks
What each level checks
- Level 0 - Basic checks, minimal false positives
- Level 1 - Unknown classes, unknown methods called on $this
- Level 2 - Unknown methods on all expressions, validating PHPDocs
- Level 3 - Return types, types assigned to properties
- Level 4 - Dead code, unreachable code
- Level 5 - Checking types of arguments passed to methods
- Level 6 - Report missing typehints (default)
- Level 7 - Report partially wrong union types
- Level 8 - Report calling methods and accessing properties on nullable types
- Level 9 - Be strict about mixed type
PocketMine-MP stubs
Retina includes PocketMine-MP type stubs that provide:- Accurate type information for PM API classes
- Method signatures and return types
- Property types
- Constant definitions
Example output
Handling PHPStan not found
If PHPStan is not installed, Retina reports:Handling analysis failures
If PHPStan crashes or times out:Configuration
Disable PHPStan analyzer
Inretina.yml:
Set analysis level
Create custom PHPStan config
If your plugin already has aphpstan.neon or phpstan.neon.dist, Retina will still generate its own temporary config to ensure PocketMine-MP stubs are loaded.
To use your own config:
- Include Retina’s stubs in your config:
- Retina will respect your configuration when found.
Performance
- PHPStan analysis can be slow on large plugins (30-300 seconds)
- Results are worth the wait - PHPStan catches bugs other analyzers miss
- Consider excluding PHPStan in CI for faster feedback, running it separately
When to use PHPStan analyzer
Use when
- You want deep type checking
- You’re refactoring complex code
- You’re preparing for production
- You want to catch edge cases
Skip when
- You need fast analysis
- You’re doing rapid prototyping
- You only want PM-specific checks
- CI pipeline is time-sensitive
Advanced usage
Ignore specific PHPStan errors
Use PHPStan’s inline ignore comments:Custom PHPStan rules
Install PHPStan extensions for additional checks:phpstan.neon:
See also
Deprecated API analyzer
Detect PocketMine-MP API deprecations
Thread safety analyzer
Find async task thread safety issues
PHPStan documentation
Learn more about PHPStan