phpstan/phpstan-nette

v0.10 offsetGet in conflict with getComponent

solcik opened this issue · 11 comments

Hello,

thank you very much for v0.10.
I tried it right away in my project and found a lot of these errors.

 ------ ------------------------------------------------------------------------------
  Line   src/....php
 ------ ------------------------------------------------------------------------------
  43     Cannot access offset 'form' on Nette\ComponentModel\IComponent.
  59     Cannot access offset 'form' on Nette\ComponentModel\IComponent.
  86     Cannot access offset 'price' on Nette\ComponentModel\IComponent.
  87     Access to an undefined property Nette\ComponentModel\IComponent::$onSuccess.
 ------ ------------------------------------------------------------------------------

These were not shown in 0.9 and I think that conflict is between new handling of offsetGet and current dynamicReturnType for getComponent().

https://github.com/phpstan/phpstan-nette/blob/master/src/Type/Nette/ComponentModelDynamicReturnTypeExtension.php

https://github.com/nette/application/blob/v2.4.12/src/Application/UI/Component.php#L377-L386

If I change arrayAccess to get components to ->getComponent() method calls, errors go away.

Yes, I already replaced my codebase with ->getComponent() calls.
There is no way (and i think there is no plan for that) how to handle dynamic return type extension for array access/set/unset/...

@CzechBoy Hey, do you have some script or something how to do this change automatically?

@novjan I don't remember, but I replaced it with some regex.

Ok, thank you.
Anyway ... do you have some plans about it @ondrejmirtes ?

I just had an idea how to implement this in an elegant way:

Feel free to test it now, it will be released along with PHPStan 0.10.2 in a few days 😊

@ondrejmirtes Hi. It looks that it works only for first offset.

This is ok:

$this['form']->setDefaults([]);

This is ok:

$this['form-checkbox']->setDefaultValue(TRUE)

This is error:

$this['form']['checkbox']->setDefaultValue(TRUE)

@ondrejmirtes Small example:

protected function createComponentFormData()
{
	$isEdit = TRUE;
	$form = new \Nette\Application\UI\Form;
	$form->addText('text');

	if ($isEdit) {
		$form['form']->addRule($form::FILLED); // Call to an undefined method Nette\ComponentModel\IComponent::addRule().
	}

	$data = $form->addContainer('data');
	$data->addText('text2');

	$form['data']['text2']->setDefaultValue('text'); // Cannot access offset 'text2' on Nette\ComponentModel\IComponent.
}

PHPStan has no way of knowing the type of $form['data']['text2']. It only works with createComponentFoo style factories.

Use this pattern:

	$data = $form->addContainer('data');
	$text2 = $data->addText('text2');
	$text2->setDefaultValue('text');

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.