Skip to content

Commit a022ff9

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.1.x
2 parents ed7eb47 + 7358b7e commit a022ff9

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpParser\Node\Expr\FuncCall;
66
use PHPStan\Analyser\Scope;
77
use PHPStan\DependencyInjection\AutowiredService;
8+
use PHPStan\Php\PhpVersion;
89
use PHPStan\Reflection\FunctionReflection;
910
use PHPStan\Reflection\ParametersAcceptorSelector;
1011
use PHPStan\Type\Accessory\AccessoryArrayListType;
@@ -18,11 +19,16 @@
1819
use PHPStan\Type\TypeCombinator;
1920
use PHPStan\Type\UnionType;
2021
use function count;
22+
use function str_contains;
2123

2224
#[AutowiredService]
2325
final class MbConvertEncodingFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
2426
{
2527

28+
public function __construct(private PhpVersion $phpVersion)
29+
{
30+
}
31+
2632
public function isFunctionSupported(FunctionReflection $functionReflection): bool
2733
{
2834
return $functionReflection->getName() === 'mb_convert_encoding';
@@ -48,7 +54,46 @@ public function getTypeFromFunctionCall(
4854

4955
$result = TypeCombinator::intersect($initialReturnType, $this->generalizeStringType($argType));
5056
if ($result instanceof NeverType) {
51-
return null;
57+
$result = $initialReturnType;
58+
}
59+
60+
if ($this->phpVersion->throwsValueErrorForInternalFunctions()) {
61+
if (!isset($functionCall->getArgs()[2])) {
62+
return TypeCombinator::remove($result, new ConstantBooleanType(false));
63+
}
64+
$fromEncodingArgType = $scope->getType($functionCall->getArgs()[2]->value);
65+
66+
$returnFalseIfCannotDetectEncoding = false;
67+
if (!$fromEncodingArgType->isArray()->no()) {
68+
$constantArrays = $fromEncodingArgType->getConstantArrays();
69+
if (count($constantArrays) > 0) {
70+
foreach ($constantArrays as $constantArray) {
71+
if (count($constantArray->getValueTypes()) > 1) {
72+
$returnFalseIfCannotDetectEncoding = true;
73+
break;
74+
}
75+
}
76+
} else {
77+
$returnFalseIfCannotDetectEncoding = true;
78+
}
79+
}
80+
if (!$returnFalseIfCannotDetectEncoding && !$fromEncodingArgType->isString()->no()) {
81+
$constantStrings = $fromEncodingArgType->getConstantStrings();
82+
if (count($constantStrings) > 0) {
83+
foreach ($constantStrings as $constantString) {
84+
if (str_contains($constantString->getValue(), ',')) {
85+
$returnFalseIfCannotDetectEncoding = true;
86+
break;
87+
}
88+
}
89+
} else {
90+
$returnFalseIfCannotDetectEncoding = true;
91+
}
92+
}
93+
94+
if (!$returnFalseIfCannotDetectEncoding) {
95+
return TypeCombinator::remove($result, new ConstantBooleanType(false));
96+
}
5297
}
5398

5499
return TypeCombinator::union($result, new ConstantBooleanType(false));

tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php renamed to tests/PHPStan/Analyser/nsrt/mb-convert-encoding-php7.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?php
1+
<?php // lint <= 8.0
22

3-
namespace MbConvertEncoding;
3+
namespace MbConvertEncodingPHP7;
44

55
/**
66
* @param 'foo'|'bar' $constantString
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php // lint >= 8.0
2+
3+
namespace MbConvertEncodingPHP8;
4+
5+
/**
6+
* @param 'foo'|'bar' $constantString
7+
* @param array{foo: string, bar: int, baz: 'foo'} $structuredArray
8+
* @param list<string> $stringList
9+
* @param list<int> $intList
10+
* @param 'foo'|'bar'|array{foo: string, bar: int, baz: 'foo'}|bool $union
11+
*/
12+
function test_mb_convert_encoding(
13+
mixed $mixed,
14+
string $constantString,
15+
string $string,
16+
array $mixedArray,
17+
array $structuredArray,
18+
array $stringList,
19+
array $intList,
20+
string|array|bool $union,
21+
int $int,
22+
): void {
23+
\PHPStan\Testing\assertType('array|string', mb_convert_encoding($mixed, 'UTF-8'));
24+
\PHPStan\Testing\assertType('string', mb_convert_encoding($constantString, 'UTF-8'));
25+
\PHPStan\Testing\assertType('string', mb_convert_encoding($string, 'UTF-8'));
26+
\PHPStan\Testing\assertType('array', mb_convert_encoding($mixedArray, 'UTF-8'));
27+
\PHPStan\Testing\assertType('array{foo: string, bar: int, baz: string}', mb_convert_encoding($structuredArray, 'UTF-8'));
28+
\PHPStan\Testing\assertType('list<string>', mb_convert_encoding($stringList, 'UTF-8'));
29+
\PHPStan\Testing\assertType('list<int>', mb_convert_encoding($intList, 'UTF-8'));
30+
\PHPStan\Testing\assertType('array{foo: string, bar: int, baz: string}|string', mb_convert_encoding($union, 'UTF-8'));
31+
\PHPStan\Testing\assertType('array|string', mb_convert_encoding($int, 'UTF-8'));
32+
33+
\PHPStan\Testing\assertType('string', mb_convert_encoding($string, 'UTF-8', 'FOO'));
34+
\PHPStan\Testing\assertType('string|false', mb_convert_encoding($string, 'UTF-8', $string));
35+
\PHPStan\Testing\assertType('string|false', mb_convert_encoding($string, 'UTF-8', 'FOO,BAR'));
36+
\PHPStan\Testing\assertType('string', mb_convert_encoding($string, 'UTF-8', ['FOO']));
37+
\PHPStan\Testing\assertType('string|false', mb_convert_encoding($string, 'UTF-8', ['FOO', 'BAR']));
38+
\PHPStan\Testing\assertType('string', mb_convert_encoding($string, 'UTF-8', ['FOO,BAR']));
39+
\PHPStan\Testing\assertType('list<string>', mb_convert_encoding($stringList, 'UTF-8', 'FOO'));
40+
\PHPStan\Testing\assertType('list<string>|false', mb_convert_encoding($stringList, 'UTF-8', $string));
41+
\PHPStan\Testing\assertType('list<string>|false', mb_convert_encoding($stringList, 'UTF-8', 'FOO,BAR'));
42+
\PHPStan\Testing\assertType('list<string>', mb_convert_encoding($stringList, 'UTF-8', ['FOO']));
43+
\PHPStan\Testing\assertType('list<string>|false', mb_convert_encoding($stringList, 'UTF-8', ['FOO', 'BAR']));
44+
\PHPStan\Testing\assertType('list<string>', mb_convert_encoding($stringList, 'UTF-8', ['FOO,BAR']));
45+
};

0 commit comments

Comments
 (0)