Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 30f12ae

Browse files
Try to support union of strings as parameter name
1 parent 2063d60 commit 30f12ae

File tree

5 files changed

+67
-19
lines changed

5 files changed

+67
-19
lines changed

‎src/Symfony/DefaultParameterMap.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
use PhpParser\Node\Expr;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Type\Type;
78
use PHPStan\Type\TypeUtils;
8-
use function count;
9+
use function array_map;
910

1011
final class DefaultParameterMap implements ParameterMap
1112
{
@@ -34,10 +35,13 @@ public function getParameter(string $key): ?ParameterDefinition
3435
return $this->parameters[$key] ?? null;
3536
}
3637

37-
public static function getParameterKeyFromNode(Expr $node, Scope $scope): ?string
38+
public static function getParameterKeysFromNode(Expr $node, Scope $scope): array
3839
{
3940
$strings = TypeUtils::getConstantStrings($scope->getType($node));
40-
return count($strings) === 1 ? $strings[0]->getValue() : null;
41+
42+
return array_map(static function (Type $type) {
43+
return $type->getValue();
44+
}, $strings);
4145
}
4246

4347
}

‎src/Symfony/FakeParameterMap.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public function getParameter(string $key): ?ParameterDefinition
2121
return null;
2222
}
2323

24-
public static function getParameterKeyFromNode(Expr $node, Scope $scope): ?string
24+
public static function getParameterKeysFromNode(Expr $node, Scope $scope): array
2525
{
26-
return null;
26+
return [];
2727
}
2828

2929
}

‎src/Symfony/ParameterMap.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public function getParameters(): array;
1515

1616
public function getParameter(string $key): ?ParameterDefinition;
1717

18-
public static function getParameterKeyFromNode(Expr $node, Scope $scope): ?string;
18+
/**
19+
* @return array<string>
20+
*/
21+
public static function getParameterKeysFromNode(Expr $node, Scope $scope): array;
1922

2023
}

‎src/Type/Symfony/ParameterDynamicReturnTypeExtension.php

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private function getGetTypeFromMethodCall(
113113
{
114114
// We don't use the method's return type because this won't work properly with lowest and
115115
// highest versions of Symfony ("mixed" for lowest, "array|bool|float|integer|string|null" for highest).
116-
$returnType = new UnionType([
116+
$defaultReturnType = new UnionType([
117117
new ArrayType(new MixedType(), new MixedType()),
118118
new BooleanType(),
119119
new FloatType(),
@@ -122,18 +122,25 @@ private function getGetTypeFromMethodCall(
122122
new NullType(),
123123
]);
124124
if (!isset($methodCall->getArgs()[0])) {
125-
return $returnType;
125+
return $defaultReturnType;
126126
}
127127

128-
$parameterKey = $this->parameterMap::getParameterKeyFromNode($methodCall->getArgs()[0]->value, $scope);
129-
if ($parameterKey !== null) {
128+
$parameterKeys = $this->parameterMap::getParameterKeysFromNode($methodCall->getArgs()[0]->value, $scope);
129+
if ($parameterKeys === []) {
130+
return $defaultReturnType;
131+
}
132+
133+
$returnTypes = [];
134+
foreach ($parameterKeys as $parameterKey) {
130135
$parameter = $this->parameterMap->getParameter($parameterKey);
131-
if ($parameter !== null) {
132-
return $this->generalizeTypeFromValue($scope, $parameter->getValue());
136+
if ($parameter === null) {
137+
return $defaultReturnType;
133138
}
139+
140+
$returnTypes[] = $this->generalizeTypeFromValue($scope, $parameter->getValue());
134141
}
135142

136-
return $returnType;
143+
return TypeCombinator::union(...$returnTypes);
137144
}
138145

139146
/**
@@ -211,18 +218,31 @@ private function getHasTypeFromMethodCall(
211218
Scope $scope
212219
): Type
213220
{
214-
$returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
221+
$defaultReturnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
215222
if (!isset($methodCall->getArgs()[0]) || !$this->constantHassers) {
216-
return $returnType;
223+
return $defaultReturnType;
217224
}
218225

219-
$parameterKey = $this->parameterMap::getParameterKeyFromNode($methodCall->getArgs()[0]->value, $scope);
220-
if ($parameterKey !== null) {
226+
$parameterKeys = $this->parameterMap::getParameterKeysFromNode($methodCall->getArgs()[0]->value, $scope);
227+
if ($parameterKeys === []) {
228+
return $defaultReturnType;
229+
}
230+
231+
$has = null;
232+
foreach ($parameterKeys as $parameterKey) {
221233
$parameter = $this->parameterMap->getParameter($parameterKey);
222-
return new ConstantBooleanType($parameter !== null);
234+
235+
if ($has === null) {
236+
$has = $parameter !== null;
237+
} elseif (
238+
($has === true && $parameter === null)
239+
|| ($has === false && $parameter !== null)
240+
) {
241+
return $defaultReturnType;
242+
}
223243
}
224244

225-
return $returnType;
245+
return newConstantBooleanType($has);
226246
}
227247

228248
}

‎tests/Type/Symfony/data/ExampleController.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ public function parameters(ContainerInterface $container, ParameterBagInterface
116116
assertType('true', $parameterBag->has('app.binary'));
117117
assertType('true', $container->hasParameter('app.constant'));
118118
assertType('true', $parameterBag->has('app.constant'));
119+
120+
$key = rand(0, 1) ? 'app.string' : 'app.int';
121+
assertType("int|string", $container->getParameter($key));
122+
assertType("int|string", $parameterBag->get($key));
123+
assertType("int|string", $this->getParameter($key));
124+
assertType('true', $container->hasParameter($key));
125+
assertType('true', $parameterBag->has($key));
126+
127+
$key = rand(0, 1) ? 'app.string' : 'app.foo';
128+
assertType("array|bool|float|int|string|null", $container->getParameter($key));
129+
assertType("array|bool|float|int|string|null", $parameterBag->get($key));
130+
assertType("array|bool|float|int|string|null", $this->getParameter($key));
131+
assertType('bool', $container->hasParameter($key));
132+
assertType('bool', $parameterBag->has($key));
133+
134+
$key = rand(0, 1) ? 'app.bar' : 'app.foo';
135+
assertType("array|bool|float|int|string|null", $container->getParameter($key));
136+
assertType("array|bool|float|int|string|null", $parameterBag->get($key));
137+
assertType("array|bool|float|int|string|null", $this->getParameter($key));
138+
assertType('false', $container->hasParameter($key));
139+
assertType('false', $parameterBag->has($key));
119140
}
120141

121142
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /