Skip to content

Conversation

@shakaran
Copy link
Contributor

@shakaran shakaran commented Dec 9, 2025

Type Safety and PHPStan Improvements

  • Added the tests directory to PHPStan analysis in phpstan.neon, ensuring static analysis coverage for test files.
  • Updated @phpstan-param docblock in MenuManipulator.php to allow object types in traversables and arrays, improving type safety for menu items.

Improving the reliability and correctness of the test suite for menu iterators, filters, and factory logic, as well as enhancing type safety in PHPStan configuration and docblocks.

The main changes include refactoring tests to ensure proper variable initialization and null checks, updating iterator usage for consistency, and making minor improvements to type annotations and test mocks.

Test Logic and Mock Enhancements

  • Fixed test logic in MenuFactoryTest by correcting extension mock expectations and replacing the custom containsCustom helper with direct usage of containsEqual, simplifying test assertions.
  • Improved callback voter test data provider by using static closures and clarifying return types in CallbackVoterTest.

Menu Item Getter/Setter Correction

  • Corrected child menu assignment and retrieval in MenuItemGetterSetterTest to use associative arrays, matching expected API usage and ensuring proper test coverage.

@garak garak requested a review from stof December 9, 2025 08:21
@garak
Copy link
Collaborator

garak commented Dec 9, 2025

* Updated `@phpstan-param` docblock in `MenuManipulator.php` to allow `object` types in traversables and arrays, improving type safety for menu items.

Why should we accept a generic object? It seems to me that your change decreases type safety rather than increasing it.

Copy link
Contributor

@derrabus derrabus left a comment

Choose a reason for hiding this comment

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

I think you're trying to solve too many problems at once. Running static analysis on the tests might be a good idea by itself, but let's not combine it with raising the PHPStan level.

Comment on lines 14 to 21
$pt1 = $this->pt1;
$this->assertNotNull($pt1);
$ch2 = $this->ch2;
$this->assertNotNull($ch2);
$gc1 = $this->gc1;
$this->assertNotNull($gc1);
$menu = $this->menu;
$this->assertNotNull($menu);
Copy link
Contributor

Choose a reason for hiding this comment

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

Those assertions don't make sense. We'd be testing our own test setup.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that the assertions are needed, since if I remove for example for pt1, it produces:

  Line   tests/Knp/Menu/Tests/Iterator/CurrentItemFilterIteratorTest.php  
 ------ ----------------------------------------------------------------- 
  :20    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject 

This is mostly because ItemInterface declaration allows null, so phpstan could not infer that is non empty via the extends in MenuTestCase.

So the asserts remove the uncertain in this case and also the phpstan error. Let me know if you want or know another way to skip this error

Copy link
Contributor

@derrabus derrabus Dec 9, 2025

Choose a reason for hiding this comment

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

I understand which PHPStan error your change is coming from. It's just that cluttering the codebase with assertions is not the only (and rarely the best) way to fix them.

And from a sematic point of view: PHPUnit assertions are supposed to validate the state produced by the code under test. Here you're running a PHPUnit assertion before even testing anything.

Copy link
Contributor Author

@shakaran shakaran Dec 9, 2025

Choose a reason for hiding this comment

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

The only way to avoid this, I think that it should be changing and remove in MenuTestCase all the |null or ? per attribute class and avoiding to assign as null in the tearDown() of MenuTestCase, do you want that way instead this? That should clean out all assetNotNull warnings

Copy link
Contributor

Choose a reason for hiding this comment

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

That sounds promising.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed in f1db5be

Comment on lines 12 to 26
protected ?ItemInterface $menu;

protected ItemInterface|null $pt1;
protected ?ItemInterface $pt1;

protected ItemInterface|null $ch1;
protected ?ItemInterface $ch1;

protected ItemInterface|null $ch2;
protected ?ItemInterface $ch2;

protected ItemInterface|null $ch3;
protected ?ItemInterface $ch3;

protected ItemInterface|null $pt2;
protected ?ItemInterface $pt2;

protected ItemInterface|null $ch4;
protected ?ItemInterface $ch4;

protected ItemInterface|null $gc1;
protected ?ItemInterface $gc1;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is just sugar syntax for union types, very common in my opinion in a lot projects

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, so the change is abosutely unrealted to and irrelevant for the goal that you're trying to achieve? Let's revert it then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed in f1db5be

@shakaran
Copy link
Contributor Author

shakaran commented Dec 9, 2025

* Updated `@phpstan-param` docblock in `MenuManipulator.php` to allow `object` types in traversables and arrays, improving type safety for menu items.

Why should we accept a generic object? It seems to me that your change decreases type safety rather than increasing it.

The exact change is:

- * @phpstan-param string|ItemInterface|array<int|string, string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface>|\Traversable<string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface>|null $subItem
+ * @phpstan-param string|ItemInterface|array<int|string, string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface|object>|\Traversable<string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface|object>|null $subItem

Adding |object will allow pass the phpstan error. In this case I don't know another way to resolve this, but it is only affecting to phpstan side. I am open to make a change if you suggest a better way

@shakaran
Copy link
Contributor Author

shakaran commented Dec 9, 2025

I think you're trying to solve too many problems at once. Running static analysis on the tests might be a good idea by itself, but let's not combine it with raising the PHPStan level.

phpstan level is not raised in this PR, as you can see in master is level 8 https://github.com/KnpLabs/KnpMenu/blob/master/phpstan.neon#L2

I am just adding tests folder, and resolving the errors which appear in level 8 for tests folder

@stof
Copy link
Collaborator

stof commented Dec 9, 2025

Adding |object will allow pass the phpstan error. In this case I don't know another way to resolve this, but it is only affecting to phpstan side.

no it is not only affecting phpstan. It changes the public API of the class, which affects what we need to cover with BC.

@shakaran
Copy link
Contributor Author

shakaran commented Dec 9, 2025

Adding |object will allow pass the phpstan error. In this case I don't know another way to resolve this, but it is only affecting to phpstan side.

no it is not only affecting phpstan. It changes the public API of the class, which affects what we need to cover with BC.

what would you suggest instead?

  1. Avoid the warning just ignore it and revert removing |object in phpstan definition
  2. Cover with BC in next release
  3. Other that you suggest

{
$count = 0;
foreach ($this->pt1 as $key => $value) {
foreach ($this->pt1->getChildren() as $key => $value) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why ? This should not be needed. This test is even meant to cover the iterable API of the menu IMO, based on its name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed at 2ccbffb

yield 'skipping' => [fn (): ?bool => null, null];
yield 'matching' => [[self::class, 'matchingCallable'], true];
yield 'not matching' => [[self::class, 'notMatchingCallable'], false];
yield 'skipping' => [[self::class, 'skippingCallable'], null];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally was


Line CallbackVoterTest.php


:60 Anonymous function never returns null so it can be removed from the return type.
🪪 return.unusedType
:61 Anonymous function never returns null so it can be removed from the return type.
🪪 return.unusedType


But I over complicate doing a static function instead of closure. Reverting only solving the nullables at cf50474

$this->assertCount(3, $this->pt1->getChildren());
$this->assertCount(1, $this->pt2->getChildren());
$this->assertCount(1, $this->ch4->getChildren());
$this->assertEquals('Grandchild 1', $this->gc1->getName());
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is totally changing the assertions being done. It does not test the integrity of the ArrayAccess anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed at 584ec1e and other cases for ensure the ArrayAccess instead getChildren

$this->menu->addChild('Child Menu');
$this->assertEquals('Child Menu', $this->menu['Child Menu']->getName());
$this->assertNull($this->menu['Fake']);
$this->assertEquals('Child Menu', $this->menu->getChildren()['Child Menu']->getName());
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not testing the ArrayAccess implementation anymore, while this is what the test is about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed at 2d5281f

abstract class MenuTestCase extends TestCase
{
protected ItemInterface|null $menu;
protected ?ItemInterface $menu;
Copy link
Collaborator

Choose a reason for hiding this comment

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

To me, the right fix is to make all those properties non-nullable and removing the tearDown method that assigns them to null (which is useless as the Test object itself is dereferenced after it is tear down so everything will still be collected)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed in f1db5be

$names = [];
// FilterIterator expects an Iterator implementation explicitly, not an IteratorAggregate.
$iterator = new CurrentItemFilterIterator($this->menu->getIterator(), new Matcher());
$iterator = new CurrentItemFilterIterator(new \ArrayIterator($this->menu->getChildren()), new Matcher());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd rather use new IteratorIterator($this->menu), which is the built-in way in PHP to wrap a Traversable into an Iterator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed at 3f6fef6

@stof
Copy link
Collaborator

stof commented Dec 9, 2025

As I don't know what phpstan warning you are trying to fix, I cannot provide alternative fixes. Please provide the warning being reported.

@shakaran
Copy link
Contributor Author

shakaran commented Dec 9, 2025

As I don't know what phpstan warning you are trying to fix, I cannot provide alternative fixes. Please provide the warning being reported.

Full list of errors that I am fixing (around 283) over master in folder test directories:

$ ./vendor/bin/phpstan analyse --level=8 ./tests/
Note: Using configuration file phpstan.neon.
 28/28 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Iterator/CurrentItemFilterIteratorTest.php                                                                                                                                   
 ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :14    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :15    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :16    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :20    Cannot call method getIterator() on Knp\Menu\ItemInterface|null.                                                                                                                            
         🪪  method.nonObject                                                                                                                                                                        
  :20    Parameter #1 $iterator of class Knp\Menu\Iterator\CurrentItemFilterIterator constructor expects Iterator<TKey, Knp\Menu\ItemInterface>, Traversable<string, Knp\Menu\ItemInterface> given.  
         🪪  argument.type                                                                                                                                                                           
  :31    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :32    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :33    Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.                                                                                                                             
         🪪  method.nonObject                                                                                                                                                                        
  :37    Parameter #1 $iterator of class Knp\Menu\Iterator\RecursiveItemIterator constructor expects Traversable<string, Knp\Menu\ItemInterface>, Knp\Menu\ItemInterface|null given.                 
         🪪  argument.type                                                                                                                                                                           
 ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Iterator/DisplayedItemFilterIteratorTest.php                                                                                                                  
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :13    Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                                                              
         🪪  method.nonObject                                                                                                                                                         
  :14    Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                                                              
         🪪  method.nonObject                                                                                                                                                         
  :15    Cannot call method setDisplayChildren() on Knp\Menu\ItemInterface|null.                                                                                                      
         🪪  method.nonObject                                                                                                                                                         
  :19    Parameter #1 $iterator of class Knp\Menu\Iterator\RecursiveItemIterator constructor expects Traversable<string, Knp\Menu\ItemInterface>, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                                                            
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Iterator/IteratorTest.php                                                                                                                                                      
 ------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :14    Argument of an invalid type Knp\Menu\ItemInterface|null supplied for foreach, only iterables are supported.                                                                                   
         🪪  foreach.nonIterable                                                                                                                                                                       
  :31    Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  method.nonObject                                                                                                                                                                          
  :34    Parameter #1 $iterator of class Knp\Menu\Iterator\RecursiveItemIterator constructor expects Traversable<string, Knp\Menu\ItemInterface>, Knp\Menu\ItemInterface|null given.                   
         🪪  argument.type                                                                                                                                                                             
  :44    Parameter #1 $iterator of class Knp\Menu\Iterator\RecursiveItemIterator constructor expects Traversable<string, Knp\Menu\ItemInterface>, Knp\Menu\ItemInterface|null given.                   
         🪪  argument.type                                                                                                                                                                             
  :54    Parameter #1 $iterator of class Knp\Menu\Iterator\RecursiveItemIterator constructor expects Traversable<int, Knp\Menu\ItemInterface>, ArrayIterator<int, Knp\Menu\ItemInterface|null> given.  
         🪪  argument.type                                                                                                                                                                             
 ------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Matcher/Voter/CallbackVoterTest.php                                
 ------ ---------------------------------------------------------------------------------- 
  :60    Anonymous function never returns null so it can be removed from the return type.  
         🪪  return.unusedType                                                             
  :61    Anonymous function never returns null so it can be removed from the return type.  
         🪪  return.unusedType                                                             
 ------ ---------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/MenuFactoryTest.php                                                                                             
 ------ ------------------------------------------------------------------------------------------------------------------------------- 
  :62    Call to function method_exists() with $this(Knp\Menu\Tests\MenuFactoryTest) and 'contains' will always evaluate to false.      
         🪪  function.impossibleType                                                                                                    
  :66    Call to function method_exists() with $this(Knp\Menu\Tests\MenuFactoryTest) and 'containsEqual' will always evaluate to true.  
         🪪  function.alreadyNarrowedType                                                                                               
 ------ ------------------------------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/MenuItemGetterSetterTest.php                                                                                                                      
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :174   Parameter #1 $children of method Knp\Menu\ItemInterface::setChildren() expects array<string, Knp\Menu\ItemInterface>, array<int, Knp\Menu\ItemInterface> given.  
         🪪  argument.type                                                                                                                                                
  :185   Cannot call method setName() on Knp\Menu\ItemInterface|null.                                                                                                     
         🪪  method.nonObject                                                                                                                                             
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/MenuItemTreeTest.php                                                                                                      
 ------ ----------------------------------------------------------------------------------------------------------------------------------------- 
  :16    Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :17    Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.                                                                        
         🪪  offsetAccess.notFound                                                                                                                
  :17    Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :18    Offset 'Parent 2' might not exist on Knp\Menu\ItemInterface|null.                                                                        
         🪪  offsetAccess.notFound                                                                                                                
  :18    Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :19    Offset 'Child 4' might not exist on Knp\Menu\ItemInterface|null.                                                                         
         🪪  offsetAccess.notFound                                                                                                                
  :19    Offset 'Parent 2' might not exist on Knp\Menu\ItemInterface|null.                                                                        
         🪪  offsetAccess.notFound                                                                                                                
  :19    Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :20    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :20    Offset 'Child 4' might not exist on Knp\Menu\ItemInterface|null.                                                                         
         🪪  offsetAccess.notFound                                                                                                                
  :20    Offset 'Grandchild 1' might not exist on Knp\Menu\ItemInterface|null.                                                                    
         🪪  offsetAccess.notFound                                                                                                                
  :20    Offset 'Parent 2' might not exist on Knp\Menu\ItemInterface|null.                                                                        
         🪪  offsetAccess.notFound                                                                                                                
  :25    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :26    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :27    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :28    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :29    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :34    Cannot call method getRoot() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :35    Cannot call method getRoot() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :36    Cannot call method getRoot() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :41    Cannot call method isRoot() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :42    Cannot call method isRoot() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :43    Cannot call method isRoot() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :48    Cannot call method getParent() on Knp\Menu\ItemInterface|null.                                                                           
         🪪  method.nonObject                                                                                                                     
  :49    Cannot call method getParent() on Knp\Menu\ItemInterface|null.                                                                           
         🪪  method.nonObject                                                                                                                     
  :50    Cannot call method getParent() on Knp\Menu\ItemInterface|null.                                                                           
         🪪  method.nonObject                                                                                                                     
  :56    Parameter #1 $child of method Knp\Menu\MenuItem::addChild() expects Knp\Menu\ItemInterface|string, Knp\Menu\ItemInterface|null given.    
         🪪  argument.type                                                                                                                        
  :58    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :59    Cannot call method getLevel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :61    Cannot call method getRoot() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :62    Cannot call method getRoot() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :63    Cannot call method isRoot() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :65    Cannot call method getParent() on Knp\Menu\ItemInterface|null.                                                                           
         🪪  method.nonObject                                                                                                                     
  :70    Cannot call method isFirst() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :71    Cannot call method isFirst() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :72    Cannot call method isFirst() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :73    Cannot call method isFirst() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :78    Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :79    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :80    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :81    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :82    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :83    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :88    Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :89    Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :90    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :91    Cannot call method actsLikeFirst() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :96    Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :97    Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :98    Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :99    Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :104   Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :105   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :106   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :107   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :108   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :109   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :114   Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :115   Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.                                                                          
         🪪  method.nonObject                                                                                                                     
  :116   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :117   Cannot call method actsLikeLast() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :122   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :123   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :123   Offset 'Child Menu' might not exist on Knp\Menu\ItemInterface|null.                                                                      
         🪪  offsetAccess.notFound                                                                                                                
  :124   Offset 'Fake' might not exist on Knp\Menu\ItemInterface|null.                                                                            
         🪪  offsetAccess.notFound                                                                                                                
  :126   Knp\Menu\ItemInterface|null does not accept string.                                                                                      
         🪪  offsetAssign.valueType                                                                                                               
  :127   Parameter #1 $object of function get_class expects object, string given.                                                                 
         🪪  argument.type                                                                                                                        
  :128   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :128   Offset 'New Child' might not exist on Knp\Menu\ItemInterface|null.                                                                       
         🪪  offsetAccess.notFound                                                                                                                
  :129   Cannot call method getLabel() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :129   Offset 'New Child' might not exist on Knp\Menu\ItemInterface|null.                                                                       
         🪪  offsetAccess.notFound                                                                                                                
  :132   Offset 'New Child' might not exist on Knp\Menu\ItemInterface|null.                                                                       
         🪪  offsetAccess.notFound                                                                                                                
  :137   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :139   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :140   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :143   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :148   Cannot call method getChildren() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :150   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :155   Cannot call method getFirstChild() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :157   Cannot call method getChildren() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :159   Cannot call method getFirstChild() on Knp\Menu\ItemInterface|null.                                                                       
         🪪  method.nonObject                                                                                                                     
  :164   Cannot call method getLastChild() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :166   Cannot call method getChildren() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :168   Cannot call method getLastChild() on Knp\Menu\ItemInterface|null.                                                                        
         🪪  method.nonObject                                                                                                                     
  :195   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :196   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :201   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :202   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :203   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :204   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :205   Cannot call method removeChild() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :206   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :207   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :207   Cannot call method isFirst() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :208   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :208   Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :213   Cannot call method removeChild() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :214   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :219   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :220   Cannot call method removeChild() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :221   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :222   Parameter #2 $haystack of method PHPUnit\Framework\Assert::assertCount() expects Countable|iterable, Knp\Menu\ItemInterface|null given.  
         🪪  argument.type                                                                                                                        
  :224   Cannot call method isLast() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :229   Cannot call method setName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :230   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :231   Cannot call method getChildren() on Knp\Menu\ItemInterface|null.                                                                         
         🪪  method.nonObject                                                                                                                     
  :232   Cannot call method getChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
  :239   Cannot call method setName() on Knp\Menu\ItemInterface|null.                                                                             
         🪪  method.nonObject                                                                                                                     
  :245   Cannot call method getUri() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :246   Cannot call method getUri() on Knp\Menu\ItemInterface|null.                                                                              
         🪪  method.nonObject                                                                                                                     
  :246   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                           
         🪪  offsetAccess.notFound                                                                                                                
  :251   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                            
         🪪  method.nonObject                                                                                                                     
 ------ ----------------------------------------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Provider/ArrayAccessProviderTest.php                                                            
 ------ --------------------------------------------------------------------------------------------------------------- 
  :23    ArrayObject<*NEVER*, *NEVER*> does not accept Knp\Menu\ItemInterface&PHPUnit\Framework\MockObject\MockObject.  
         🪪  offsetAssign.valueType                                                                                     
  :32    ArrayObject<*NEVER*, *NEVER*> does not accept Closure.                                                         
         🪪  offsetAssign.valueType                                                                                     
  :33    Cannot access offset 'options' on object.                                                                      
         🪪  offsetAccess.nonOffsetAccessible                                                                           
 ------ --------------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Provider/LazyProviderTest.php                                                                                                                                                   
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :13    Parameter #1 $builders of class Knp\Menu\Provider\LazyProvider constructor expects array<string, array{Closure(): object, string}|(callable(): Knp\Menu\ItemInterface)>, array{first: Closure  
         (): void, second: Closure(): void} given.                                                                                                                                                      
         🪪  argument.type                                                                                                                                                                              
  :46    Parameter #1 $builders of class Knp\Menu\Provider\LazyProvider constructor expects array<string, array{Closure(): object, string}|(callable(): Knp\Menu\ItemInterface)>, array{broken: stdCla  
         ss} given.                                                                                                                                                                                     
         🪪  argument.type                                                                                                                                                                              
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Renderer/AbstractRendererTest.php                           
 ------ --------------------------------------------------------------------------- 
  :35    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :44    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :53    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :62    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :71    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :83    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :92    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :103   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :116   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :127   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :136   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :145   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :154   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :163   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :174   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :185   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :191   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :196   Cannot call method setAttribute() on Knp\Menu\ItemInterface|null.          
         🪪  method.nonObject                                                       
  :197   Cannot call method setAttribute() on Knp\Menu\ItemInterface|null.          
         🪪  method.nonObject                                                       
  :199   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :204   Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.            
         🪪  method.nonObject                                                       
  :206   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :216   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :238   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :255   Cannot call method setChildrenAttribute() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                                       
  :257   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :257   Offset 'Parent 2' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :262   Cannot call method setDisplayChildren() on Knp\Menu\ItemInterface|null.    
         🪪  method.nonObject                                                       
  :264   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :269   Cannot call method setDisplayChildren() on Knp\Menu\ItemInterface|null.    
         🪪  method.nonObject                                                       
  :269   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :271   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :276   Cannot call method setDisplay() on Knp\Menu\ItemInterface|null.            
         🪪  method.nonObject                                                       
  :276   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :278   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :284   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :290   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :296   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :301   Cannot call method setDisplayChildren() on Knp\Menu\ItemInterface|null.    
         🪪  method.nonObject                                                       
  :301   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :303   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :309   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :314   Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.            
         🪪  method.nonObject                                                       
  :314   Offset 'Child 1' might not exist on Knp\Menu\ItemInterface|null.           
         🪪  offsetAccess.notFound                                                  
  :314   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :316   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :321   Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.            
         🪪  method.nonObject                                                       
  :321   Offset 'Child 1' might not exist on Knp\Menu\ItemInterface|null.           
         🪪  offsetAccess.notFound                                                  
  :321   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :323   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :328   Cannot call method setCurrent() on Knp\Menu\ItemInterface|null.            
         🪪  method.nonObject                                                       
  :328   Offset 'Child 1' might not exist on Knp\Menu\ItemInterface|null.           
         🪪  offsetAccess.notFound                                                  
  :328   Offset 'Parent 1' might not exist on Knp\Menu\ItemInterface|null.          
         🪪  offsetAccess.notFound                                                  
  :330   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
  :337   Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.   
         🪪  method.nonObject                                                       
 ------ --------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Renderer/ArrayAccessProviderTest.php                                                                         
 ------ ---------------------------------------------------------------------------------------------------------------------------- 
  :23    ArrayObject<*NEVER*, *NEVER*> does not accept Knp\Menu\Renderer\RendererInterface&PHPUnit\Framework\MockObject\MockObject.  
         🪪  offsetAssign.valueType                                                                                                  
  :32    ArrayObject<*NEVER*, *NEVER*> does not accept Knp\Menu\Renderer\RendererInterface&PHPUnit\Framework\MockObject\MockObject.  
         🪪  offsetAssign.valueType                                                                                                  
 ------ ---------------------------------------------------------------------------------------------------------------------------- 

 ------ -------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Renderer/ListRendererTest.php                              
 ------ -------------------------------------------------------------------------- 
  :30    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.  
         🪪  method.nonObject                                                      
 ------ -------------------------------------------------------------------------- 

 ------ -------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Renderer/TwigRendererTest.php                              
 ------ -------------------------------------------------------------------------- 
  :31    Cannot call method render() on Knp\Menu\Renderer\RendererInterface|null.  
         🪪  method.nonObject                                                      
 ------ -------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Twig/HelperTest.php                             
 ------ --------------------------------------------------------------- 
  :271   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :273   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :274   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :275   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :275   Offset 'c2_2' might not exist on Knp\Menu\ItemInterface|null.  
         🪪  offsetAccess.notFound                                      
  :276   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :276   Offset 'c2_2' might not exist on Knp\Menu\ItemInterface|null.  
         🪪  offsetAccess.notFound                                      
  :277   Cannot call method addChild() on Knp\Menu\ItemInterface|null.  
         🪪  method.nonObject                                           
  :277   Offset 'c2_2' might not exist on Knp\Menu\ItemInterface|null.  
         🪪  offsetAccess.notFound                                      
  :281   Cannot call method getName() on Knp\Menu\ItemInterface|null.   
         🪪  method.nonObject                                           
 ------ --------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Twig/MenuExtensionTest.php                                                                                                                                              
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :24    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :30    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :37    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :43    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :50    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :56    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :62    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :68    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :75    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :80    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :86    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :92    Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :98    Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :106   Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :110   Call to an undefined method Knp\Menu\Util\MenuManipulator|PHPUnit\Framework\MockObject\MockObject::expects().                                                                          
         🪪  method.notFound                                                                                                                                                                    
  :116   Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :116   Parameter #4 $menuManipulator of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Util\MenuManipulator|null,                                               
         Knp\Menu\Util\MenuManipulator|PHPUnit\Framework\MockObject\MockObject given.                                                                                                           
         🪪  argument.type                                                                                                                                                                      
  :124   Call to an undefined method Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject::expects().                                                                      
         🪪  method.notFound                                                                                                                                                                    
  :130   Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :130   Parameter #3 $matcher of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Matcher\MatcherInterface|null,                                                   
         Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject given.                                                                                                       
         🪪  argument.type                                                                                                                                                                      
  :138   Call to an undefined method Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject::expects().                                                                      
         🪪  method.notFound                                                                                                                                                                    
  :144   Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :144   Parameter #3 $matcher of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Matcher\MatcherInterface|null,                                                   
         Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject given.                                                                                                       
         🪪  argument.type                                                                                                                                                                      
  :151   Call to an undefined method Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject::expects().                                                                                   
         🪪  method.notFound                                                                                                                                                                    
  :157   Call to an undefined method Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject::expects().                                                                      
         🪪  method.notFound                                                                                                                                                                    
  :163   Parameter #2 $helper of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Twig\Helper, Knp\Menu\Twig\Helper|PHPUnit\Framework\MockObject\MockObject given.  
         🪪  argument.type                                                                                                                                                                      
  :163   Parameter #3 $matcher of method Knp\Menu\Tests\Twig\MenuExtensionTest::getTemplate() expects Knp\Menu\Matcher\MatcherInterface|null,                                                   
         Knp\Menu\Matcher\MatcherInterface|PHPUnit\Framework\MockObject\MockObject given.                                                                                                       
         🪪  argument.type                                                                                                                                                                      
  :169   Parameter #1 $filename of function filemtime expects string, string|false given.                                                                                                       
         🪪  argument.type                                                                                                                                                                      
  :170   Parameter #1 $filename of function filemtime expects string, string|false given.                                                                                                       
         🪪  argument.type                                                                                                                                                                      
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   Knp/Menu/Tests/Util/MenuManipulatorTest.php                                                                                                                                                    
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  :22    Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::moveToFirstPosition() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :35    Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::moveToLastPosition() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                            
         🪪  argument.type                                                                                                                                                                              
  :48    Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::moveToPosition() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                                
         🪪  argument.type                                                                                                                                                                              
  :62    Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::slice() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                                         
         🪪  argument.type                                                                                                                                                                              
  :75    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :75    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :76    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :76    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :76    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :77    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :77    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :78    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :79    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :79    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :80    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :80    Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :93    Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::split() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                                         
         🪪  argument.type                                                                                                                                                                              
  :109   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :110   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :110   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :111   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :111   Cannot call method getName() on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  method.nonObject                                                                                                                                                                           
  :118   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getPathAsString() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                               
         🪪  argument.type                                                                                                                                                                              
  :119   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getPathAsString() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                               
         🪪  argument.type                                                                                                                                                                              
  :125   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                                                                                  
         🪪  method.nonObject                                                                                                                                                                           
  :126   Cannot call method addChild() on Knp\Menu\ItemInterface|null.                                                                                                                                  
         🪪  method.nonObject                                                                                                                                                                           
  :130   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :133   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :134   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :134   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :139   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :142   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :142   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :152   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :159   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :159   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :169   Offset '123' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :170   Offset '123' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                   
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :170   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :176   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :179   Offset 'child' might not exist on Knp\Menu\ItemInterface|null.                                                                                                                                 
         🪪  offsetAccess.notFound                                                                                                                                                                      
  :179   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :188   Parameter #1 $item of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects Knp\Menu\ItemInterface, Knp\Menu\ItemInterface|null given.                                           
         🪪  argument.type                                                                                                                                                                              
  :188   Parameter #2 $subItem of method Knp\Menu\Util\MenuManipulator::getBreadcrumbsArray() expects array<int|string, array{label: string, uri: string|null, item: Knp\Menu\ItemInterface|null}|floa  
         t|int|Knp\Menu\ItemInterface|string|null>|string|Traversable<mixed, array{label: string, uri: string|null, item: Knp\Menu\ItemInterface|null}|float|int|Knp\Menu\ItemInterface|string|null>|n  
         ull, array{stdClass} given.                                                                                                                                                                    
         🪪  argument.type                                                                                                                                                                              
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

                                                                                                                        
 [ERROR] Found 283 errors  

@shakaran
Copy link
Contributor Author

shakaran commented Dec 9, 2025

@stof @garak @derrabus All reviews are completed and checked now in this one. Waiting new input or merging. Thanks

Copy link
Collaborator

@stof stof left a comment

Choose a reason for hiding this comment

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

Many of the changes you made were done in response to the previous way of fixing access to nullable test properties.

I suggest that you start from the master branch again (potentially from the commit fixing the invalid phpdoc type which is based on it), make the properties non-nullable, and then work on the remaining phpstan errors (which will be a lot less than on the master branch), to avoid all those useless change in the PR diff.

* @param string|ItemInterface|array<int|string, mixed>|\Traversable<mixed>|null $subItem A string or array to append onto the end of the array
*
* @phpstan-param string|ItemInterface|array<int|string, string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface>|\Traversable<string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface>|null $subItem
* @phpstan-param string|ItemInterface|array<int|string, string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface|object>|\Traversable<string|int|float|null|array{label: string, uri: string|null, item: ItemInterface|null}|ItemInterface|object>|null $subItem
Copy link
Collaborator

Choose a reason for hiding this comment

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

This must be reverted. the place where phpstan is reported an error is inside testBreadcrumbsArrayInvalidData, which is specifically testing the runtime behavior when passing invalid data (as not all users of the library might be using static analysis to catch such usage, and the code has some defense against that in that case).

the proper way to fix the phpstan warning is to use @phpstan-expect-error to make phpstan aware that an error is expected in that line.

$this->gc1->setCurrent(true);
$pt1 = $this->pt1;
$ch2 = $this->ch2;
$gc1 = $this->gc1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Those changes should be reverted

$this->gc1->setCurrent(true);
$pt1 = $this->pt1;
$ch2 = $this->ch2;
$gc1 = $this->gc1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Those changes should be reverted

$this->ch4->setDisplayChildren(false);
$ch1 = $this->ch1;
$ch2 = $this->ch2;
$ch4 = $this->ch4;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Those changes should be reverted

{
public function testIterator(): void
{
$pt1 = $this->pt1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Those changes should be reverted

/** @var Helper&MockObject $helper */
$helper = $helperMock;
$matcher = null;
$manipulator = null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be reverted IMO.

* @param array<string> $methods
*/
private function getHelperMock(array $methods): MockObject|Helper
private function getHelperMock(array $methods): MockObject
Copy link
Collaborator

Choose a reason for hiding this comment

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

this should be documented as Helper&MockObject as return type instead, which is the proper type.

Copy link
Collaborator

Choose a reason for hiding this comment

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

same for the other mock methods below (with the corresponding type of course)

{
$manipulator = new MenuManipulator();
$sliced = $manipulator->slice($this->pt1, $offset, $length);
$pt1 = $this->pt1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be reverted.


$ch1 = $this->ch1;
$ch2 = $this->ch2;
$ch3 = $this->ch3;
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be reverted.

->with(['foo' => 'bar'])
->willReturn(['uri' => 'foobar']);
->with(['uri' => 'foobar'])
->willReturnArgument(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This changes the behavior of the test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants