suhock/phpstan-rules

A set of custom PHPStan rules

Maintainers

Package info

github.com/suhock/phpstan-rules

Type:phpstan-extension

pkg:composer/suhock/phpstan-rules

Transparency log

Statistics

Installs: 4

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-07-24 10:44 UTC

This package is auto-updated.

Last update: 2026-07-24 11:41:11 UTC


README

A set of custom PHPStan rules.

Installation

composer require --dev suhock/phpstan-rules

If you use phpstan/extension-installer, the rules are registered automatically. Otherwise include the ruleset in your phpstan.neon:

includes:
    - vendor/suhock/phpstan-rules/rules.neon

Rules

NoStaticReturnTypeInFinalClassRule

Reports a static return type on a method of a class that cannot be extended: a final class, an enum, or an anonymous class. In such a class static always resolves to the class itself, so self is equivalent and states the intent honestly; declaring static advertises late static binding the class does not support, and silently changes the inferred return type across subclasses if final is ever removed.

final class Example
{
    public function make(): static  // reported: use "self"
    {
        return new self();
    }
}

When allowWhenOverriding is enabled (the default), a method whose static return type is inherited from an overridden parent method or interface is not reported. On PHP 8.4 and earlier a static return type cannot be narrowed to self in an override without a fatal incompatible-declaration error, so static is the only valid choice there. Set it to false to flag those overrides as well.

NoPhpstanIgnoreRule

Reports every ignore annotation: @phpstan-ignore, @phpstan-ignore-line, and @phpstan-ignore-next-line. Excludes those whose error identifiers are all present in a configured allow list. An annotation with no identifier (the legacy line-based form) can never be allow-listed and is always reported.

// with allowedIdentifiers: ["missingType.iterableValue"]

$x = $lib->call();   // @phpstan-ignore missingType.iterableValue   <- allowed
$y = $lib->call();   // @phpstan-ignore argument.type               <- reported (not allow-listed)
// @phpstan-ignore-next-line                                        <- reported (no identifier)
$z = $lib->call();

This is a hard gate with explicit, curated exceptions, and is disabled by default.

Compared to ergebnis/phpstan-rules' all-or-nothing NoPhpstanIgnoreRule, this one supports an allow list.

To simply ban the line-based @phpstan-ignore-line / @phpstan-ignore-next-line forms while allowing the inline @phpstan-ignore <identifier> form, use PHPStan's built-in reportIgnoresWithoutComments option instead — note it also requires an explanatory comment on every ignore.

Configuration

All rules are toggled (and the allow list set) under the parameters.suhock key:

parameters:
    suhock:
        noStaticReturnTypeInFinalClass:
            enabled: true
            allowWhenOverriding: true   # default: skip "static" returns inherited from an override
        noPhpstanIgnore:
            enabled: false     # default off
            allowedIdentifiers:
                - missingType.iterableValue

Development

composer install
composer test          # PHPUnit
composer phpstan       # dogfood the rules on this package
composer php-cs-fixer  # code style