Skip to content

Commit 31b86f8

Browse files
Introduce StrrevFunctionReturnTypeExtension
1 parent a2c0946 commit 31b86f8

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

conf/config.neon

+5
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,11 @@ services:
17741774
tags:
17751775
- phpstan.broker.dynamicFunctionReturnTypeExtension
17761776

1777+
-
1778+
class: PHPStan\Type\Php\StrrevFunctionReturnTypeExtension
1779+
tags:
1780+
- phpstan.broker.dynamicFunctionReturnTypeExtension
1781+
17771782
-
17781783
class: PHPStan\Type\Php\SubstrDynamicReturnTypeExtension
17791784
tags:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Php;
4+
5+
use PhpParser\Node\Expr\FuncCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\FunctionReflection;
8+
use PHPStan\Type\Accessory\AccessoryLowercaseStringType;
9+
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
10+
use PHPStan\Type\Accessory\AccessoryNonFalsyStringType;
11+
use PHPStan\Type\Accessory\AccessoryUppercaseStringType;
12+
use PHPStan\Type\Constant\ConstantStringType;
13+
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
14+
use PHPStan\Type\IntersectionType;
15+
use PHPStan\Type\StringType;
16+
use PHPStan\Type\Type;
17+
use PHPStan\Type\TypeCombinator;
18+
use function count;
19+
use function strrev;
20+
21+
final class StrrevFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
22+
{
23+
24+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
25+
{
26+
return $functionReflection->getName() === 'strrev';
27+
}
28+
29+
public function getTypeFromFunctionCall(
30+
FunctionReflection $functionReflection,
31+
FuncCall $functionCall,
32+
Scope $scope,
33+
): Type
34+
{
35+
$args = $functionCall->getArgs();
36+
if (count($args) < 1) {
37+
return new StringType();
38+
}
39+
40+
$inputType = $scope->getType($args[0]->value);
41+
$constantStrings = $inputType->getConstantStrings();
42+
if (count($constantStrings) > 0) {
43+
$resultTypes = [];
44+
foreach ($constantStrings as $constantString) {
45+
$resultTypes[] = new ConstantStringType(strrev($constantString->getValue()));
46+
}
47+
48+
return TypeCombinator::union(...$resultTypes);
49+
}
50+
51+
$accessoryTypes = [];
52+
if ($inputType->isNonFalsyString()->yes()) {
53+
$accessoryTypes[] = new AccessoryNonFalsyStringType();
54+
} elseif ($inputType->isNonEmptyString()->yes()) {
55+
$accessoryTypes[] = new AccessoryNonEmptyStringType();
56+
}
57+
if ($inputType->isLowercaseString()->yes()) {
58+
$accessoryTypes[] = new AccessoryLowercaseStringType();
59+
}
60+
if ($inputType->isUppercaseString()->yes()) {
61+
$accessoryTypes[] = new AccessoryUppercaseStringType();
62+
}
63+
64+
if (count($accessoryTypes) > 0) {
65+
$accessoryTypes[] = new StringType();
66+
67+
return new IntersectionType($accessoryTypes);
68+
}
69+
70+
return new StringType();
71+
}
72+
73+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Strrev;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
/**
10+
* @param string $string
11+
* @param non-empty-string $nonEmptyString
12+
* @param non-falsy-string $nonFalsyString
13+
* @param numeric-string $numericString
14+
* @param lowercase-string $lowercaseString
15+
* @param uppercase-string $uppercaseString
16+
* @param 'foo'|'bar' $constantStrings
17+
*
18+
* @return void
19+
*/
20+
public function test(
21+
string $string,
22+
string $nonEmptyString,
23+
string $nonFalsyString,
24+
string $numericString,
25+
string $lowercaseString,
26+
string $uppercaseString,
27+
string $constantStrings,
28+
) {
29+
assertType('string', strrev($string));
30+
assertType('non-empty-string', strrev($nonEmptyString));
31+
assertType('non-falsy-string', strrev($nonFalsyString));
32+
assertType('non-empty-string', strrev($numericString));
33+
assertType('lowercase-string', strrev($lowercaseString));
34+
assertType('uppercase-string', strrev($uppercaseString));
35+
assertType("'oof'|'rab'", strrev($constantStrings));
36+
}
37+
}

0 commit comments

Comments
 (0)