Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dead Code Detector Laravel Package

shipmonk/dead-code-detector

PHPStan extension that detects unused PHP code: dead methods, properties, constants, and enum cases. Finds dead cycles and transitive dead members, can flag dead tested code, supports popular frameworks (e.g., Symfony), and offers customizable usage providers with optional auto-removal.

View on GitHub
Deep Wiki
Context7
1.0.0

Stable version!

  • Detection of all dead members is implemented and stable!
    • Dead methods, constants, enum cases and properties
  • Thus, no more BC breaks in extension points are expected
  • It took ~4 years of development

Performance improvements

  • Result cache offloaded to own cache (#319)
    • Analysis reusing cache:
      • up to ~40% less memory
      • up to ~40% faster
    • Result cache size: decreased by ~55%

New features:

  • Fully new Laravel support (#294)
    • Route registration — Route::get(), post(), put(), patch(), delete(), any(), match(), resource(), apiResource()
      • Callable array syntax: [Controller::class, 'method']
      • Legacy string syntax: 'Controller@method'
      • Invokable controllers: Controller::class
    • Event listeners — Event::listen(), Event::subscribe()
    • Auto-discovered event listeners — classes with handle* methods whose first parameter has a class type
    • Scheduled jobs — Schedule::job()
    • Gate definitions — Gate::define() (callable + invokable), Gate::policy()
    • Policy resolution — $this->authorize() calls resolve policy class via Laravel's namespace convention (Models\Policies\)
    • Console commands — __construct, handle on Illuminate\Console\Command subclasses
    • Jobs — __construct, handle, failed, middleware, retryUntil, uniqueId, tags, backoff, uniqueVia, displayName on ShouldQueue / Dispatchable classes
    • Service providers — __construct, register, boot
    • Middleware — handle, terminate, __construct (detected by first parameter type Illuminate\Http\Request)
    • Notifications — via, toMail, toArray, toDatabase, toBroadcast, toVonage, toSlack
    • Form requests — authorize, rules, messages, attributes, prepareForValidation, passedValidation, failedValidation, failedAuthorization
    • Policies — before, viewAny, view, create, update, delete, restore, forceDelete (heuristic via \Policies\ namespace + Policy suffix)
    • Mailables — build, content, envelope, attachments, headers
    • Broadcast events — broadcastWith, broadcastAs, broadcastWhen
    • JSON resources — paginationInformation
    • Notifiable routing — routeNotificationFor* methods
    • Eloquent features:
      • Model methods — constructor, boot, booted, casts, newFactory
      • Query scopes — scope* methods
      • Relationships — methods returning Illuminate\Database\Eloquent\Relations\*
      • Attribute accessors — methods returning Illuminate\Database\Eloquent\Casts\Attribute
      • Legacy accessors/mutators — get*Attribute() / set*Attribute()
      • Observers — Model::observe() calls + #[ObservedBy] attribute (all observer event methods)
      • Factories — definition, configure
      • Seeders — run
      • Migrations — up, down
  • Symfony improvements
    • #[Autoconfigure(constructor:, calls:)], #[AutowireCallable], #[TaggedIterator], #[TaggedLocator], #[Required] on properties, #[AsSchedule], #[AsCronTask], #[AsPeriodicTask], !php/enum references in config yamls (#317)
    • Allow explicit containerXmlPaths configuration - no need for phpstan/phpstan-doctrine for DIC calls analysis (#325)
    • Symfony UX support: #[AsTwigComponent]/#[AsLiveComponent] (constructor, mount()), #[LiveProp], #[LiveAction], #[LiveListener], lifecycle hooks (#329)
  • Reflection improvements
    • support member constructors like new ReflectionMethod(Class, 'method') (#313)

Dependencies:

  • Requires PHP ^8.1 (was ^7.4) (#296)
  • Requires phpstan/phpstan ^2.1.41, (was ^2.1.23) (#297)
0.15.1

Fixes:

  • Fix false-positive for self-referencing property access in property hooks (#311)
0.15.0

New features:

  • Dead properties detection (#277, #281, #291)
    • Never read and never written properties are detected
  • Property hooks full support (#281)
    • Now part of transitivity chain detection (both read & write)
  • Twig supports template parameters (#275)
    • Including transitively referenced ones
    • Supports:
      • Params passed to $controller->render('my.twig', ['param' => $viewModel]),
      • Params returned from #[Template] controller methods
      • Params rendered via Twig\Environment::render() and similar
  • Symfony:
    • AutowireLocator to support defaultPriorityMethod (#286, @alcohol)
    • Support #[Interact] attribute for commands (#288, @mjanser)
  • Nette tester
    • test* methods, setUp/tearDown, [@dataProvider](https://github.com/dataProvider) (#299)

Improvements:

  • Solution to partial analysis false positives over inline ignores (#292)
  • ApiPhpDocUsageProvider: only count phpdocs within analysed files (#284)

Breaking changes:

  • All dead members are detected by default (#301)
    • You can rollback to previous setup via:
parameters:
    shipmonkDeadCode:
        detect:
            deadEnumCases: false
            deadProperties:
                neverRead: false
                neverWritten: false
0.14.1

Fixes:

  • Fix infinite run for huge unused subtrees while groupping errors (#282)
0.14.0

New features:

  • Support PHP 8.5 features (#269)
  • Support phpbench entrypoints (#262, @simPod)
  • Support behat entrypoints (#267, @devbanana)
  • Support stream_wrapper_register magic (#266)

Improvements

  • All filepaths are now resolved relative to config file they reside (same as native PHPStan configs) (#219)
    • usageProviders.symfony.configDir
    • usageExcluders.tests.devPaths

Dependencies

  • phpstan/phpstan now requires ^2.1.23 (was ^2.1.12) (#254)

Breaking changes

  • All classes are final (#237)
0.13.5

Improvements:

  • Symfony & Doctrine (#258):
    • Support #[AsDoctrineListener]
    • Support #[AutoconfigureTag('doctrine.event_listener')]
0.13.4

Fixes:

  • Fix disabling dead methods detection (#257)
0.13.3

Improvements:

  • Symfony:
    • Support #[AsTransitionListenerWorkflow] and other Event listener attributes (#248, by @S1ructure)
    • Support #[AsMessageHandler] attribute (#247, by @S1ructure)
0.13.2

Fixes

  • Property hooks partial support; fix crash & false positives (#244)
0.13.1

Improvements

  • Symfony: support anonymous services in DIC (#238)
  • Support [@api](https://github.com/api) over enums and enum cases (#240)
  • Debug output not to report mixed over mixed usages caused by ReflectionClass<object>::getMethods() etc. (#241)
0.13.0

New features:

  • Detect dead enum cases (#197); off by default, enable by:
parameters:
    shipmonkDeadCode:
        detect:
            deadEnumCases: true

Fixes

  • Fix false positive when [@final](https://github.com/final) class is inherited (#233)
  • Fix debug output for overridden built-in methods (#234)

Breaking changes:

  • ClassMemberRef is now generic, you may need to update phpdocs of those
  • ClassConstantRef constructor now requires TrinaryLogic $isEnumCase argument

Dependencies

  • phpstan/phpstan now requires ^2.1.12 (was ^2.1.9)
0.12.4

Fixes:

  • Detect also overriden vendor constants (#225)
0.12.3

Fixes:

  • Fix false positive with interface parent (#221)
0.12.2

Fixes

  • tests excluder not to exclude mixed usages in tests (#214)
  • Fix usageProviders.symfony.configDir wiring (#216)
0.12.1

Improvements:

  • PHPUnit: support #[DataProviderExternal] (#212)
0.12.0

New features:

0.11.1

Fixes:

  • Fix custom devPaths config for tests excluder (#202)
  • Fix detection of absolute paths in composer.json for tests excluder (#203)
  • Drop provided usage class existence validation (#201)
0.11.0

New features

  • Support unknown member names like $foo->$unknown() (#189)
    • Such call marks all methods of $foo as used (including possible descendants, ancestors, traits, ...)
  • Reflection provider:
    • Usages like ReflectionClass->getMethods() now mark alive also methods of descendants (#189)
    • Support calls over unbounded ReflectionClass<object> (#193)
      • e.g. $anyObjectReflection->getMethod('foo') marks all foo methods of all types as alive
      • Can be disabled with usageOverMixed excluder
  • New Twig provider:
    • Support #[AsTwigFilter], #[AsTwigFunction], #[AsTwigTest] and new TwigFilter(..., callback) counterparts (#194, @zacharylund)

Fixes:

  • Fix origin file reference for traits (#190)
  • Report dead method line at its name (#192)
  • Fix mixed calls diagnostics when custom excluder is used (#196)

Breaking changes:

- #[Deprecated] // [@phpstan-ignore](https://github.com/phpstan-ignore) shipmonk.deadMethod
- public function someMethod(): void
+ #[Deprecated]
+ public function someMethod(): void // [@phpstan-ignore](https://github.com/phpstan-ignore) shipmonk.deadMethod
0.10.2

Improvements:

  • Symfony:
  • Doctrine:
    • detect repositoryMethod in #[UniqueEntity] (#184)

Fixes:

  • Autoremove: fix removal of transitively dead constants (#183)
0.10.1

Improvements

  • Debug: Changing references not to invalidate result cache (#169)
  • Autoremove: warn about kept excluded usages (#175)
 • Removed method UserFacade::deadMethod
   ! Excluded usage at tests/User/UserFacadeTest.php:241 left intact
  • Improve descendant detection for const fetches (#176)

Dependencies

  • phpstan/phpstan now requires ^2.1.9 (was ^2.1.7) (#169)
0.10.0

New features:

  • Allow debugging of usages (#165, #172):
parameters:
    shipmonkDeadCode:
        debug:
            usagesOf:
                - App\User\Entity\Address::__construct

with -vvv outputs e.g.:

App\User\Entity\Address::__construct
|
| Marked as alive by:
| entry virtual usage from ShipMonk\PHPStan\DeadCode\Provider\SymfonyUsageProvider (Route method via #[Route] attribute)
|   calls App\User\RegisterUserController::__invoke:36 
|     calls App\User\UserFacade::registerUser:142
|       calls App\User\Entity\Address::__construct
|
| Found 2 usages:
|  • src/User/UserFacade.php:142
|  • tests/User/Entity/AddressTest.php:64 - excluded by tests excluder
  • Improved possible descendant detection (#151)
    • e.g. new Foo->method() does not mark method as used on Foo children anymore

Improvements:

  • Skip private constructors only when those have zero params (#159)
  • Reduce result cache size (#168)
  • Support Symfony's defaultIndexMethod on AutowireLocator/AutowireIterator attribute (#161, @ruudk)

Dependencies

  • Requires phpstan/phpstan ^2.1.7 (was ^2.0.0) (#151)

Breaking changes

  • ClassMemberUsage now requires UsageOrigin, not optionally ClassMethodRef (#165)
  • UsageOriginDetector was removed (#165)
    • use either UsageOrigin::createRegular or UsageOrigin::createVirtual
  • Virtual usages emitted by ReflectionBasedMemberUsageProvider now require note (#171)
    • true => VirtualUsageData::withNote('why considered used')
    • false => null
  • parameter trackMixedAccess was replaced with excluder (#167)
parameters:
    shipmonkDeadCode:
-         trackMixedAccess: false
+         usageExcluders:
+           usageOverMixed:
+               enabled: true
0.9.2

Fixes:

  • TestsUsageExcluder: fix path normalization for phar files (#155)
0.9.1

Fixes

  • TestsUsageExcluder: normalize provided paths (#149)
0.9.0

New features:

  • Members used only in tests can be reported as dead (#139)
parameters:
    shipmonkDeadCode:
        usageExcluders:
            tests:
                enabled: true # off by default
  • Custom usage exclusions (#139)
    • via MemberUsageExcluder interface

Fixes:

  • Fix false positives in indirect usage edgecases (#141)
  • Fix transitive member reported repeatedly in a dead group when called multiple times (#143)
  • Fix usage of symbols not available on PHP 7.4 (#145)
  • Dead cycle representative error is ignorable now (no longer picked randomly) (#144)
0.8.1

Fixes:

  • Symfony: fix DIC filepath for phpstan-symfony 2.0.2 (#138)
0.8.0

New features

  • Symfony:
    • detect constants used in config yamls via !php const Foo\Bar::BAZ (#131)
    • detect methods called by DIC, e.g. factory: [Acme\SerializerFactory, create] (#128)

Fixes

  • Reflection:
    • support accessing members present only on descendants (#134)
    • proper transitivity detection (#135)
  • Fix missing parts of vendor class hierarchy (#136)
0.7.0

New features:

  • Full dead class constant detection support (#113)
    • Transitive detection (e.g. constant fetched in dead method is dead)
    • Usages over mixed (e.g. $unknown::CONST)
    • Auto-removal (via --error-format removeDeadCode)
    • Trait constants (available since PHP 8.2)
    • constant function (e.g. constant('PDO::ATTR_ERRMODE'))
    • customizable (e.g. you can extract !php/const Foo::BAR usages from your yamls)
  • AST-based usage providers (#117)
    • Just implement MemberUsageProvider
    • Allows to emit member usages based on e.g. methods calls
    • Handy for command buses, event systems, serializers and more
  • Detect reflection usages (#120)
    • e.g. $reflectionClass->getMethod('foo') marks foo method as used

Improvements:

  • Symfony & Doctrine: improve usage provider extendability (#121)
  • Symfony: precise detection of EventSubscriberInterface::getSubscribedEvents (#122)
  • Doctrine: precise detection of Doctrine\Common\EventSubscriber::getSubscribedEvents (#127)

Breaking changes:

  • Renames (to fit constant usages and AST-based providers):
# classes & methods
- `ShipMonk\PHPStan\DeadCode\Provider\MethodEntrypointProvider::getEntrypoints(): list<ReflectionMethod>` 
+ `ShipMonk\PHPStan\DeadCode\Provider\MemberUsageProvider::getUsages(): list<ClassMemberUsage>`

- `ShipMonk\PHPStan\DeadCode\Provider\SimpleMethodEntrypointProvider::isEntrypointMethod(): bool`
+ `ShipMonk\PHPStan\DeadCode\Provider\ReflectionBasedMemberUsageProvider::shouldMarkMethodAsUsed(): bool`

# neon config params
- `parameters.shipmonkDeadCode.entrypoints` 
+ `parameters.shipmonkDeadCode.usageProviders`

- `parameters.shipmonkDeadCode.trackCallsOnMixed` 
+ `parameters.shipmonkDeadCode.trackMixedAccess`

# neon service tag 
- `shipmonk.deadCode.entrypointProvider`
+ `shipmonk.deadCode.memberUsageProvider`
0.6.0

Dependencies

  • requires phpstan/phpstan 2.0
0.5.1

Fixes:

  • Disable mixed calls diagnosis for trackMixedCalls: false (#109)
0.5.0

New features

  • Ability to automatically remove dead code (#103)
    • via vendor/bin/phpstan analyse --error-format removeDeadCode
  • Support calls over mixed (#105)
    • e.g. $unknownClass->method()

Dependencies

  • requires phpstan/phpstan 1.11.7 (was 1.11.0) (#107)
0.4.0

Major changes:

  • Dead cycles detection (#99)
    • Also, all transitively dead methods are reported within the first run:
 ------ ------------------------------------------------------------------------
  Line   src/App/Facade/UserFacade.php
 ------ ------------------------------------------------------------------------
  26     Unused App\Facade\UserFacade::updateUserAddress
         🪪  shipmonk.deadMethod
         💡 Thus App\Entity\User::updateAddress is transitively also unused
         💡 Thus App\Entity\Address::setPostalCode is transitively also unused
         💡 Thus App\Entity\Address::setCountry is transitively also unused
         💡 Thus App\Entity\Address::setStreet is transitively also unused

New features:

  • phpunit: support data providers in children classes (#97)
  • symfony: support #[AsCommand], #[AsController], Bundle children (#89)
  • doctrine: support EntityRepository constructor (#90)

Fixes:

  • vendor: properly detect vendor-originating methods (#101)
0.3.0

Major changes:

  • Performance boost ~20% (#74, #79)
  • EntrypointProvider interface changed (#74)
    • Just extend SimpleMethodEntrypointProvider for easy transition

New features

  • Support dead __clone methods (#80)

Fixes

  • Fix many trait related edgecases (#70, #75, #76, #78)
  • Fix missing nette provider in config (#81)
0.2.1

Fixes

  • Fix invalid file reported for non-overridden dead trait methods (#67)
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation