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 77118a5

Browse files
committed
Specify type after calling InputBag::has
1 parent df5ce32 commit 77118a5

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

‎extension.neon‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,8 @@ services:
278278
-
279279
factory: PHPStan\Type\Symfony\ResponseHeaderBagDynamicReturnTypeExtension
280280
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
281+
282+
# InputBag::get() type specification
283+
-
284+
factory: PHPStan\Type\Symfony\InputBagTypeSpecifyingExtension
285+
tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Symfony;
4+
5+
use PhpParser\Node\Expr\MethodCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Analyser\SpecifiedTypes;
8+
use PHPStan\Analyser\TypeSpecifier;
9+
use PHPStan\Analyser\TypeSpecifierAwareExtension;
10+
use PHPStan\Analyser\TypeSpecifierContext;
11+
use PHPStan\Reflection\MethodReflection;
12+
use PHPStan\Reflection\ParametersAcceptorSelector;
13+
use PHPStan\Reflection\ReflectionProvider;
14+
use PHPStan\Type\MethodTypeSpecifyingExtension;
15+
use PHPStan\Type\TypeCombinator;
16+
use Symfony\Component\HttpFoundation\InputBag;
17+
18+
final class InputBagTypeSpecifyingExtension implements MethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
19+
{
20+
21+
private const INPUT_BAG_CLASS = InputBag::class;
22+
private const HAS_METHOD_NAME = 'has';
23+
private const GET_METHOD_NAME = 'get';
24+
25+
/** @var ReflectionProvider */
26+
private $reflectionProvider;
27+
28+
/** @var TypeSpecifier */
29+
private $typeSpecifier;
30+
31+
public function __construct(ReflectionProvider $reflectionProvider,)
32+
{
33+
$this->reflectionProvider = $reflectionProvider;
34+
}
35+
36+
public function getClass(): string
37+
{
38+
return self::INPUT_BAG_CLASS;
39+
}
40+
41+
public function isMethodSupported(MethodReflection $methodReflection, MethodCall $node, TypeSpecifierContext $context): bool
42+
{
43+
return $methodReflection->getName() === self::HAS_METHOD_NAME && !$context->null();
44+
}
45+
46+
public function specifyTypes(MethodReflection $methodReflection, MethodCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
47+
{
48+
$classReflection = $this->reflectionProvider->getClass(self::INPUT_BAG_CLASS);
49+
$methodVariants = $classReflection->getNativeMethod(self::GET_METHOD_NAME)->getVariants();
50+
$returnType = ParametersAcceptorSelector::selectSingle($methodVariants)->getReturnType();
51+
52+
if (!TypeCombinator::containsNull($returnType)) {
53+
return new SpecifiedTypes();
54+
}
55+
56+
return $this->typeSpecifier->create(
57+
new MethodCall($node->var, self::GET_METHOD_NAME, $node->getArgs()),
58+
TypeCombinator::removeNull($returnType),
59+
$context
60+
);
61+
}
62+
63+
public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void
64+
{
65+
$this->typeSpecifier = $typeSpecifier;
66+
}
67+
68+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
$bag = new \Symfony\Component\HttpFoundation\InputBag(['foo' => 'bar', 'bar' => ['x']]);
66

77
assertType('bool|float|int|string|null', $bag->get('foo'));
8+
9+
if ($bag->has('foo')) {
10+
assertType('bool|float|int|string', $bag->get('foo'));
11+
assertType('bool|float|int|string|null', $bag->get('bar'));
12+
}
13+
814
assertType('bool|float|int|string|null', $bag->get('foo', null));
915
assertType('bool|float|int|string', $bag->get('foo', ''));
1016
assertType('bool|float|int|string', $bag->get('foo', 'baz'));

0 commit comments

Comments
(0)

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