phpstan / phpstan-nette Goto Github PK
View Code? Open in Web Editor NEWNette Framework class reflection extension for PHPStan & framework-specific rules
License: MIT License
Nette Framework class reflection extension for PHPStan & framework-specific rules
License: MIT License
I cannot make the phpstan-nette work with nette 2.4 and php 7.2. As I can see from composer.json only 2.3 and 3.0 is supported?
After update Nette to last version with PHP 7.4 support. It is not compatible with last version of https://github.com/nette/php-generator. It is because of this change:
nette/php-generator@6e1cc8d
Now createObject
is part of Nette\PhpGenerator\Dumper
.
PHP Fatal error: Uncaught Nette\MemberAccessException: Call to undefined static method Nette\PhpGenerator\Helpers::createObject().
I am trying to use phpstan with nette and I have a problem with not recognizing Nette Events (even if this should be supported according to README).
My code looks like this:
trait CommonTrait
{
use SmartObject;
/** @var array */
public $onUpdate = [];
...
public function insert($data) {
...
$this->onUpdate($data);
}
But after running PHP stan with Nette extension I am getting these errors:
Call to an undefined method App\Model\Db\Languages::onUpdate()
And it is the same with other classes using this trait.
I am using Nette 2.4 and the latest PHPStan shim and I have tried that the Nette extension loads correctly.
Setup:
phpstan/phpstan-shim 0.10
phpstan/phpstan-nette 0.10
--optimize-autoloader
flagNette\Bridges\ApplicationDI\ApplicationExtension
with (default) settings:application:
scanComposer: TRUE
scanFilter: 'Presenter'
Result:
Application crashes during container compilation.
Why:
ApplicationExtension
scans all classes from composer autoloader. One of them is PresenterGetSessionReturnTypeExtension
, which passes the default filter because it contains Presenter
in its name. Nette then tries to load it in order to run additional checks via reflection, but that this ends with fatal error: Interface 'PHPStan\Type\DynamicMethodReturnTypeExtension' not found
.
The error is a result of a combination of multiple factors...
--optimize-autoloader
flag the error goes away, because PresenterGetSessionReturnTypeExtension
is not registered in the classmap that Nette uses. So, your app may run locally just fine, but fails in CI (or production) with a very obscure fatal error.phpstan
core package instead of phstan-shim
, you're fine -DynamicMethodReturnTypeExtension
interface is loadable via composer autoloading, becuase it's not hidden inside phar like in phpstan-shim
.The fatal error is not solvable in Nette. You might argue that this phpstan setup is done incorrectly (it should be installed as 3rd party tool outside of application vendor)... Well, yes... unfortunately this setup is quite common in the wild because of the easy setup.
Possible solution:
Rename the extension to not contain Presenter
? It's ugly, but I don't have a better suggestion.
The workflow release.yml is referencing action metcalfc/changelog-generator using references v1.0.0. However this reference is missing the commit 14b159ac83976a0eb274f0a9a6c278c3f1b08e87 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.
I am planning to write rules to check validity of links (link, redirect, ...) creation.
We already do this in our phpstan-latte extension (in hacky way) but I would like to write universal solution.
Should I make it as PR to this package or would you preffer it as separate package?
Hi, i have problems with latest nette/forms and phpstan 1.0.. i will describe it on presenter, but same errors are in control...
<?php declare(strict_types = 1);
namespace App\Presenters;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
use Nette\Utils\ArrayHash;
final class HomepagePresenter extends Presenter
{
protected function createCompomentForm(): Form
{
$form = new Form();
$form->onSuccess[] = function (Form $form, ArrayHash $values): void {
};
$form->onSuccess[] = [$this, 'formOnSuccess'];
return $form;
}
public function formOnSuccess(Form $form, ArrayHash $values): void
{
}
}
------ ---------------------------------------------------------------------------------
Line Presenters/HomepagePresenter.php
------ ---------------------------------------------------------------------------------
15 Array (array<callable(Nette\Application\UI\Form, mixed): void>) does not accept
Closure(Nette\Application\UI\Form, Nette\Utils\ArrayHash): void.
18 Array (array<callable(Nette\Application\UI\Form, mixed): void>) does not accept
array{$this(App\Presenters\HomepagePresenter), 'formOnSuccess'}.
------ ---------------------------------------------------------------------------------
would it be possible to have a new Rule which reports errors when nette-config files reference classes which are @deprecated
.
this would help to provide a smoother migration path for packages which distribute phpstan extensions via .neon files.
see also deprecated-packages/symplify#4169 for a related problems discussion about BC breaking changes in phpstan context.
Since version 1.2.2 it reports these errors:
Call to an undefined method Nette\Forms\Control::getOption().
Call to an undefined method Nette\Forms\Control::getControlPrototype().
Call to an undefined method Nette\Forms\Control::getContainerPrototype().
Call to an undefined method Nette\Forms\Control::getItemLabelPrototype().
see here:
https://github.com/contributte/datagrid/pull/957/checks?check_run_id=2015573206
I don't think this should be noted as error here...
This code is correct and working. With phpstan >= 1.10.23 it reports error Access to an uninitialized property App\AdminModule\Presenters\AdminPresenter::$user.
class AdminPresenter extends Presenter
{
/** @inject */
public User $user;
public function startup()
{
parent::startup();
if (!$this->user->isLoggedIn()) {
// do something
}
}
}
Hi,
I have a problem with PhpStan + PhpStan-Nette:
Nette\Application\Routers\RouteList does not accept Nette\Application\Routers\Route
Code producing this error:
use Nette\Application\Routers\RouteList;
use Nette\Application\Routers\Route;
$router = new RouteList('v1');
$router[] = new Route('/v1/status', 'Status:default');
Workaround for this situation is this:
$router = new RouteList('v1');
$router->offsetSet(null, new Route('/v1/status', 'Status:default'));
and it works fine, on one project but on the next one there si different error message:
Nette\Application\Routers\RouteList::offsetSet() expects Nette\Routing\Router, Nette\Application\Routers\Route given.
Not sure if it is bug or there is something what I'm doing wrong.
Thank you.
PHP: 7.3
Nette Application: 2.4.13
PhpStan: 0.12.52
Phpstan-Nette: 0.12.9
Since stubs for certain Nette 3.0 classes were introduced (such as 336ef25#diff-bb9396b9da8def8667dbcf5a2ab44096R6), compatibility with various Nette 2.x packages is broken.
It would be best to at least bump versions in conflict section. Should I bump these versions or try to revert those Nette 3-only changes?
I have following code placed in action method of a presenter.
try {
$identity = $this->accountFacade->authenticate($params);
} catch (AccountNotFound $e) {
$this->error('', IResponse::S404_NOT_FOUND);
} catch (AccountExpired $e) {
$template->setFile(__DIR__ . '/...');
$this->sendTemplate();
}
$this->getUser()->login($identity);
Unfortunately phpstan reports Variable $identity might not be defined.
for the AccountExpired
catch block. When I added throw new \Nette\Application\AbortException()
after $this->sendTemplate()
, it stopped reporting the error.
sendTemplate()
has @throw Nette\Application\AbortException
annotated and sendResponse()
is listed in early terminated method calls so I don't know where the problem is.
Running phpstan-nette on php 7.2 fails with the following error:
Fatal error: Cannot use Nette\Object as Object because 'Object' is a special class name in /home/travis/build/nepada/security-annotations/vendor/phpstan/phpstan-nette/src/Reflection/Nette/NetteObjectClassReflectionExtension.php on line 5
I think the workaround is to use either FQN, or alias.
When I am using code $form['password']->addError('Error');
what is valid nette error on form component, I am getting Call to an undefined method Nette\ComponentModel\IComponent::addError()
that is right. There is no addError
defined in IComponent
.
Can I add custom rule to skip this validation?
Method Nette\Http\Session::getSection()
has optional second parameter which can change class of returned object.
This extension does not support it and always returns Nette\Http\SessionSection
class.
Regular preg_match in PHPStan 1.11.10 does not suffer this issue:
preg_match($s, '#([+-])#', $nativeMatch);
$netteMatch = Strings::match($s, '#([+-])#');
\PHPStan\dumpType($nativeMatch); // array<string>
\PHPStan\dumpType($netteMatch); // array{string, '+'}|null
Using version 1.3.6
I recently added a rule to force using Strings::match()
instead of preg_match()
in my project for better API and error handling. However it seems that while PHPStan checks preg_match
for invalid regular expression (https://github.com/phpstan/phpstan-src/blob/1.9.x/src/Rules/Regexp/RegularExpressionPatternRule.php) the same isn't done for Strings::match()
.
This is actually very problematic because Strings::match()
has the regex and haystack arguments swapped which can be easily missed when switching from preg_match
and I already noticed two cases where one of my developers made that mistake.
How should this be solved? Should we copy the rule from PHPStan here and adjust it? Or should the rule in PHPStan be configurable somehow to allow checking other functions and methods? Or maybe a new regex-string
type should be added?
I'm trying to run PhpStan on my test cases. Currently PHPStan doesn't understand any type assertions. For the beginning, it would be great to have just few basic:
i get this error for all components. why is this an error?
the Nette\ComponentModel\Component constructor just checks some legacy stuff
i think this should not be reported as error
When I run the following command in Travis CI, I get an error message.
I think the error started after the last commit dc67915.
Hello,
currently I have encountered problems in testing applications because PHPStan started throwing exceptions for Nette Forms Form. He doesn't like callbacks.
Array (array<callable(Nette\Forms\Form, mixed): void>) does not accept Closure(Nette\Application\UI\Form, Nette\Utils\ArrayHash): void.
for
$form->onSuccess[] = function (Nette\Application\UI\Form $form, ArrayHash $values): void {
...
}
Array (array<callable(Nette\Forms\Form, mixed): void>) does not accept array($this(App\Modules\Section\Presenters\Forum\ForumPresenter), 'onSuccess').
for
$form->onSuccess[] = [$this, 'onSuccess'];
Is there a solution via phpstan-nette extension to fix it?
In one of our legacy projects we upgraded to Nette 3. After upgrade PHPStan reports many weird errors about incompatible types in places where types should be compatible.
For example:
... expects Nette\Caching\IStorage, Nette\Caching\Storage given
... expects Nette\Database\Row, Nette\Database\Table\ActiveRow given
It seems that it reports places where signature uses old name with I prefix (probably left in Nette code for backward compatibility)? And also places where implementation of renamed Nette interfaces are used agains these interfaces.
It seems that PHPStan do not know that IRow
and Row
are equivalents. But I do not know why and I do not know how to debug it, Any hints? I already checked and we have latest versions of Nette packages and PHPStan with phpstan-nette extension.
I try it but I have big trable. It is some bug?
Step by step:
And get return as:
Line presenters/HomepagePresenter.php
Class App\Presenters\HomepagePresenter was not found while trying to analyse it - autoloading is probably not configured properly.
I try add to composer without effect:
"autoload": { "psr-4": { "App\\": "app/" } },
Sub-components accessed via hyphen notation are treated as mixed
$this['document']['head'];
$this['document-head'];
$this->getComponent('document')->getComponent('head');
$this->getComponent('document-head');
Current result
1 Dumped type: HeadControl
2 Dumped type: mixed~null
3 Dumped type: HeadControl
4 Dumped type: mixed~null
Expected result:
All should return HeadControl. Or report that this syntax is not supported.
Which variant would you prefer?
I get an error for all presenters that they don't call parent constructor. why is this an error?
Hello, in several classes as part of the project, after testing (PHPStan level 2), I'm encountering errors of the type Slince\Shopify\Client::methodName(). Could you please advise me on how to resolve these issues? Thank you.
<?php
namespace App\Providers\Shopify;
use Slince\Shopify\Exception\ClientException;
class BlogProvider extends ShopifyProvider
{
public function __construct(...)
{
...
parent::__construct();
}
/**
* @param int $id
* @return array
*/
public function push(int $id): array
{
try {
// getArticleManager() declared in Client.php (https://github.com/slince/shopify-api-php/blob/3.x/src/Client.php)
$this->getClient($id)->getArticleManager()->update(); // PHPStan throws error here: Call to an undefined method Slince\Shopify\Client::getArticleManager().
return ['result' => true];
} catch (ClientException $exception) {
...
}
}
}
?>
<?php
namespace App\Providers\Shopify;
...
use Slince\Shopify\Client;
use Slince\Shopify\PublicAppCredential;
class ShopifyProvider
{
public function __construct(...)
{
...
}
/**
* @param int $clientId
* @return \Slince\Shopify\Client
*/
public function getClient(int $clientId): Client {
...
return new Client($baseUrl, $credential, [
'meta_cache_dir' => __DIR__,
'api_version' => '2023-04',
]);
}
}
?>
Unreachable statement - code above always terminates.
PHPStan wrongly assumes that this code in Nette\Database\Row always throws Exception and assumes that the further code will not execute.
This was not a case in Nette 3.1, problem occured after updating to Nette 3.2
public function __get(mixed $key): never
{
$hint = Nette\Utils\Helpers::getSuggestion(array_map('strval', array_keys((array) $this)), $key);
throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'" . ($hint ? ", did you mean '$hint'?" : '.'));
}
This happens for example for code
code
$row->variable
code
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/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.
Hello
Trying to clean phpstan lvl5 errors after upgrade to Nette 3. I am still getting these errors and really dont know what to do (i tried to ignore it, but problem is #2
in error for me)
Parameter #2 $destination of method Nette\Application\UI\Component::redirect() expects string|null, array<string, int> given.
Parameter #2 $destination of method Nette\Application\UI\Component::redirect() expects string|null, array<string, mixed> given.
Any idea how to 'fix' this error or how to add it to exceptions?
Hi,
any idea, how to fix errors like follow:
Access to an undefined property Nette\Application\UI\Presenter::$permission.
if I using code below in components?
$this->presenter->permission;
Hi,
(first of all great work with the tool; kudos)
I'm trying to meet level 2 requirements on our Nette project. In presenter we're working with Nette Form components.
The issue I'm facing is, that PHPstan doesn't recognize my form elements as BaseControl
even when I think it already should.
I read #27 (comment) and I got an impression, that @ondrejmirtes wanted form elements to always be a BaseControl
. I can also see https://github.com/phpstan/phpstan-nette/blob/1.1.x/src/Type/Nette/FormsBaseControlDynamicReturnTypeExtension.php which seems like the thing that should handle it.
Am I just wrong here and the assumption is incorrect?
This is what I execute:
php vendor/bin/phpstan analyse --level=2 --memory-limit=1G app tests extensions
368/368 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
------ --------------------------------------------------------------------------
Line extensions/mailer-module/src/Presenters/GeneratorPresenter.php
------ --------------------------------------------------------------------------
134 Call to an undefined method Nette\ComponentModel\IComponent::setValue().
------ --------------------------------------------------------------------------
------ --------------------------------------------------------------------------
Line extensions/mailer-module/src/Presenters/ListPresenter.php
------ --------------------------------------------------------------------------
419 Call to an undefined method Nette\ComponentModel\IComponent::setValue().
422 Call to an undefined method Nette\ComponentModel\IComponent::getValue().
424 Call to an undefined method Nette\ComponentModel\IComponent::getValue().
429 Call to an undefined method Nette\ComponentModel\IComponent::setItems().
------ --------------------------------------------------------------------------
This is the simplified GeneratorPresenter
:
<?php
declare(strict_types=1);
use Nette\Application\UI\Form;
use Remp\MailerModule\Forms\SourceTemplateFormFactory;
final class GeneratorPresenter extends BasePresenter
{
public function createComponentMailSourceTemplateForm(): Form
{
$form = $this->sourceTemplateFormFactory->create(isset($this->params['id']) ? (int)$this->params['id'] : null);
return $form;
}
public function handleRenderSorting($sorting): void
{
/** @var Form $form */
$form = $this['mailSourceTemplateForm'];
$form['sorting']->setValue($sorting); // <<<-------- THIS IS WHAT PHPSTAN COMPLAINS ABOUT
//...
}
}
Am I wrong thinking, that if PHPstan knows that the $form
is of type Form
, and the sorting
is a form element, that it is not just IComponent
, but a BaseControl
?
Thanks a lot for the clarification.
component-model 3.1.0 returns array Container::getComponents()
when $deep === false
:
instead of Iterator
:
phpstan-nette/stubs/ComponentModel/Container.stub
Lines 11 to 13 in 8af9474
The return type should be something like
@phpstan-return (
$deep is true
? ($filterType is null ? array<int|string, \Nette\ComponentModel\IComponent> : array<int|string, T>)
: ($filterType is null ? \Iterator<int|string, \Nette\ComponentModel\IComponent> : \Iterator<int|string, T>)
)
I can open a PR but not sure what to do about older versions. Should I just add conflict with < 3.1.0
?
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
nette/utils
, nikic/php-parser
, phpunit/phpunit
)composer.json
php ^7.2 || ^8.0
nette/application ^3.0
nette/forms ^3.0
nette/utils ^2.3.0 || ^3.0.0
nikic/php-parser ^4.13.2
php-parallel-lint/php-parallel-lint ^1.2
phpstan/phpstan-phpunit ^1.0
phpstan/phpstan-strict-rules ^1.0
phpunit/phpunit ~9.5.28
.github/workflows/build.yml
actions/checkout v4
shivammathur/setup-php v2
actions/checkout v4
actions/checkout v4
shivammathur/setup-php v2
actions/checkout v4
shivammathur/setup-php v2
actions/checkout v4
shivammathur/setup-php v2
.github/workflows/create-tag.yml
actions/checkout v4
WyriHaximus/github-action-get-previous-tag v1
WyriHaximus/github-action-next-semvers v1
rickstaa/action-create-tag v1
rickstaa/action-create-tag v1
.github/workflows/lock-closed-issues.yml
dessant/lock-threads v5
.github/workflows/release-toot.yml
cbrgm/mastodon-github-action v2
.github/workflows/release-tweet.yml
Eomm/why-don-t-you-tweet v1
.github/workflows/release.yml
actions/checkout v4
metcalfc/changelog-generator v4.3.1
actions/create-release v1
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.