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 90ed4f1

Browse files
Bleksakondrejmirtes
authored andcommitted
fix getValues() invalid type
1 parent ad594d4 commit 90ed4f1

File tree

3 files changed

+79
-97
lines changed

3 files changed

+79
-97
lines changed

‎src/Type/Nette/FormContainerValuesDynamicReturnTypeExtension.php‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,36 @@ public function isMethodSupported(MethodReflection $methodReflection): bool
2626
return $methodReflection->getName() === 'getValues';
2727
}
2828

29-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
29+
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
3030
{
31-
if (count($methodCall->getArgs()) === 0) {
31+
$args = $methodCall->getArgs();
32+
33+
if (count($args) === 0) {
3234
return new ObjectType('Nette\Utils\ArrayHash');
3335
}
3436

35-
$arg = $methodCall->getArgs()[0]->value;
37+
$arg = $args[0]->value;
3638
$scopedType = $scope->getType($arg);
37-
if ($scopedType->isTrue()->yes()) {
38-
returnnewArrayType(newStringType(), newMixedType());
39-
}
40-
if ($scopedType->isFalse()->yes()) {
39+
40+
$constantStrings = $scopedType->getConstantStrings();
41+
42+
if (count($constantStrings) === 0) {
4143
return new ObjectType('Nette\Utils\ArrayHash');
4244
}
4345

44-
return null;
46+
$constantString = $constantStrings[0];
47+
48+
$value = $constantString->getValue();
49+
50+
if ($scopedType->isClassString()->yes()) {
51+
return $scopedType->getClassStringObjectType();
52+
}
53+
54+
if ($value === 'array') {
55+
return new ArrayType(new StringType(), new MixedType());
56+
}
57+
58+
return new ObjectType('Nette\Utils\ArrayHash');
4559
}
4660

4761
}

‎tests/Type/Nette/FormContainerValuesDynamicReturnTypeExtensionTest.php‎

Lines changed: 20 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,106 +2,37 @@
22

33
namespace PHPStan\Type\Nette;
44

5-
use Nette\Utils\ArrayHash;
6-
use PhpParser\Node\Arg;
7-
use PhpParser\Node\Expr;
8-
use PhpParser\Node\Expr\MethodCall;
9-
use PHPStan\Analyser\Scope;
10-
use PHPStan\Reflection\FunctionVariant;
11-
use PHPStan\Reflection\MethodReflection;
12-
use PHPStan\Type\ArrayType;
13-
use PHPStan\Type\Constant\ConstantBooleanType;
14-
use PHPStan\Type\Generic\TemplateTypeMap;
15-
use PHPStan\Type\IterableType;
16-
use PHPStan\Type\MixedType;
17-
use PHPStan\Type\ObjectType;
18-
use PHPStan\Type\UnionType;
19-
use PHPStan\Type\VerbosityLevel;
20-
use PHPUnit\Framework\TestCase;
5+
use PHPStan\Testing\TypeInferenceTestCase;
216

22-
final class FormContainerValuesDynamicReturnTypeExtensionTest extends TestCase
7+
final class FormContainerValuesDynamicReturnTypeExtensionTest extends TypeInferenceTestCase
238
{
249

25-
private FormContainerValuesDynamicReturnTypeExtension $extension;
26-
27-
protected function setUp(): void
10+
/**
11+
* @return iterable<string, mixed[]>
12+
*/
13+
public static function dataFileAsserts(): iterable
2814
{
29-
$this->extension = newFormContainerValuesDynamicReturnTypeExtension();
15+
yieldfromself::gatherAssertTypes(__DIR__ . '/data/FormContainerModel.php');
3016
}
3117

32-
public function testParameterAsArray(): void
18+
/**
19+
* @dataProvider dataFileAsserts
20+
* @param mixed ...$args
21+
*/
22+
public function testFileAsserts(
23+
string $assertType,
24+
string $file,
25+
...$args
26+
): void
3327
{
34-
$methodReflection = $this->createMock(MethodReflection::class);
35-
$methodReflection
36-
->method('getVariants')
37-
->willReturn([new FunctionVariant(
38-
TemplateTypeMap::createEmpty(),
39-
TemplateTypeMap::createEmpty(),
40-
[],
41-
true,
42-
new UnionType([new ArrayType(new MixedType(), new MixedType()), new IterableType(new MixedType(), new ObjectType(ArrayHash::class))]),
43-
)]);
44-
45-
$scope = $this->createMock(Scope::class);
46-
$scope->method('getType')->willReturn(new ConstantBooleanType(true));
47-
48-
$methodCall = $this->createMock(MethodCall::class);
49-
$arg = $this->createMock(Arg::class);
50-
$value = $this->createMock(Expr::class);
51-
$arg->value = $value;
52-
$methodCall->args = [
53-
0 => $arg,
54-
];
55-
$methodCall->method('getArgs')->willReturn($methodCall->args);
56-
57-
$resultType = $this->extension->getTypeFromMethodCall($methodReflection, $methodCall, $scope);
58-
59-
self::assertInstanceOf(ArrayType::class, $resultType);
28+
$this->assertFileAsserts($assertType, $file, ...$args);
6029
}
6130

62-
public function testParameterAsArrayHash(): void
31+
public staticfunction getAdditionalConfigFiles(): array
6332
{
64-
$methodReflection = $this->createMock(MethodReflection::class);
65-
$methodReflection
66-
->method('getVariants')
67-
->willReturn([new FunctionVariant(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], true, new UnionType([new ArrayType(new MixedType(), new MixedType()), new IterableType(new MixedType(), new ObjectType(ArrayHash::class))]))]);
68-
69-
$scope = $this->createMock(Scope::class);
70-
$scope->method('getType')->willReturn(new ConstantBooleanType(false));
71-
72-
$methodCall = $this->createMock(MethodCall::class);
73-
$arg = $this->createMock(Arg::class);
74-
$value = $this->createMock(Expr::class);
75-
$arg->value = $value;
76-
$methodCall->args = [
77-
0 => $arg,
33+
return [
34+
__DIR__ . '/phpstan.neon',
7835
];
79-
$methodCall->method('getArgs')->willReturn($methodCall->args);
80-
81-
$resultType = $this->extension->getTypeFromMethodCall($methodReflection, $methodCall, $scope);
82-
83-
self::assertInstanceOf(ObjectType::class, $resultType);
84-
self::assertSame(ArrayHash::class, $resultType->describe(VerbosityLevel::value()));
85-
}
86-
87-
public function testDefaultParameterIsArrayHash(): void
88-
{
89-
$methodReflection = $this->createMock(MethodReflection::class);
90-
$methodReflection
91-
->method('getVariants')
92-
->willReturn([new FunctionVariant(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], true, new UnionType([new ArrayType(new MixedType(), new MixedType()), new IterableType(new MixedType(), new ObjectType(ArrayHash::class))]))]);
93-
94-
$scope = $this->createMock(Scope::class);
95-
$scope->method('getType')->willReturn(new ConstantBooleanType(false));
96-
97-
$methodCall = $this->createMock(MethodCall::class);
98-
$methodCall->args = [];
99-
$methodCall->method('getArgs')->willReturn($methodCall->args);
100-
101-
$resultType = $this->extension->getTypeFromMethodCall($methodReflection, $methodCall, $scope);
102-
103-
self::assertInstanceOf(ObjectType::class, $resultType);
104-
self::assertSame(ArrayHash::class, $resultType->describe(VerbosityLevel::value()));
10536
}
10637

10738
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace PHPStan\Type\Nette\Data\FormContainerModel;
4+
5+
use Nette\Forms\Form;
6+
use function PHPStan\Testing\assertType;
7+
8+
class Dto
9+
{
10+
public string $name;
11+
public string $value;
12+
13+
public function __construct(
14+
string $name,
15+
string $value
16+
)
17+
{
18+
$this->name = $name;
19+
$this->name = $value;
20+
}
21+
}
22+
23+
class FormContainerModel
24+
{
25+
public function test()
26+
{
27+
$form = new Form();
28+
$form->addText('name');
29+
$form->addText('value');
30+
31+
$dto = $form->getValues(Dto::class);
32+
$array = $form->getValues('array');
33+
34+
assertType(Dto::class, $dto);
35+
assertType('array<string, mixed>', $array);
36+
}
37+
}

0 commit comments

Comments
(0)

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