Skip to content

Comments

Add proper generic type annotations (fixes missingType.generics)#19200

Open
dereuromark wants to merge 13 commits intocakephp:5.xfrom
dereuromark:fix/phpstan-view-generic-types
Open

Add proper generic type annotations (fixes missingType.generics)#19200
dereuromark wants to merge 13 commits intocakephp:5.xfrom
dereuromark:fix/phpstan-view-generic-types

Conversation

@dereuromark
Copy link
Member

@dereuromark dereuromark commented Jan 17, 2026

Summary

This PR adds proper generic type annotations to fix PHPStan missingType.generics errors instead of ignoring them globally.

Progress

Metric Before After
missingType.generics errors 405 0
Total errors 405+ 69

The 69 remaining errors are different types (return.type, argument.type, generics.interfaceConflict) not related to the original missingType.generics ignore rule.

Files Modified

40 files across these subsystems:

  • View: Helper, HelperRegistry, Cell, ViewBuilder, ViewVarsTrait, Widget classes
  • Cache: CacheEngine, CacheRegistry, Cache.php
  • ORM: Table, Association, EagerLoader, Marshaller, Behavior classes
  • Database: Query, QueryFactory
  • Datasource: FactoryLocator, Paginator classes
  • Event: EventManager, EventDispatcherTrait
  • Console: BaseCommand, HelpCommand
  • Http: BaseApplication, BodyParserMiddleware
  • Utility: Hash
  • Core: BasePlugin, PluginInterface
  • Controller: Controller, Component

Approach

For each generic class/interface:

  1. Add @template annotation to define type parameters
  2. Use ClassName<TemplateType> in PHPDoc @param, @return, @var
  3. Add @extends/@implements annotations to subclasses
  4. Add @phpstan-ignore missingType.generics only for truly self-referential cases

Status

Ready for review. All missingType.generics errors are fixed, allowing removal of the global ignore rule from phpstan.neon.dist.

…enerics

This is a work-in-progress to properly specify generic types instead of
ignoring the missingType.generics errors in PHPStan.

Changes include:
- Add @template annotations to Helper, View subclasses, Cache classes
- Add proper generic type parameters to method signatures
- Fix Collection, ORM, Event system generic types

Progress: ~210 of 405 errors fixed (52%)

Remaining work needed for complete fix.
@dereuromark dereuromark added this to the 5.3.2 milestone Jan 17, 2026
Complete the fix for generic type annotations by:
- Add generic types to Association.php methods (attachTo, find, etc.)
- Add @phpstan-ignore for self-referential generics in EventDispatcherTrait
- Fixes all remaining missingType.generics errors

Remaining 69 errors are different types (return.type, argument.type,
generics.interfaceConflict) not related to the original missingType.generics issue.
@dereuromark dereuromark changed the title WIP: Add proper generic type annotations (fixes missingType.generics) Add proper generic type annotations (fixes missingType.generics) Jan 17, 2026
* @phpstan-ignore missingType.generics
*/
public function dispatchEvent(string $name, array $data = [], ?object $subject = null): EventInterface
public function dispatchEvent(string $name, array $data = [], ?object $subject = null): EventInterface // @phpstan-ignore missingType.generics
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather add these kind of ignore statements via the basline file instead of doing them inline

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to make them visible first, maybe we can fix some of them up.
Then we can still move them to baseline.

- Add @phpstan-ignore comments for Collection return type mismatches
- Add path-specific ignores for generics.interfaceConflict in TreeIterator/TreePrinter
- Add path-specific ignores for argument.type covariance issues in Cache/ORM
- Use consistent SelectQuery generic types in Association.php
- Cache.php: inline ignore for NullEngine fallback
- TableRegistry.php: inline ignore for TableLocator
- bootstrap.php: inline ignore for TableLocator

generics.interfaceConflict must remain in config (PHPStan limitation
for class-level interface conflicts)
@dereuromark
Copy link
Member Author

@rochamarcelo what do you think?

/**
* Print out command list
*
* @extends \Cake\Console\BaseCommand<\Cake\Console\Command\HelpCommand>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit strange, but if it works , it works.

@rochamarcelo
Copy link
Contributor

It looks good.

Autocomplete works for collections on PHPStorm when using the result of $collection->filter() in foreach loop.

I got this with SelectQuery: ' variable $query contains generic class Cake\ORM\Query\SelectQuery but does not specify its types: TSubject'

- Remove unused import EntityInterface from EagerLoader
- Remove @inheritdoc when combined with @param/@return (coding standard violation)
- Add proper type hints and @param annotations
@dereuromark dereuromark force-pushed the fix/phpstan-view-generic-types branch from f195061 to 6650705 Compare January 18, 2026 12:41
@dereuromark
Copy link
Member Author

Fixed! Using {@inheritDoc} (with curly braces) instead of removing it entirely. This preserves the inherited documentation while satisfying phpcs. Thanks for catching this @ADmad!

@rochamarcelo
Copy link
Contributor

Okay, I didn't expected the trait requires to override @return from CollectionInterface.

Looks good.

@dereuromark
Copy link
Member Author

@rochamarcelo To fix the PHPStan error about SelectQuery not specifying its types, you need to add the generic type annotation:

/** @var \Cake\ORM\Query\SelectQuery<\App\Model\Entity\YourEntity> $query */
$query = $this->YourTable->find();

Or for array results (when using ->disableHydration()):

/** @var \Cake\ORM\Query\SelectQuery<array> $query */

The TSubject template parameter expects either an entity class or array.

@dereuromark dereuromark marked this pull request as ready for review January 22, 2026 16:40
@dereuromark
Copy link
Member Author

So, how do we move forward with the inline ignores?
Are some of them solvable?
Should we move them to baseline? Or keep them visible on the specific lines?

@rochamarcelo
Copy link
Contributor

I prefer a baseline file but no hard opnion on this.

Btw, about dispatchEvent not sure if is relevant but in any class we can use any type as subject not only the main class, for example in a command I could have dispatchEvent('someEvent', [], $apiClient), since $apiClient is not a Command it will raise a phpstan error

@rochamarcelo
Copy link
Contributor

…view

Suggestions  for generic usage on view
@dereuromark
Copy link
Member Author

@rochamarcelo Thx, merged in.
Anything else missing from your side?

@rochamarcelo
Copy link
Contributor

@dereuromark I forgot to update command dereuromark#2

rochamarcelo and others added 2 commits February 1, 2026 19:39
* use static instead of self used generic template

* use static instead of self used generic template
@dereuromark dereuromark requested a review from markstory February 5, 2026 08:16
@dereuromark
Copy link
Member Author

@ADmad How shall we proceed here?

@LordSimal
Copy link
Contributor

I'd say if we get the CI green this is fine to merge since its a major step into better static analysis

@ADmad
Copy link
Member

ADmad commented Feb 17, 2026

@ADmad How shall we proceed here?

We can merge once CI is green.

- Resolve merge conflict in CollectionTrait.php by keeping both generic
  templates and @require-implements annotation
- Fix Association::find() return type to SelectQuery<EntityInterface|array>
  to be compatible with BelongsToMany::find() override
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants