CodeIgniter / phpstan-codeigniter

CodeIgniter extensions and rules for PHPStan
https://codeigniter.com/
MIT License
15 stars 0 forks source link

bug: phpstan does not find CodeIgniter\Settings #3

Closed dgvirtual closed 1 year ago

dgvirtual commented 1 year ago

PHP Version

8.1

PHPStan CodeIgniter Version

v4.3.7

PHPStan Version

1.10.27

What happened?

I am using Codeigniter Settings service.

Added

codeigniter:
    additionalServices:
        - CodeIgniter\Settings

to phpstan.neon.dist

Minimum Reproduction Script

vendor/bin/phpstan analyse app

I am getting an error:

Getting this: (after some successful processing):


 Error                                                                                        

 Internal error: Internal error: Service class "CodeIgniter\\Settings" is not found. in file  
 /home/dg/Programavimas/saskaitos/app/Modules/SystemLogs/Libraries/Logs.php                   
 Run PHPStan with -v option and post the stack trace to:                                      
 https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml                       
 Internal error: Internal error: Service class "CodeIgniter\\Settings" is not found. in file  
 /home/dg/Programavimas/saskaitos/app/Libraries/InvoicesLib.php 

Expected Output

Well, I expect the phpstan would not report such error.

I am not at all sure this is a bug, but also not sure where to ask what is wrong.

paulbalandan commented 1 year ago

Hi! Can I see your composer.json?

dgvirtual commented 1 year ago

Here please:

{
    "name": "codeigniter4/appstarter",
    "type": "project",
    "description": "Simonos apskaita",
    "homepage": "https://codeigniter.com",
    "license": "MIT",
    "require": {
        "php": "^7.3 || ^8.0",
        "codeigniter4/framework": "^4",
        "benedmunds/codeigniter-ion-auth": "4.x-dev",
        "codeigniter4/translations": "4.x-dev",
        "dompdf/dompdf": "dev-master",
        "mk-j/php_xlsxwriter": "dev-master",
        "codeigniter4/settings": "dev-develop",
        "michalsn/codeigniter-htmx": "dev-php7port",
        "ezyang/htmlpurifier": "dev-master",
        "erusev/parsedown-extra": "dev-master"
    },
    "require-dev": {
        "fakerphp/faker": "^1.9",
        "mikey179/vfsstream": "^1.6",
        "phpunit/phpunit": "^9.1"
    },
    "suggest": {
        "ext-fileinfo": "Improves mime type detection for files"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app",
            "Config\\": "app/Config"
        },
        "exclude-from-classmap": [
            "**/Database/Migrations/**"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\Support\\": "tests/_support"
        }
    },
    "scripts": {
        "test": "phpunit"
    },
    "support": {
        "forum": "http://forum.codeigniter.com/",
        "source": "https://github.com/codeigniter4/CodeIgniter4",
        "slack": "https://codeigniterchat.slack.com"
    },
    "minimum-stability": "dev",
    "repositories": {
        "codeigniter-htmx": {
            "type": "vcs",
            "url": "git@github.com:dgvirtual/codeigniter-htmx.git"
        },
        "ionAuth": {
            "type": "vcs",
            "url": "git@github.com:benedmunds/CodeIgniter-Ion-Auth.git"
        }
    }
}
paulbalandan commented 1 year ago

Ok. I think I get the problem. Try using CodeIgniter\Settings\Settings as class

paulbalandan commented 1 year ago

Also, Settings is the actual service class. You need to put there instead is the factory for it: CodeIgniter\Settings\Config\Services

dgvirtual commented 1 year ago

That CodeIgniter\Settings\Config\Services line actually worked, thank you.

Could you also help me with the next problem of the same category...

I am using IonAuth as a service, defined in Config/Services.php:

public static function ionAuth($getShared = true)
    {
        if ($getShared) {
            return static::getSharedInstance('ionAuth');
        }

        return new \IonAuth\Libraries\IonAuth();
    }

I have added - Config\Services to additionalServices:; While it does not throw an error, the ionAuth is not recognized as a service by phpstan:

 :235   Call to unknown service name 'ionAuth'.                                                 
         💡 If 'ionAuth' is a valid service name, you can add its possible service class(es) in  
            codeigniter.additionalServices in your phpstan.neon.dist.  

I have also tried adding - IonAuth\Libraries\IonAuth to additionalServices:, but the notice does not o away.

Is there something else I should do?

paulbalandan commented 1 year ago

That's weird. Looking at it seems it should work.

  1. Is Config\Services the default provided by the framework located in app/Config/Services.php? If yes, no need to add it in additionalServices.
  2. If that does not work, try adding a return type to your ionAuth method.
dgvirtual commented 1 year ago

OK, so I have added \IonAuth\Libraries\IonAuth as return type and now it seems to be working. public static function ionAuth($getShared = true): \IonAuth\Libraries\IonAuth { <...> }

Just a final question: to better understand what I had just been doing, could you suggest some concepts to get familiar with (ask ChatGPT eg :) ). From the little that I understood of your comments I see I still have a lot to learn.

paulbalandan commented 1 year ago

Ok. In the context of service class detection, you must remember these points:

  1. additionalServices expects class strings only. It should be a valid class extending CodeIgniter\Config\BaseService. You are putting here the services factory, not the actual service class you need.
  2. PHPStan doesn't descend to the method body for the return type of the method. It relies on the PHPDocs or the actual return type declaration. This reliance is used in this extension. If you don't provide a return type, phpstan cannot know what service you are requesting.
paulbalandan commented 1 year ago

I'll push commits tomorrow for better developer experience.

dgvirtual commented 1 year ago

Ok. In the context of service class detection, you must remember these points:

1. `additionalServices` expects class strings only. It should be a valid class extending `CodeIgniter\Config\BaseService`. You are putting here the services factory, not the actual service class you need.

2. PHPStan doesn't descend to the method body for the return type of the method. It relies on the PHPDocs or the actual return type declaration. This reliance is used in this extension. If you don't provide a return type, phpstan cannot know what service you are requesting.

Thanks a lot!

MGatner commented 1 year ago

🥳