Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add psalm-flow for string functions from sscanf to wordwrap #4591

Merged
merged 6 commits into from
Nov 21, 2020

Conversation

LukasReschke
Copy link
Contributor

@LukasReschke LukasReschke commented Nov 17, 2020

This should conclude all string functions from https://www.php.net/manual/en/book.strings.php

Continuation of #4576

Ref #3636

TODO

  • strtr return provider
  • Fix tests
  • Cleanup commits + remove accidentially commited files

@LukasReschke
Copy link
Contributor Author

Any pointers why the following test is failing? I defined the second argument as mixed as per php.net (https://www.php.net/manual/en/function.strstr.php). But the test seems to intentionally test wrong behaviour?

'strtrWithPossiblyFalseFirstArg' => [
'<?php
/**
* @param false|string $str
* @param array<string, string> $replace_pairs
* @return string
*/
function strtr_wrapper($str, array $replace_pairs) {
/** @psalm-suppress PossiblyFalseArgument */
return strtr($str, $replace_pairs);
}',
],

@LukasReschke LukasReschke changed the title Add string functions from sscanf to wordwrap Add psalm-flow for string functions from sscanf to wordwrap Nov 17, 2020
@weirdan
Copy link
Collaborator

weirdan commented Nov 17, 2020

But the test seems to intentionally test wrong behaviour?

The test was added along with the fix for #915, and was probably related to how Psalm selects the overloaded signature (strtr() has two) from the callmap.

defined the second argument as mixed as per php.net

That's too wide. It should be either string or array, depending on the number of parameters (string for 3 arg signature and array for 2).

@LukasReschke
Copy link
Contributor Author

LukasReschke commented Nov 17, 2020

That's too wide. It should be either string or array, depending on the number of parameters (string for 3 arg signature and array for 2).

Oof. Seems the PHP documentation omits that behaviour for arrays straight out. Even though it works fine as per https://3v4l.org/7PJG7 :-/

I'm going to fix this, thanks! Also the CallMap was new to me, good to know. :)

I was wrong. I looked at the wrong docs. https://www.php.net/manual/en/function.strtr.php and https://www.php.net/manual/en/function.strstr.php were confusing me :)

@LukasReschke LukasReschke marked this pull request as draft November 17, 2020 19:49
stubs/CoreGenericFunctions.phpstub Outdated Show resolved Hide resolved
stubs/CoreGenericFunctions.phpstub Outdated Show resolved Hide resolved
stubs/CoreGenericFunctions.phpstub Outdated Show resolved Hide resolved
stubs/CoreGenericFunctions.phpstub Outdated Show resolved Hide resolved
stubs/CoreGenericFunctions.phpstub Outdated Show resolved Hide resolved
@staabm
Copy link
Contributor

staabm commented Nov 20, 2020

Side-note: could someone elaborate why/when psalm-flow should be used?

Its not documented.. is it a psalm internal-only phpdoc?

@orklah
Copy link
Collaborator

orklah commented Nov 20, 2020

Side-note: could someone elaborate why/when psalm-flow should be used?

Its not documented.. is it a psalm internal-only phpdoc?

See #4587 (comment)

@LukasReschke LukasReschke marked this pull request as ready for review November 21, 2020 17:34
@LukasReschke
Copy link
Contributor Author

This should be ready to review now. For strtr I added a provider (StrTrReturnTypeProvider) that will propagate the taint flow for all parameters.

@LukasReschke
Copy link
Contributor Author

LukasReschke commented Nov 21, 2020

The error being thrown is from https://github.com/sebastianbergmann/phpunit/blob/58f69d18fd1e61b54c18cf9d06b762507be55562/src/TextUI/DefaultResultPrinter.php#L149-L154:

        if (!in_array($colors, self::AVAILABLE_COLORS, true)) {
            throw InvalidArgumentException::create(
                3,
                vsprintf('value from "%s", "%s" or "%s"', self::AVAILABLE_COLORS)
            );
        }

As per php.net:

https://www.php.net/manual/en/function.vsprintf.php

vsprintf ( string $format , array $args ) : string|false

Return array values as a formatted string according to format, or FALSE on failure.

And the code doesn't check for false. - Should this be accepted behaviour? For sprintf it seems we just ignore the fact that it could return false. I can also do the same for vsprintf.

/**
* @psalm-pure
*
* @param string|int|float $args
*
* @psalm-flow ($format, $args) -> return
*/
function sprintf(string $format, ...$args) : string {}

@muglug muglug merged commit 3943b55 into vimeo:master Nov 21, 2020
@muglug
Copy link
Collaborator

muglug commented Nov 21, 2020

Thanks!

Possibly-false returns in standard library functions are annoying. In > 99.9% of their common usage those functions don’t return false, so Psalm has an annotation @psalm-ignore-falsable-return that triggers special behaviour in a bunch of places.

@orklah
Copy link
Collaborator

orklah commented Nov 24, 2020

I have a few differents false positives that popped in my work codebase that seems related to this PR.

I'll need to verify them and post issues but if someone is faster than me:

  • stristr return type seems to not contain false anymore
  • substr_replace 4th param should be optional and it became mandatory
  • I have new errors related to the offset of the array returned by str_split. Not sure if it's a false positive or if the type was narrowed => Checked, the return type was list<string>|false and is now array<string>

danog pushed a commit to danog/psalm that referenced this pull request Jan 29, 2021
* Add string functions from sscanf to wordwrap

This should conclude all string functions from https://www.php.net/manual/en/book.strings.php

Continuation of vimeo#4576

Ref vimeo#3636

* Add StrTrReturnTypeProvider

* Fix psalm error

* phpcs

* Line length

* Ignore false return on vsprintf

Co-authored-by: Matthew Brown <github@muglug.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants