vscode-intelephense icon indicating copy to clipboard operation
vscode-intelephense copied to clipboard

PHP_VERSION_ID incorrect value

Open momala454 opened this issue 2 years ago • 8 comments

Describe the bug the plugin doesn't verify that parameter types of mb_strtolower are correct. Maybe there are more functions with the same problem.

To Reproduce

echo mb_strtolower(new stdClass());
echo strtolower(new stdClass());
mysqli_connect(new stdClass());
die(new stdClass());

Expected behavior an error should be displayed on each of those lines, but it is shown only on strtolower and mysqli_connect. Btw, no tooltip is shown on "die"

Screenshots image

Platform and version windows 1.8.2

momala454 avatar Mar 24 '22 13:03 momala454

echo mb_strtolower(new stdClass());

My vscode has an error message. image

Maybe it's because your project file is contaminated by other ide-helper or polyfill files. You can see it in your screenshot. image For example a file like this https://github.com/symfony/polyfill/blob/main/src/Mbstring/bootstrap.php

die(new stdClass());

die is a language construct. In fact, It accepts the mixed type, PHP will cast it to a string.

class test
{
    function __toString()
    {
        return __CLASS__;
    }
}

die(new test());

# see the error message of PHP
die(new stdClass); // Uncaught Error: Object of class stdClass could not be converted to string
trim(new stdClass); // Uncaught TypeError: trim(): Argument #1 ($string) must be of type string, stdClass given

tianyiw2013 avatar Mar 25 '22 03:03 tianyiw2013

Thanks, you're right, that was symfony. Strangely it was loading the PHP<8 and the PHP>=8 file. I suppose intelephense could detect this and ignore the file

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

image image

Why does it show 50306 if i have configured php 8 ? running the script shows 80102 for 8.1.2

momala454 avatar Mar 25 '22 07:03 momala454

Why does it show 50306 if i have configured php 8 ?

It's statically defined in stubs. You shouldn't rely on constant values showed in tooltips.

KapitanOczywisty avatar Apr 22 '22 08:04 KapitanOczywisty

it makes sense. But do you think it's a good idea to change it to the configured value so the symfony functions for PHP of a lower version are ignored ?

So like in this following code, if i'm on php8, the signature of the function is the one with int $a

if (\PHP_VERSION_ID < 80000) {
    function helloWorldTestVersion(string $a) {

    }
}
else {
    function helloWorldTestVersion(int $a) {

    }
}

helloWorldTestVersion('a');

currently intelephense show both of them

momala454 avatar Apr 25 '22 09:04 momala454

That's irrelevant. Even you use

if (false) {
    function helloWorldTestVersion(string $a) {

    }
}
else {
    function helloWorldTestVersion(int $a) {

    }
}

Both signatures are still provided by intelephense.

jfcherng avatar Apr 25 '22 10:04 jfcherng

what should symfony or intelephense do to prevent us to see the function definitions we don't want to see then ?

what is your opinion to change the way intelphense handle method definitions to ignore them if they are never executed (like in your example) ?

momala454 avatar Apr 25 '22 10:04 momala454

The idea is good, but I think this feature is difficult to implement.

tianyiw2013 avatar Apr 25 '22 10:04 tianyiw2013

Dead code detection: #1718

I think this is a bad idea to have different function signature in different php versions (unless you're dealing with resource/object migration). Better is to keep version logic inside a function:

function helloWorldTestVersion(string $a) {
  if (\PHP_VERSION_ID < 80000) {
  } else {
  }
}

If you need to make some polyfills, place them into separate file e.g. polyfills/php-80.php. Then file can be excluded in intelephense.references.exclude or intelephense.files.exclude. Currently @ignore is not working, but it'd be another option.

There are some existing polyfills, which should remove this whole problem: https://packagist.org/explore/?query=symfony%2Fpolyfill-php

KapitanOczywisty avatar Apr 25 '22 12:04 KapitanOczywisty

Closing as out of scope. It is not feasible to provide the level of analysis needed to solve this edge case.

bmewburn avatar Dec 30 '22 06:12 bmewburn

@bmewburn and just for the constant PHP_VERSION_ID, could the extension just use the version defined in settings ?

momala454 avatar Dec 30 '22 08:12 momala454

@momala454 I think this again falls into the edge case category that is very low priority. However, I did remember just now that there is an existing way to better control what versions of a function is indexed by intelephense. You can add annotations above the definition like so:

/**
 * @removed 8.1.0
 */
 function myFunction(string $string) { }

/**
 * @since 8.1.0 
 */
   function myFunction(object $object) { }

bmewburn avatar Dec 31 '22 00:12 bmewburn