Giter Site home page Giter Site logo

phpstan-symfony's Introduction

PHPStan - PHP Static Analysis Tool

PHPStan

Build Status Latest Stable Version Total Downloads License PHPStan Enabled


PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line.

Read more about PHPStan »

Try out PHPStan on the on-line playground! »

Sponsors

TheCodingMachine     Private Packagist
CDN77     Blackfire.io
iO     Amezmo
ShipMonk     Togetter
RightCapital     ContentKing
ZOL     Psyonix
Shopware     Craft CMS
Worksome     campoint AG
Crisp.nl     Inviqa
GetResponse     EdgeNext
Fame Helsinki

You can now sponsor my open-source work on PHPStan through GitHub Sponsors.

Does GitHub already have your 💳? Do you use PHPStan to find 🐛 before they reach production? Send a couple of 💸 a month my way too. Thank you!

One-time donations through PayPal are also accepted. To request an invoice, contact me through e-mail.

Documentation

All the documentation lives on the phpstan.org website:

PHPStan Pro

PHPStan Pro is a paid add-on on top of open-source PHPStan Static Analysis Tool with these premium features:

  • Web UI for browsing found errors, you can click and open your editor of choice on the offending line.
  • Continuous analysis (watch mode): scans changed files in the background, refreshes the UI automatically.

Try it on PHPStan 0.12.45 or later by running it with the --pro option. You can create an account either by following the on-screen instructions, or by visiting account.phpstan.com.

After 30-day free trial period it costs 7 EUR for individuals monthly, 70 EUR for teams (up to 25 members). By paying for PHPStan Pro, you're supporting the development of open-source PHPStan.

You can read more about it on PHPStan's website.

Code of Conduct

This project adheres to a Contributor Code of Conduct. By participating in this project and its community, you are expected to uphold this code.

Contributing

Any contributions are welcome. PHPStan's source code open to pull requests lives at phpstan/phpstan-src.

phpstan-symfony's People

Contributors

alexander-schranz avatar eliashaeussler avatar emodric avatar enumag avatar fluffycondor avatar franmomu avatar hxv avatar jeroennoten avatar khartir avatar kocal avatar leongersen avatar localheinz avatar lookyman avatar mcfedr avatar mhujer avatar mitelg avatar mzk avatar ondrejmirtes avatar ossinkine avatar pierstoval avatar pplotka avatar renovate-bot avatar renovate[bot] avatar ruudk avatar staabm avatar thomaslandauer avatar tomasfejfar avatar tomasvotruba avatar vincentlanglet avatar yguedidi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpstan-symfony's Issues

Request::get('foo') error after update from 0.10.8 to 0.11.0

Hi,
given the following code (see the gist https://gist.github.com/84m/1cb41b41fcacf65d1017f4f1c8c09700 for working example)

<?php declare(strict_types = 1);
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class Controller
{
    public function getFoo(Request $request)
    {
        $userId = $request->get('userid');
        if (isset($userId)) {
            $userId = (int)($userId);
        }
        
        // ...
        $response = new Response();
        if (isset($userId)) {
            $response->headers->add(['userId' => $userId]);
        }
        
        return $response;
    }
}

i was not getting an error on 0.10.8:

$ vendor/bin/phpstan analyse --level 1 Controller.php
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
                                                                                                                  
 [OK] No errors

After an update to 0.11. i get

$ vendor/bin/phpstan analyse --level 1 Controller.php
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ---------------------------------------------------------------- 
  Line   Controller.php                                                  
 ------ ---------------------------------------------------------------- 
  21     Variable $userId in isset() always exists and is not nullable.  
 ------ ---------------------------------------------------------------- 
                                                                                                        
 [ERROR] Found 1 error

I'm not sure what changed here, but if there's no userid within the request, the variable is still null

Request::getSession and null return value.

Request's method getSession can return null value, so when I tried call code like this: $request->getSession()->set(...) I got error:

Cannot call method set() on Symfony\Component\HttpFoundation\Session\SessionInterface|null.

I thought that checking if a request has sessions before call setter, resolve the problem, but unfortunately not. I created a repo which gives You a possibility to reproduce the problem:

https://github.com/plotek/symfony-phpstan

Possible workaround:

if ($request->hasSession()) {
    $session = $request->getSession();
    Assert::isInstanceOf($session, SessionInterface::class);
    $session->set('Test', 'Value');
}

False positive with Symfony\Component\DependencyInjection\ContainerBuilder::has

I have around 10 compiler passes in my code base.

I have NOT configured the path to container XML as I am not interested in testing for existing/non-existing services.

However, somehow, one and only one of my compiler passes fails with the message:

Call to method Symfony\Component\DependencyInjection\ContainerBuilder::has()
with 'fos_http_cache.cache_manager' will always evaluate to false.

The code in question is fairly standard:

if (!$container->has('fos_http_cache.cache_manager')) {
    return;
}

Every other compiler pass uses the same pattern and does not fail.

Why?

Thanks!

False positive with Symfony Messenger

Symfony\Component\Messenger\Envelope::all() returns a different type based on whether or not an argument was passed to it. Currently PHPStan doesn't know that which results in errors like this:

Parameter #1 ... of method ... expects array<array<Symfony\Component\Messenger\Stamp\StampInterface>>, array<array<Symfony\Component\Messenger\Stamp\StampInterface>|Symfony\Component\Messenger\Stamp\StampInterface> given.

I'd send PR but I'm not sure how cases like these should be solved in PHPStan. If you can give me an advice how to do it, I'll send the PR.

[Command] getOption return types

This is a question, I'd be interested in implementing this, but not sure if its possible with Phpstan, so a point in the right direction would be useful.

In Symfony commands options (and arguments) are added in configure function, and this affects the return type of $input->getOption later.

class MyCommand {
    
    protected function configure(): void
    {
        $this
            ->addOption('str', null, InputOption::VALUE_REQUIRED, 'This option will be ?string')
            ->addOption('bool', null, InputOption::VALUE_NONE, 'this option will be bool')
            ->addOption('arra', null, InputOption::VALUE_IS_ARRAY, 'this option will be ?(string[])')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $str = $input->getOption('str');
    }
}

So can I change the return type of getOption, according to the options that are configured?

namespace of composer package is wrong

At packagist.org the package phpstan/phpstan-symfony is not available. For the installation you must type composer require --dev lookyman/phpstan-symfony instead and also include the config from different namespace vendor/lookyman/phpstan-symfony/extension.neon.

PHPStan not correctly resolving available services in subclassed AbstractController::getSubscribedServices()

Summary of a problem or a feature request

It appears that PHPStan doesn't analyse correctly the inheritance in Symfony controllers' getSubscribedServices method in subclasses of the abstract controller.

Code snippet that reproduces the problem

https://github.com/theplankmeister/phpstanerr/blob/master/src/Controller/DefaultController.php#L17
also see https://github.com/theplankmeister/phpstanerr/blob/master/src/Example/ExampleService.php
and the output of https://travis-ci.com/theplankmeister/phpstanerr/jobs/166870630 which demonstrates that the service DOES exist (via Cypress testing defined in https://github.com/theplankmeister/phpstanerr/blob/master/cypress/integration/whatevs.js) yet PHPStan still fails.

Expected output

Expected PHPStan to not complain about Service "example_service" is not registered in the container.

Tag a release?

Can you tag a new release? Or import the tags from the old repository? Currently composer cannot install this package because no versions are tagged.

composer require phpstan/phpstan-symfony

  [InvalidArgumentException]                       
  Could not find package phpstan/phpstan-symfony.  
                                                   
  Did you mean this?                               
      phpstan/phpstan-symfony                      

Container has check throw condition is always true

if (!$container->has('doctrine.orm.entity_manager')) {
    throw new \InvalidArgumentException('Configure your entity manager correctly');
}

In my bundle I have a check for has service the phpstan throw the following error: If condition is always true. or Negated boolean is always false. because I think the service exist in my current configured container file. But this check is needed as somebody which don't have the other library imported or configured it different.

I think has should always be possible to be true or false.

getContent as string|resource

Hello.

When I have this code

        $content = json_decode($request->getContent(), true);

and I get this error.

  56     Parameter #1 $json of function json_decode expects string,   
         resource|string given.  

It would be nice to have phpstan recognise that default request returns string.

Conditional $container->get() not evaluated correctly

First off, is there a way to test the Symfony extension in the PHPStan Playground? In absence of that, here is the classic way of explaining the problem. We have a couple of conditional get calls to the service container like so:

if ($container->has('doctrine.orm.entity_manager')) {
    $em = $container->get('doctrine.orm.entity_manager');
    // ...
}

Unfortunately, this conditional is not properly evaluated:

Service "doctrine.orm.entity_manager" is not registered in the container.

In this case, the get should not cause an error since it will not be reached if there's no such service.

[Command] Missing options

Hello,

I am adding the console_application_loader config part on my PHPStan configuration and I'm facing an issue with Symfony's defaults options not being found.

Command "..." does not define option "env".

We are using the env options to hide some dynamic informations on test environment for our test suite.

My console-application.php file

<?php

use Symfony\Bundle\FrameworkBundle\Console\Application;

require __DIR__.'/../vendor/autoload.php';

$kernel = new AppKernel('test', false);

return new Application($kernel);

I tried to create a patch, but without success. I don't find a way to retrieve those default options in the UndefinedOptionRule class.

services should not be case sensitive

it is common pattern to name services as class path, and then select them with SomeClass::class.

symfony converts those dependencies to lower case before saving / resolving.

This causing errors like Service "SomeNamespace\SomeClass" is not registered in the container.

because in appDevDebugProjectContainer.xml it is saved as: somenamespace\someclass

Support for detecting undefined methods on objects being injected through constructor?

Hi! Amazing work at phpstan!!
I am using phpstan with symfony and doctrine extensions. I was trying to detect an error for objects injected/autowired through the __construct(). It seems that currently it can't derive the type of the local variable based on the type-hint of the injected parameter. I found out that if I set analysis level at 2 it detects undefined methods called for normal objects instantiated with new. Even at level 7 I couldn't detect undefined methods for injected services.

Thank you!

XML imports are not resolved

Currently, imports are not resolved:

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd">

    <imports>
        <import resource="foo.xml"/>
        <import resource="bar.xml"/>
    </imports>

</container>

Undefined variable $container in config files

If you have for example a config/packages/framework.php

Phpstan will report Undefined variable $container if possible this should always be defined in $container and be typed as ContainerBuilder.

Workaround:

# phpstan.neon

parameters:
    # ...

    ignoreErrors:
        - message: '#Undefined variable: \$container#'
          path: '%currentWorkingDirectory%/config/packages/*'

Fatal Error Uncaught Type Error

Bug report

Analysing this class gives the following error:

PHP Fatal error: Uncaught TypeError: Argument 1 passed to PHPStan\Analyser\MutatingScope::getType() must be an instance of PhpParser\Node\Expr, null given, called in development/dev-ops/analyze/vendor-bin/phpstan/vendor/phpstan/phpstan-symfony/src/Type/Symfony/SerializerDynamicReturnTypeExtension.php on line 42 and defined in phar:///development/dev-ops/analyze/vendor-bin/phpstan/vendor/phpstan/phpstan/phpstan/src/Analyser/MutatingScope.php:276
Stack trace:
#0 development/dev-ops/analyze/vendor-bin/phpstan/vendor/phpstan/phpstan-symfony/src/Type/Symfony/SerializerDynamicReturnTypeExtension.php(42): PHPStan\Analyser\MutatingScope->getType(NULL)
phpstan/phpstan#1 phar:///development/dev-ops/analyze/vendor-bin/phpstan/vendor/phpstan/phpstan/phpstan/src/Analyser/MutatingScope.php(2207): PHPStan\Type\Symfony\SerializerDynamicReturnTypeExtension->getTypeFromMethodCall(Object(PHPStan\Reflection\ObjectTypeMethodReflection), Object(PhpParser\Node\Expr\MethodCall), Object(PHPStan\Analyser\MutatingScop in phar:///development/dev-ops/analyze/vendor-bin/phpstan/vendor/phpstan/phpstan/phpstan/src/Analyser/MutatingScope.php on line 276

Code snippet that reproduces the problem

Happens here https://github.com/shopware/platform/blob/6.1/src/Core/Framework/Struct/Serializer/StructNormalizer.php
But I don't know the exact place. If you need more information, please let me know

Load .env file

Support question

Since I updated my project to Symfony 4/Flex, I had to create .env, ... files with some values.
For example I have

DATABASE_URL=mysql://user:[email protected]:3300/database

This file seems to not be loaded by phpstan

In EnvVarProcessor.php line 131:
  Environment variable not found: "DATABASE_URL".

with this config (phpstan.neon)

includes:
    - symfony/vendor/phpstan/phpstan-doctrine/extension.neon
    - symfony/vendor/phpstan/phpstan-symfony/extension.neon
    - symfony/vendor/phpstan/phpstan-phpunit/extension.neon
    - symfony/vendor/phpstan/phpstan-phpunit/rules.neon

parameters:
    autoload_directories:
        - symfony/src/Migrations
    doctrine:
        objectManagerLoader: phpstanLoader.php
    symfony:
        container_xml_path: symfony/var/cache/dev/appAppKernelDevDebugContainer.xml

services:
    -
        class: PhpStan\ProxyQueryMethodsClassReflectionExtension
        tags: [phpstan.broker.methodsClassReflectionExtension]

phpstanLoader.php

<?php

use AssuranceVie\Kernel;

require __DIR__.'/symfony/vendor/autoload.php';

$kernel = new Kernel('test', true);
$kernel->boot();

return $kernel->getContainer()->get('doctrine')->getManager();

What should I add ? I didn't find it in the documentation.

"wildcard" for `container_xml_path`

Hey,
I would like to introduce this extension to Shopware 6.
Due to our plugin system, the cache directory and also the built Symfony DI container are not absolute (See Kernel::getCacheDir)
I understand that the file_get_contents here could not work with a wildcard, e.g. like this: %rootDir%/../../var/cache/dev*/srcShopware_Development_KernelDevDebugContainer.xml

Do you see a way to declare the absolute path on runtime of PHPStan before the Symfony rules are executed? Like a plugin or so, where I set the config container_xml_path dynamically?

False positive: Service XY is private

Symfony: 4.1
PhpStan: 0.10.5

Using the following code

<?php declare(strict_types=1);

// ✂️

class EntitySearchSelectorController extends AbstractController
{
    /**
     * @param Request $request
     * @param string  $entityType
     *
     * @return JsonResponse
     */
    public function doSearch (Request $request, string $entityType) : JsonResponse
    {
        switch ($entityType)
        {
            case "material":
                $model = $this->get(MaterialModel::class);
                break;

            case "manufacturer":
                $model = $this->get(ManufacturerModel::class);
                break;

            case "magazine":
                $model = $this->get(MagazineContentModel::class);
                break;

            default:
                throw $this->createNotFoundException(\sprintf(
                    "Unsupported entity type „%s”.",
                    $entityType
                ));
        }
        // ✂️
    }

    /**
     * @inheritdoc
     */
    public static function getSubscribedServices () : array
    {
        return \array_replace(parent::getSubscribedServices(), [
            MagazineContentModel::class,
            ManufacturerModel::class,
            MaterialModel::class,
        ]);
    }
}

I'll get an error where PhpStan complains that my services are private - which is the default for Symfony services. In this example I've marked two of my three services explicitly as public. However, it shouldn't be needed in this case. The code is working perfectly fine in both dev and prod environment. It's just PhpStan that is complaining.

In this project we've adopted the bundle-less approach, as recommended by Symfony.

image

The config/services.yaml is also nothing fancy and looks like this:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    # Uncommented for the sake of reproducing/reporting this issue
    #App\Model\Magazine\MagazineContentModel:
    #    # required to keep PhpStan silent
    #    public: true

    App\Model\ManufacturerModel:
        # required to keep PhpStan silent
        public: true

    App\Model\Material\MaterialModel:
        # required to keep PhpStan silent
        public: true

Symfony DI DefinitionDecorator not found

Designation Value
php 7.3
symfony/framework 3.4
phpstan 0.11.8
phpstan-symfony 0.11.6
docker docker run --rm -v `pwd`:/project cacahouete/phpaudit:latest php -d memory_limit=50000M /usr/local/src/vendor/bin/phpstan.phar analyse src -l 1

I don't know why, but when I use phpstan-symfony with following config:

    symfony:
        container_xml_path: /project/var/cache/dev/srcDevDebugProjectContainer.xml
        console_application_loader: /project/tests/phpstan/console-application.php

I have the following error:

  Line   Xxxx/PaymentBundle/Command/SendTaxReceiptCommand.php                
 ------ ----------------------------------------------------------------------- 
         Internal error: Class                                                  
         'Symfony\Component\DependencyInjection\DefinitionDecorator' not found  
         Run PHPStan with --debug option and post the stack trace to:           
         https://github.com/phpstan/phpstan/issues/new 

(With option --debug)

Fatal error: Uncaught Error: Class 'Symfony\Component\DependencyInjection\DefinitionDecorator' not found in /project/vendor/hwi/oauth-bundle/DependencyInjection/Security/Factory/OAuthFactory.php:77
Stack trace:
#0 /project/vendor/hwi/oauth-bundle/DependencyInjection/Security/Factory/OAuthFactory.php(101): HWI\Bundle\OAuthBundle\DependencyInjection\Security\Factory\OAuthFactory->createResourceOwnerMap(Object(Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationContainerBuilder), 'main', Array)
#1 /project/vendor/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php(53): HWI\Bundle\OAuthBundle\DependencyInjection\Security\Factory\OAuthFactory->createAuthProvider(Object(Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationContainerBuilder), 'main', Array, '...')
#2 /project/vendor/symfony/security-bundle/DependencyInjection/SecurityExtension.php(534): Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory->create(O in /project/vendor/hwi/oauth-bundle/DependencyInjection/Security/Factory/OAuthFactory.php on line 77

In class ChildDefinition I found class alias 👍

class_alias(ChildDefinition::class, DefinitionDecorator::class);

I don't understand why phpstan can't found this class :s

Test service container

Symfony 4.1 introduced new testing service container which allows to get private services in tests.
For example following code is correct:

namespace App\Tests\Controller;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;

class DefaultControllerTest extends WebTestCase
{
    public function testIndex(): void
    {
        $client = static::createClient();

        /** @var ContainerInterface $container */
        $container = $client->getContainer();
        $entityManager = $container->get(EntityManagerInterface::class);
        // do something with entity manager

        $client->request('GET', '/');

        $this->assertSame(200, $client->getResponse()->getStatusCode());
    }
}

But PHPStan throws error "Service "Doctrine\ORM\EntityManagerInterface" is private."

Support Symfony 5

Hello, would it be possible to update dependencies requirements to support Symfony 5 distribution?

I am currently having a problem with phpstan/phpstan 0.11.19 requires symfony/console ~3.2 || ~4.0 -> no matching package found

To solve this symfony/console ^5.0 would be welcomed

However I believe there are more packages that would benefit from getting updated

No return type for Controller::get

Same error as described here: lookyman/phpstan-symfony#9

Code:

$this->get('session')->getFlashBag()->set('notice', 'Message');

Error:

Call to an undefined method object::getFlashBag().

It does work with $this->container->get('session').

  • phpstan/phpstan-symfony: 0.10.1
  • phpstan: 0.10.2

get correct User class?

It would be nice it this plugin could allow to get User class declared in configuration (e.g. in config/packages/security.yaml), so it can be retrieved instead of generic \Symfony\Component\Security\Core\User\UserInterface.

Tipical scenarios are getting User calling $this->getUser() from controller and calling $tokenStorage->getToken()->getUser() from a service where token storage is injected.

ContainerInterfacePrivateServiceRule should report services that are implicitly private

Since Symfony 3.4, services are private by default. However, the XmlServiceMapFactory still assumes that a service is public if the public attribute hasn't been set:

$service = new Service(
strpos((string) $attrs->id, '.') === 0 ? substr((string) $attrs->id, 1) : (string) $attrs->id,
isset($attrs->class) ? (string) $attrs->class : null,
!isset($attrs->public) || (string) $attrs->public !== 'false',
isset($attrs->synthetic) && (string) $attrs->synthetic === 'true',
isset($attrs->alias) ? (string) $attrs->alias : null
);

(the 3rd argument of the Service constructor is bool $public).

This means that the ContainerInterfacePrivateServiceRule will only report private services if they are explicitly marked as private in their service configuration, but not if they are implicitly private.

In order to correctly report private services being fetched from the container, this logic should be reversed so that a service without a public flag is considered private:

$service = new Service(
	// ...
	isset($attrs->public) && (string) $attrs->public !== 'false',
	// ...
);

That will result in false positives for Symfony versions < 3.4, but those versions are no longer supported by Symfony itself. Alternatively, the XmlServiceMapFactory would have to determine the Symfony version and switch it's logic based on that, but I'm not sure if that's even possible...

$container->has() always true

If I use $container->has() in a CompilerPass, php-stan says that is always true.

Example:

<?php declare(strict_types=1);

namespace Project\Web\CompilerPass;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class ExceptionHandlerPass implements CompilerPassInterface
{

    public function process(ContainerBuilder $container)
    {
        if (!$container->has("project.exception_listener")) {
            $definition = $container->findDefinition("project.exception_listener");

            $taggedServices = $container->findTaggedServiceIds("project.exception_listener.handler");

            foreach ($taggedServices as $id => $taggedService) {
                $definition->addMethodCall("addExceptionHandler", [new Reference($id)]);
            }
        }
    }
}

Error:

 ------ ------------------------------------------- 
  Line   src/CompilerPass/ExceptionHandlerPass.php  
 ------ ------------------------------------------- 
  14     Negated boolean is always false.           
 ------ ------------------------------------------- 

Without the Symfony Plugin it works.

composer.json version requirement for nikic/php-parser possibly too restrictive

I recently ran into a version conflict between this package and phpDocumentor/Reflection with respect to nikic/php-parser.

This project's package requires ^4.0, while the aforementioned package requires either ^1.0 or ^3.0 - depending on how bleeding edge you want to be.

The problem with this is that if nikic/php-parser releases a major version faster than your library, and another package depends on that newer version, there will be a version conflict disallowing said package and this package from being installed. This in fact is the case for trying to install this package along side phpDocumentor/Reflection (which is depended on by ramsey/jenkins-php).

My suggestion, as a library, would be to use a less restrictive version constraint of >=4.0 so that your library can still take advantage of the minimum requirements while not conflicting with newer packages/libraries depending on newer versions.

Thank you.

False positive in Tests: Service XY is private

When using the KernelTestCase and asking PhpStan to analyze a test, I have this error:

image

However, the static::$container that is in the KernelTestCase is supposed to be an instance of the TestContainer but is typed as ContainerInterface because it might happen that the test.container service can be absent from the container, therefore making static::$container be the full container (as of KernelTestCase here )

Here is the code that triggers the error: Pierstoval/AgateApps/.../RedeemerTest.php#L61-L79

If the test.container service exists in the container AND for this specific case, I think there shouldn't be any error.

False positive with Symfony Forms

Hello all,

I get a "Call to an undefined method Symfony\Component\Form\FormInterface::getClickedButton()." error when working with Symfony Forms using the following code (within a Symfony Controller class):

$form = $this->createForm(...); $clickedButton = $form->getClickedButton();

The second line will raise the error since the createForm method returns a FormInterface

Problem with Symfony/Dotenv

Hi,

I don't know if it is the correct repository for this issue.
I try to use phpstan in tests (phpunit) folder but I have this error :

Capture d’écran 2020-05-23 à 00 29 29

with :

phpstan/phpstan 0.12.25 PHPStan - PHP Static Analysis Tool
phpstan/phpstan-doctrine 0.12.13 Doctrine extensions for PHPStan
phpstan/phpstan-phpunit 0.12.8 PHPUnit extensions and rules for PHPStan
phpstan/phpstan-symfony 0.12.6 Symfony Framework extensions and rules for PHPStan
symfony/phpunit-bridge v5.0.8 Symfony PHPUnit Bridge

I have already try to add phpstan-symfony and phpstan-phpunit but not working.
Maybe I forget or misunderstood anything ?

Thank you in advance

Support custom Symfony Validation Constraint

Hello, I'm encountering an issue with custom Validation Constraint.

PhpStan returns me this error:

 ------ ----------------------------------------------------------------------------------- 
  Line   common/Bundle/Common/CoreBundle/Validator/Constraints/IsStringValidator.php        
 ------ ----------------------------------------------------------------------------------- 
  21     Access to an undefined property Symfony\Component\Validator\Constraint::$message.  
 ------ ----------------------------------------------------------------------------------- 

This is my code (just an example, not for production 😄) :

<?php
// packages/common/Bundle/Common/CoreBundle/Validator/Constraints/IsStringValidator.php

declare(strict_types=1);

namespace Yprox\Bundle\Common\CoreBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class IsStringValidator extends ConstraintValidator
{
    /**
     * {@inheritdoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || is_string($value)) {
            return true;
        }

        $this->context->addViolation($constraint->message);

        return false;
    }
}
<?php
// packages/common/Bundle/Common/CoreBundle/Validator/Constraints/IsString.php

declare(strict_types=1);

namespace Yprox\Bundle\Common\CoreBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class IsString extends Constraint
{
    public $message = 'Value must be a string';
}

And this is normal, because there is no property $message on abstrac class Symfony\Component\Validator\Constraint.


I tried to update my code to this:

/**
 * {@inheritdoc}
 */
public function validate($value, IsString $constraint)

but I can't because the declaration is not compatible with ConstraintValidatorInterface::validate($value, Constraint $constraint).

So I tried with a PHPDoc like this:

/**
 * {@inheritdoc}
 * @param IsString $constraint
 */
public function validate($value, Constraint $constraint)

but I still have the same error from PhpStan.


Is there any workaround for that? Should I ignore this error by configuring PhpStan?

Maybe PhpStan can automatically call Constraint#validatedBy()? I'm not sure about that 😕 ...

Thank you! 🙂

Problem with Symfony/DotEnv

Hi,

I don't know if it is the correct repository for this issue.
I try to use phpstan in tests (phpunit) folder but I have this error :

Capture d’écran 2020-05-23 à 00 29 29

with :

phpstan/phpstan 0.12.25 PHPStan - PHP Static Analysis Tool
phpstan/phpstan-doctrine 0.12.13 Doctrine extensions for PHPStan
phpstan/phpstan-phpunit 0.12.8 PHPUnit extensions and rules for PHPStan
phpstan/phpstan-symfony 0.12.6 Symfony Framework extensions and rules for PHPStan
symfony/phpunit-bridge v5.0.8 Symfony PHPUnit Bridge

I have already try to add phpstan-symfony and phpstan-phpunit but not working.
Maybe I forget or misunderstood anything ?

Thank you in advance

Command::addOption()'s $default expects wrong array format

Symfony 4.0 documents Symfony\Component\Console\Command\Command::addOption()'s 5th parameter $default as mixed.

When using default values with InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL mode, the $default parameter expects array<int, string>|null.
This is wrong because keys are irrelevant and leads to error like this:

Parameter #5 $default of method Symfony\Component\Console\Command\Command::addOption() expects array<int, string>|null, array<string> given.

Happens when $default is given an array documented as string[].

Sample code:

/** @var string[] $default */
$default = getSomeDefaults();

$command->addOption(
	'foo',
	null,
	InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
	'foo bar',
	$default
);

This error pops up at level 0 only with this extension enabled, not without it.

Help getArgument/getOption in Symfony Console InputInterface

Symfony had a few recent PRs to the Symfony console that impacted my PHPStan analysis due to PHPDoc changes:

symfony/symfony#28448
symfony/symfony#28374
symfony/symfony#28647

Bottom line:

  • InputInterface::getArgument now returns string|string[]|null
  • InputInterface::getOption returns string|string[]|bool|null.

In reality, they can return string[] only if the relative argument/option is set as InputArgument::IS_ARRAY/InputOption::VALUE_IS_ARRAY.

Is it possible to add an aid in this package for this case? The minimum repro case is this one:

class PhpstanCommand extends \Symfony\Component\Console\Command\Command
{
    protected function configure()
    {
        $this->addArgument('argument', InputArgument::REQUIRED);
        $this->addOption('option', null, InputOption::VALUE_REQUIRED);
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // Cannot cast array<string>|string|null to string. 
        $argument = (string) $input->getArgument('argument');
        // Cannot cast array<string>|bool|string|null to string. 
        $option = (string) $input->getOption('option');
    }
}

services_test.yml is not considered in test context

I have a RealImplementation with potentially expensive calls that is registered for a ServiceInterface in services.yml file. This is overwritten for tests via services_test.yml to instead use a MockImplentation.

There's also a sanity check in relevant tests to ensure that the correct version is being used:

 $service = $container->get(ServiceInterface::class);
 \assert($service instanceof MockImplementation);

This assertion triggers the following error:

Call to function assert() with false will always evaluate to false.                                                                                  
Instanceof between RealImplementation and MockImplementation will always evaluate to false.

This can be worked around by manually widening the type of the variable like so:

/** @var ServiceInterface $service **/
 $service = $container->get(ServiceInterface::class);
 \assert($service instanceof MockImplementation);

Support yaml format services definition

My symfony services definition is in yaml format, but this seems to only support xml format via the container_xml_path configuration option. Also does this support symfony 4+?

Thanks!

False positive with Container::get not nullable

Symfony\Component\DependencyInjection\ContainerInterface::get() can return null when using ContainerInterface::NULL_ON_INVALID_REFERENCE

$stack = $container->get('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE);
if (null === $stack) {
    return null;
}

Strict comparison using === between null and Symfony\Component\HttpFoundation\RequestStack will always evaluate to false.

[Command] Error when using a constant as argument/option default value

Hello,

We have the following error messages while using a command argument/option default value as a constant:

 ------ ------------------------------------------------------------------------------------------------------------------------------ 
  42     Parameter #4 $default of method Symfony\Component\Console\Command\Command::addArgument() expects string|null, mixed given.    
  42     Parameter #5 $default of method Symfony\Component\Console\Command\Command::addOption() expects int|string|null, mixed given.  
 ------ ------------------------------------------------------------------------------------------------------------------------------

The following code should return the error:

    public const MODE_CREATED = 'created';

    protected function configure()
    {
        $this
            ->setName('abc')
            ->addArgument('a', InputArgument::REQUIRED, '', static::MODE_CREATED)
            ->addOption('b', null, InputOption::VALUE_REQUIRED, '', static::MODE_CREATED)
        ;
    }

Even if the constant value is a string, it's understood as mixed.


For the moment, to avoid the error message, I have a private method which returns the constant value and use it as default value.

Wrong error message

I encountered this error:

In XmlServiceMapFactory.php line 26:
                                                                                                                                          
  [PHPStan\Symfony\XmlContainerNotExistsException]                                                                                        
  Container .../vendor/phpstan/phpstan/../../../app/cache/dev/appDevDebugProjectContainer.xml not exists

This is however not true, the file does exist. I removed the @ operator in XmlServiceMapFactory and got this:

PHP Warning:  simplexml_load_file(): .../vendor/phpstan/phpstan/../../../app/cache/dev/appDevDebugProjectContainer.xml:235: parser error : PCDATA invalid Char value 27 in .../vendor/phpstan/phpstan-symfony/src/Symfony/XmlServiceMapFactory.ph</parameter> in .../vendor/phpstan/phpstan-symfony/src/Symfony/XmlServiceMapFactory.php on line 23

WebTestCase collector not special-casing return

The collector for a test client in functional tests isn't using the argument to map to the actual return type, leading to false positives.

    $client = static::createClient();

    $client->enableProfiler();
    $client->request('POST', '/api/1/company);
    $this->assertSame(
      0,
      $client->getProfile()->getCollector('swiftmailer')->getMessageCount()
    );

This results in:

Call to an undefined method Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface::getMessageCount()

Internal error with 0.11.4 on Symfony 4.2.6.

Hi,

Since I updated to version 0.11.4 on this package I have this error message.

#vendor/bin/phpstan analyse -l7 --debug -- src tests config 

PHP Fatal error:  Uncaught PHPStan\ShouldNotHappenException: Internal error. in /opt/project/vendor/phpstan/phpstan-symfony/src/Rules/Symfony/UndefinedArgumentRule.php:52
Stack trace:
#0 /opt/project/vendor/phpstan/phpstan/src/Analyser/Analyser.php(154): PHPStan\Rules\Symfony\UndefinedArgumentRule->processNode(Object(PhpParser\Node\Expr\MethodCall), Object(PHPStan\Analyser\Scope))
#1 /opt/project/vendor/phpstan/phpstan/src/Analyser/NodeScopeResolver.php(1691): PHPStan\Analyser\Analyser->PHPStan\Analyser\{closure}(Object(PhpParser\Node\Expr\MethodCall), Object(PHPStan\Analyser\Scope))
#2 /opt/project/vendor/phpstan/phpstan/src/Analyser/NodeScopeResolver.php(1139): PHPStan\Analyser\NodeScopeResolver->callNodeCallbackWithExpression(Object(Closure), Object(PhpParser\Node\Expr\MethodCall), Object(PHPStan\Analyser\Scope), Object(PHPStan\Analyser\ExpressionContext))
#3 /opt/project/vendor/phpstan/phpstan/src/Analyser/NodeScopeResolver.php(387): PHPStan\Analyser\NodeScopeResolver->processExprNode(Object(PhpParser\Node\Expr\MethodCall) in /opt/project/vendor/phpstan/phpstan-symfony/src/Rules/Symfony/UndefinedArgumentRule.php on line 52

My phpstan config:

includes:
    - ./vendor/phpstan/phpstan-symfony/extension.neon
    - ./vendor/phpstan/phpstan-webmozart-assert/extension.neon
    - ./vendor/phpstan/phpstan-phpunit/extension.neon
    - ./vendor/phpstan/phpstan-phpunit/rules.neon
    - ./vendor/phpstan/phpstan-doctrine/extension.neon
    - ./vendor/phpstan/phpstan-doctrine/rules.neon
    - ./vendor/jangregor/phpstan-prophecy/src/extension.neon
    - ./vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon
parameters:
    symfony:
        container_xml_path: '%rootDir%/../../../var/cache/dev/srcApp_KernelDevDebugContainer.xml'
    ignoreErrors:
        - message: '#Service ".*" is private\.#'
          path: '%currentWorkingDirectory%/tests'
        - message: '#Cannot .* on Faker\\Generator\|null\.#'
          path: '%currentWorkingDirectory%/tests'
        - message: '#Service "test\..*" is not registered in the container\.#'
          path: '%currentWorkingDirectory%/tests'

I am using symfony v4.2.6.

Let me know for anything.

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.