Skip to content

Commit f3fb189

Browse files
committed
Non-empty parameter array might be empty in different environment
1 parent c5fb143 commit f3fb189

File tree

3 files changed

+31
-24
lines changed

3 files changed

+31
-24
lines changed

src/Type/Symfony/ParameterDynamicReturnTypeExtension.php

+18-15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\BooleanType;
1313
use PHPStan\Type\Constant\ConstantArrayType;
1414
use PHPStan\Type\Constant\ConstantBooleanType;
15+
use PHPStan\Type\ConstantType;
1516
use PHPStan\Type\DynamicMethodReturnTypeExtension;
1617
use PHPStan\Type\FloatType;
1718
use PHPStan\Type\IntegerType;
@@ -99,27 +100,29 @@ private function getGetTypeFromMethodCall(
99100
if ($parameterKey !== null) {
100101
$parameter = $this->parameterMap->getParameter($parameterKey);
101102
if ($parameter !== null) {
102-
return TypeTraverser::map($scope->getTypeFromValue($parameter->getValue()), static function (\PHPStan\Type\Type $type, callable $traverse): Type {
103-
if ($type instanceof \PHPStan\Type\ConstantType) {
104-
$generalized = $type->generalize();
105-
if ($generalized instanceof ConstantArrayType) {
106-
if (count($generalized->getValueTypes()) !== 0) {
107-
throw new \PHPStan\ShouldNotHappenException();
108-
}
109-
110-
return new ArrayType(new MixedType(), new MixedType());
111-
}
112-
113-
return $generalized;
114-
}
115-
return $traverse($type);
116-
});
103+
return $this->generalizeType($scope->getTypeFromValue($parameter->getValue()));
117104
}
118105
}
119106

120107
return $returnType;
121108
}
122109

110+
private function generalizeType(Type $type): Type
111+
{
112+
return TypeTraverser::map($type, function (Type $type, callable $traverse): Type {
113+
if ($type instanceof ConstantArrayType) {
114+
if (count($type->getValueTypes()) === 0) {
115+
return new ArrayType(new MixedType(), new MixedType());
116+
}
117+
return new ArrayType($this->generalizeType($type->getKeyType()), $this->generalizeType($type->getItemType()));
118+
}
119+
if ($type instanceof ConstantType) {
120+
return $type->generalize();
121+
}
122+
return $traverse($type);
123+
});
124+
}
125+
123126
private function getHasTypeFromMethodCall(
124127
MethodReflection $methodReflection,
125128
MethodCall $methodCall,

tests/Type/Symfony/container.xml

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
<parameter key="app.binary" type="binary">VGhpcyBpcyBhIEJlbGwgY2hhciAH</parameter>
3232
<parameter key="app.constant">Y-m-d\TH:i:sP</parameter>
3333
<parameter key="test_collection" type="collection"/>
34+
<parameter key="non_empty_collection" type="collection">
35+
<parameter>value</parameter>
36+
</parameter>
3437
</parameters>
3538

3639
<services>

tests/Type/Symfony/data/ExampleAbstractController.php

+10-9
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,23 @@ public function parameters(ContainerInterface $container, ParameterBagInterface
4949
assertType("string", $container->getParameter('app.boolean_as_string'));
5050
assertType("string", $parameterBag->get('app.boolean_as_string'));
5151
assertType("string", $this->getParameter('app.boolean_as_string'));
52-
assertType("array<int, string>&nonEmpty", $container->getParameter('app.list'));
53-
assertType("array<int, string>&nonEmpty", $parameterBag->get('app.list'));
54-
assertType("array<int, string>&nonEmpty", $this->getParameter('app.list'));
55-
assertType("array<int, array<string, string>&nonEmpty>&nonEmpty", $container->getParameter('app.list_of_list'));
56-
assertType("array<int, array<string, string>&nonEmpty>&nonEmpty", $parameterBag->get('app.list_of_list'));
57-
assertType("array<int, array<string, string>&nonEmpty>&nonEmpty", $this->getParameter('app.list_of_list'));
58-
assertType("array<string, string>&nonEmpty", $container->getParameter('app.map'));
59-
assertType("array<string, string>&nonEmpty", $parameterBag->get('app.map'));
60-
assertType("array<string, string>&nonEmpty", $this->getParameter('app.map'));
52+
assertType("array<int, string>", $container->getParameter('app.list'));
53+
assertType("array<int, string>", $parameterBag->get('app.list'));
54+
assertType("array<int, string>", $this->getParameter('app.list'));
55+
assertType("array<int, array<string, string>>", $container->getParameter('app.list_of_list'));
56+
assertType("array<int, array<string, string>>", $parameterBag->get('app.list_of_list'));
57+
assertType("array<int, array<string, string>>", $this->getParameter('app.list_of_list'));
58+
assertType("array<string, string>", $container->getParameter('app.map'));
59+
assertType("array<string, string>", $parameterBag->get('app.map'));
60+
assertType("array<string, string>", $this->getParameter('app.map'));
6161
assertType("string", $container->getParameter('app.binary'));
6262
assertType("string", $parameterBag->get('app.binary'));
6363
assertType("string", $this->getParameter('app.binary'));
6464
assertType("string", $container->getParameter('app.constant'));
6565
assertType("string", $parameterBag->get('app.constant'));
6666
assertType("string", $this->getParameter('app.constant'));
6767
assertType("array", $this->getParameter('test_collection'));
68+
assertType("array<int, string>", $this->getParameter('non_empty_collection'));
6869

6970
assertType('false', $container->hasParameter('unknown'));
7071
assertType('false', $parameterBag->has('unknown'));

0 commit comments

Comments
 (0)