Skip to content

Commit

Permalink
Merge pull request #9837 from kkmuffme/dirname-return-type-non-empty-…
Browse files Browse the repository at this point in the history
…string

Dirname return type non empty string
  • Loading branch information
orklah committed May 30, 2023
2 parents 2bbfca6 + e3e7373 commit 8cdb4b0
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 5 deletions.
2 changes: 1 addition & 1 deletion dictionaries/CallMap.php
Expand Up @@ -1613,7 +1613,7 @@
'DirectoryIterator::setFileClass' => ['void', 'class='=>'class-string'],
'DirectoryIterator::setInfoClass' => ['void', 'class='=>'class-string'],
'DirectoryIterator::valid' => ['bool'],
'dirname' => ['string', 'path'=>'string', 'levels='=>'int'],
'dirname' => ['string', 'path'=>'string', 'levels='=>'int<1, max>'],
'disk_free_space' => ['float|false', 'directory'=>'string'],
'disk_total_space' => ['float|false', 'directory'=>'string'],
'diskfreespace' => ['float|false', 'directory'=>'string'],
Expand Down
2 changes: 1 addition & 1 deletion dictionaries/CallMap_historical.php
Expand Up @@ -9995,7 +9995,7 @@
'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'],
'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'length='=>'int'],
'dir' => ['Directory|false', 'directory'=>'string', 'context='=>'resource'],
'dirname' => ['string', 'path'=>'string', 'levels='=>'int'],
'dirname' => ['string', 'path'=>'string', 'levels='=>'int<1, max>'],
'disk_free_space' => ['float|false', 'directory'=>'string'],
'disk_total_space' => ['float|false', 'directory'=>'string'],
'diskfreespace' => ['float|false', 'directory'=>'string'],
Expand Down
Expand Up @@ -369,6 +369,10 @@ public static function getPathTo(
return null;
}

if ($dir_level < 1) {
return null;
}

return dirname($evaled_path, $dir_level);
}
} elseif ($stmt instanceof PhpParser\Node\Expr\ConstFetch) {
Expand Down
Expand Up @@ -9,6 +9,7 @@
use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface;
use Psalm\Type;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Union;

use function array_values;
Expand Down Expand Up @@ -61,6 +62,16 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev
$statements_source->getCodebase()->config,
);

if ($evaled_path === null) {
$type = $node_type_provider->getType($call_args[0]->value);
if ($type !== null && $type->isSingle()) {
$atomic_type = array_values($type->getAtomicTypes())[0];
if ($atomic_type instanceof TNonEmptyString) {
return Type::getNonEmptyString();
}
}
}

if ($evaled_path === null) {
return Type::getString();
}
Expand Down
15 changes: 12 additions & 3 deletions tests/ReturnTypeProvider/DirnameTest.php
Expand Up @@ -35,12 +35,21 @@ public function providerValidCodeParse(): iterable
],
];

yield 'dirnameOfIntLevelReturnsString' => [
yield 'dirnameOfIntLevelLiteralReturnsLiteral' => [
'code' => '<?php
$dir = dirname("' . $input . '", 0);
$dir = dirname("' . $input . '", 10);
',
'assertions' => [
'$dir===' => 'string',
'$dir===' => "'.'",
],
];

yield 'dirnameOfNonEmptyStringIntLevelOneReturnsNonEmptyString' => [
'code' => '<?php
$dir = dirname(uniqid() . "abc", 2);
',
'assertions' => [
'$dir===' => 'non-empty-string',
],
];
}
Expand Down

0 comments on commit 8cdb4b0

Please sign in to comment.