Skip to content

Commit 077e36e

Browse files
committed
fixed PHPStan errors [WIP]
1 parent 7c3b073 commit 077e36e

20 files changed

Lines changed: 163 additions & 75 deletions

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
],
1717
"require": {
1818
"php": "8.1 - 8.5",
19-
"nette/component-model": "^3.1",
19+
"nette/component-model": "3.1.x-dev",
2020
"nette/http": "^3.3",
2121
"nette/utils": "^4.0.10"
2222
},

phpstan-baseline.neon

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,20 @@ parameters:
3131
path: src/Forms/Blueprint.php
3232

3333
-
34-
message: '#^Method Nette\\Forms\\Controls\\BaseControl@anonymous/Forms/Blueprint\.php\:97\:\:getControl\(\) never returns Nette\\Utils\\Html so it can be removed from the return type\.$#'
34+
message: '#^Method Nette\\Forms\\Controls\\BaseControl@anonymous/Forms/Blueprint\.php\:94\:\:getLabel\(\) never returns null so it can be removed from the return type\.$#'
3535
identifier: return.unusedType
3636
count: 1
3737
path: src/Forms/Blueprint.php
3838

3939
-
40-
message: '#^Method Nette\\Forms\\Controls\\BaseControl@anonymous/Forms/Blueprint\.php\:97\:\:getLabel\(\) never returns Nette\\Utils\\Html so it can be removed from the return type\.$#'
41-
identifier: return.unusedType
42-
count: 1
43-
path: src/Forms/Blueprint.php
44-
45-
-
46-
message: '#^Method Nette\\Forms\\Form@anonymous/Forms/Blueprint\.php\:89\:\:receiveHttpData\(\) never returns null so it can be removed from the return type\.$#'
47-
identifier: return.unusedType
40+
message: '#^Property Nette\\Forms\\Controls\\BaseControl@anonymous/Forms/Blueprint\.php\:94\:\:\$inner \(Nette\\Forms\\Controls\\BaseControl\) does not accept Nette\\Forms\\Control\.$#'
41+
identifier: assign.propertyType
4842
count: 1
4943
path: src/Forms/Blueprint.php
5044

5145
-
52-
message: '#^Property Nette\\Forms\\Controls\\BaseControl@anonymous/Forms/Blueprint\.php\:97\:\:\$inner has no type specified\.$#'
53-
identifier: missingType.property
46+
message: '#^Ternary operator condition is always true\.$#'
47+
identifier: ternary.alwaysTrue
5448
count: 1
5549
path: src/Forms/Blueprint.php
5650

@@ -84,12 +78,6 @@ parameters:
8478
count: 1
8579
path: src/Forms/Container.php
8680

87-
-
88-
message: '#^Unable to resolve the template type T in call to method Nette\\Forms\\Container\:\:getUntrustedValues\(\)$#'
89-
identifier: argument.templateType
90-
count: 1
91-
path: src/Forms/Container.php
92-
9381
-
9482
message: '#^Call to an undefined method Nette\\Forms\\Control\:\:getForm\(\)\.$#'
9583
identifier: method.notFound
@@ -150,18 +138,54 @@ parameters:
150138
count: 1
151139
path: src/Forms/Controls/CheckboxList.php
152140

141+
-
142+
message: '#^Parameter \#1 \$value \(BackedEnum\|int\|string\|null\) of method Nette\\Forms\\Controls\\ChoiceControl\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Control\:\:setValue\(\)$#'
143+
identifier: method.childParameterType
144+
count: 1
145+
path: src/Forms/Controls/ChoiceControl.php
146+
147+
-
148+
message: '#^Parameter \#1 \$value \(BackedEnum\|int\|string\|null\) of method Nette\\Forms\\Controls\\ChoiceControl\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Controls\\BaseControl\:\:setValue\(\)$#'
149+
identifier: method.childParameterType
150+
count: 1
151+
path: src/Forms/Controls/ChoiceControl.php
152+
153153
-
154154
message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
155155
identifier: function.alreadyNarrowedType
156156
count: 1
157157
path: src/Forms/Controls/ColorPicker.php
158158

159+
-
160+
message: '#^Parameter \#1 \$value \(string\|null\) of method Nette\\Forms\\Controls\\ColorPicker\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Control\:\:setValue\(\)$#'
161+
identifier: method.childParameterType
162+
count: 1
163+
path: src/Forms/Controls/ColorPicker.php
164+
165+
-
166+
message: '#^Parameter \#1 \$value \(string\|null\) of method Nette\\Forms\\Controls\\ColorPicker\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Controls\\BaseControl\:\:setValue\(\)$#'
167+
identifier: method.childParameterType
168+
count: 1
169+
path: src/Forms/Controls/ColorPicker.php
170+
159171
-
160172
message: '#^Match expression does not handle remaining values\: int\<min, 0\>\|int\<4, max\>$#'
161173
identifier: match.unhandled
162174
count: 4
163175
path: src/Forms/Controls/DateTimeControl.php
164176

177+
-
178+
message: '#^Parameter \#1 \$value \(DateTimeInterface\|int\|string\|null\) of method Nette\\Forms\\Controls\\DateTimeControl\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Control\:\:setValue\(\)$#'
179+
identifier: method.childParameterType
180+
count: 1
181+
path: src/Forms/Controls/DateTimeControl.php
182+
183+
-
184+
message: '#^Parameter \#1 \$value \(DateTimeInterface\|int\|string\|null\) of method Nette\\Forms\\Controls\\DateTimeControl\:\:setValue\(\) should be contravariant with parameter \$value \(mixed\) of method Nette\\Forms\\Controls\\BaseControl\:\:setValue\(\)$#'
185+
identifier: method.childParameterType
186+
count: 1
187+
path: src/Forms/Controls/DateTimeControl.php
188+
165189
-
166190
message: '#^Method Nette\\Forms\\Controls\\HiddenField\:\:getLabel\(\) has parameter \$caption with no type specified\.$#'
167191
identifier: missingType.parameter
@@ -192,12 +216,6 @@ parameters:
192216
count: 1
193217
path: src/Forms/Controls/SubmitButton.php
194218

195-
-
196-
message: '#^Call to an undefined method Nette\\ComponentModel\\IComponent\:\:getValue\(\)\.$#'
197-
identifier: method.notFound
198-
count: 1
199-
path: src/Forms/Form.php
200-
201219
-
202220
message: '#^Call to an undefined method Nette\\Forms\\Control\:\:getParent\(\)\.$#'
203221
identifier: method.notFound
@@ -216,6 +234,12 @@ parameters:
216234
count: 1
217235
path: src/Forms/Form.php
218236

237+
-
238+
message: '#^Return type \(static\(Nette\\Forms\\Form\)\) of method Nette\\Forms\\Form\:\:getForm\(\) should be covariant with return type \(\(\$throw is true \? Nette\\Forms\\Form \: Nette\\Forms\\Form\|null\)\) of method Nette\\Forms\\Container\:\:getForm\(\)$#'
239+
identifier: method.childReturnType
240+
count: 1
241+
path: src/Forms/Form.php
242+
219243
-
220244
message: '#^Call to an undefined method Nette\\Forms\\Control\:\:getHtmlName\(\)\.$#'
221245
identifier: method.notFound
@@ -228,12 +252,6 @@ parameters:
228252
count: 1
229253
path: src/Forms/Helpers.php
230254

231-
-
232-
message: '#^Parameter \#1 \$callback of function array_map expects \(callable\(Nette\\Utils\\ImageType\)\: mixed\)\|null, Closure\(1\|2\|3\|6\|18\|19\)\: string given\.$#'
233-
identifier: argument.type
234-
count: 1
235-
path: src/Forms/Helpers.php
236-
237255
-
238256
message: '#^Strict comparison using \=\=\= between '''' and '''' will always evaluate to true\.$#'
239257
identifier: identical.alwaysTrue

phpstan.neon

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 6
2+
level: 8
33

44
paths:
55
- src
@@ -13,5 +13,56 @@ parameters:
1313
identifier: new.static
1414
path: src/Bridges/FormsLatte/Nodes/*
1515

16+
- # Html properties accept broader types (bool for attribute removal, mixed for flexibility)
17+
identifier: assign.propertyType
18+
paths:
19+
- src/Forms/Controls/BaseControl.php
20+
- src/Forms/Controls/TextBase.php
21+
- src/Forms/Controls/TextInput.php
22+
- src/Forms/Form.php
23+
24+
- # Control interface intentionally minimal; BaseControl provides full implementation
25+
identifier: method.notFound
26+
reportUnmatched: false
27+
paths:
28+
- src/Forms/Controls/SubmitButton.php
29+
30+
- # getLabel() returns Html in base but children legitimately widen to Html|string|null
31+
identifier: method.childReturnType
32+
reportUnmatched: false
33+
paths:
34+
- src/Forms/Controls/Button.php
35+
- src/Forms/Controls/Checkbox.php
36+
- src/Forms/Controls/HiddenField.php
37+
- src/Forms/Blueprint.php
38+
39+
- # DateTimeControl formatHtmlValue accepts broader types from rule args
40+
message: '#^Parameter \#1 \$value of method Nette\\Forms\\Controls\\DateTimeControl\:\:formatHtmlValue\(\)#'
41+
path: src/Forms/Controls/DateTimeControl.php
42+
43+
- # getSingleType() returns ?string, template T cannot be resolved from plain string
44+
identifier: argument.templateType
45+
reportUnmatched: false
46+
paths:
47+
- src/Forms/Container.php
48+
- src/Forms/Form.php
49+
50+
- # getSingleType() returns ?string which is not class-string<T> but is correct at runtime
51+
message: '#^Parameter \#1 \$returnType of method Nette\\Forms\\Container\:\:(getValues|getUntrustedValues)\(\) expects#'
52+
reportUnmatched: false
53+
paths:
54+
- src/Forms/Container.php
55+
- src/Forms/Form.php
56+
57+
- # Deprecated method with untyped parameters
58+
message: '#^Parameter \#2 \$controls of method Nette\\Forms\\Container\:\:getUntrustedValues\(\) expects#'
59+
path: src/Forms/Container.php
60+
count: 1
61+
62+
- # Complex generic return types not fully expressible
63+
identifier: return.type
64+
paths:
65+
- src/Forms/Container.php
66+
1667
includes:
1768
- phpstan-baseline.neon

src/Bridges/FormsDI/FormsExtension.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace Nette\Bridges\FormsDI;
99

1010
use Nette;
11-
use function defined, is_object;
11+
use function defined;
1212

1313

1414
/**
@@ -29,8 +29,9 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
2929
{
3030
$initialize = $this->initialization ?? $class->getMethod('initialize');
3131

32-
assert(is_object($this->config));
33-
foreach ($this->config->messages as $name => $text) {
32+
/** @var object{messages: array<string, string>} $config */
33+
$config = $this->config;
34+
foreach ($config->messages as $name => $text) {
3435
if (defined('Nette\Forms\Form::' . $name)) {
3536
$initialize->addBody('Nette\Forms\Validator::$messages[Nette\Forms\Form::?] = ?;', [$name, $text]);
3637
} elseif (defined($name)) {

src/Bridges/FormsLatte/FormsExtension.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ public function getTags(): array
2727
'inputError' => Nodes\InputErrorNode::create(...),
2828
'formPrint' => Nodes\FormPrintNode::create(...),
2929
'formClassPrint' => Nodes\FormPrintNode::create(...),
30-
'n:name' => fn(Latte\Compiler\Tag $tag) => yield from strtolower($tag->htmlElement->name) === 'form'
31-
? Nodes\FormNNameNode::create($tag)
32-
: Nodes\FieldNNameNode::create($tag),
30+
'n:name' => function (Latte\Compiler\Tag $tag) {
31+
assert($tag->htmlElement !== null);
32+
return yield from strtolower($tag->htmlElement->name) === 'form'
33+
? Nodes\FormNNameNode::create($tag)
34+
: Nodes\FieldNNameNode::create($tag);
35+
},
3336
];
3437
}
3538

src/Bridges/FormsLatte/Nodes/FieldNNameNode.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public function print(PrintContext $context): string
6060
private function init(Tag $tag): void
6161
{
6262
$el = $tag->htmlElement;
63+
assert($el !== null);
6364
$usedAttributes = self::findUsedAttributes($el);
6465
$elName = strtolower($el->name);
6566

src/Bridges/FormsLatte/Nodes/FormNNameNode.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ public function print(PrintContext $context): string
5959
private function init(Tag $tag): void
6060
{
6161
$el = $tag->htmlElement;
62+
assert($el !== null);
6263

6364
$tag->replaceNAttribute(new AuxiliaryNode(fn(PrintContext $context) => $context->format(
6465
'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), %dump, false) %line;',
6566
array_fill_keys(FieldNNameNode::findUsedAttributes($el), null),
6667
$this->position,
6768
)));
6869

70+
assert($el->content !== null);
6971
$el->content = new Latte\Compiler\Nodes\FragmentNode([
7072
$el->content,
7173
new AuxiliaryNode(fn(PrintContext $context) => $context->format(

src/Bridges/FormsLatte/Runtime.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static function renderFormBegin(Form $form, array $attrs, bool $withTags
4444
$el->action = (string) $el->action;
4545
$el = clone $el;
4646
if ($form->isMethod('get')) {
47-
$el->action = preg_replace('~\?[^#]*~', '', $el->action, 1);
47+
$el->action = preg_replace('~\?[^#]*~', '', (string) $el->action, 1);
4848
}
4949

5050
$el->addAttributes($attrs);
@@ -59,7 +59,7 @@ public static function renderFormEnd(Form $form, bool $withTags = true): string
5959
{
6060
$s = '';
6161
if ($form->isMethod('get')) {
62-
foreach (preg_split('#[;&]#', (string) parse_url($form->getElementPrototype()->action, PHP_URL_QUERY), -1, PREG_SPLIT_NO_EMPTY) as $param) {
62+
foreach (preg_split('#[;&]#', (string) parse_url((string) $form->getElementPrototype()->action, PHP_URL_QUERY), -1, PREG_SPLIT_NO_EMPTY) as $param) {
6363
$parts = explode('=', $param, 2);
6464
$name = urldecode($parts[0]);
6565
$prefix = explode('[', $name, 2)[0];

src/Forms/Blueprint.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
namespace Nette\Forms;
99

10-
use Nette\Utils\Html;
1110

1211

1312
/**
@@ -85,26 +84,26 @@ public function generateLatte(Form $form): string
8584
{
8685
$dict = new \SplObjectStorage;
8786
$dummyForm = new class extends Form {
88-
protected function receiveHttpData(): ?array
87+
protected function receiveHttpData(): array
8988
{
9089
return [];
9190
}
9291
};
9392

9493
foreach ($form->getControls() as $input) {
9594
$dict[$input] = $dummyInput = new class extends Controls\BaseControl {
96-
public $inner;
95+
public Controls\BaseControl $inner;
9796

9897

99-
public function getLabel(string|\Stringable|null $caption = null): Html|string|null
98+
public function getLabel(string|\Stringable|null $caption = null): string|null
10099
{
101100
return $this->inner->getLabel()
102101
? '{label ' . $this->inner->lookupPath(Form::class) . '/}'
103102
: null;
104103
}
105104

106105

107-
public function getControl(): Html|string
106+
public function getControl(): string
108107
{
109108
return '{input ' . $this->inner->lookupPath(Form::class) . '}';
110109
}
@@ -206,7 +205,7 @@ public function generateDataClass(
206205
$type = '?' . $type;
207206
}
208207
} elseif ($input instanceof Container) {
209-
$type = $baseName . ucwords($name);
208+
$type = $baseName . ucwords((string) $name);
210209
$nextCode .= $this->generateDataClass($input, $propertyPromotion, $type);
211210
$type .= self::ClassNameSuffix;
212211
} else {

src/Forms/Container.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function setValues(array|object $values, bool $erase = false, bool $onlyD
8686
* Returns the values submitted by the form.
8787
* @template T of object
8888
* @param class-string<T>|T|'array'|true|null $returnType
89-
* @param ?list<Control> $controls
89+
* @param ?list<Control|self> $controls
9090
* @return ($returnType is class-string<T>|T ? T : ($returnType is 'array'|true ? mixed[] : ArrayHash<mixed>))
9191
*/
9292
public function getValues(string|object|bool|null $returnType = null, ?array $controls = null): object|array
@@ -127,7 +127,7 @@ public function getValues(string|object|bool|null $returnType = null, ?array $co
127127
* Returns the potentially unvalidated values submitted by the form.
128128
* @template T of object
129129
* @param class-string<T>|T|'array'|null $returnType
130-
* @param ?list<Control> $controls
130+
* @param ?list<Control|self> $controls
131131
* @return ($returnType is class-string<T>|T ? T : ($returnType is 'array' ? mixed[] : ArrayHash<mixed>))
132132
*/
133133
public function getUntrustedValues(string|object|null $returnType = null, ?array $controls = null): object|array
@@ -138,6 +138,7 @@ public function getUntrustedValues(string|object|null $returnType = null, ?array
138138

139139
} else {
140140
$returnType ??= $this->mappedType ?? ArrayHash::class;
141+
/** @var class-string|'array' $returnType */
141142
$rc = new \ReflectionClass($returnType === self::Array ? \stdClass::class : $returnType);
142143
$constructor = $rc->hasMethod('__construct') ? $rc->getMethod('__construct') : null;
143144
if ($constructor?->getNumberOfRequiredParameters()) {
@@ -257,7 +258,7 @@ public function getErrors(): array
257258
$errors = array_merge($errors, $control->getErrors());
258259
}
259260

260-
return array_unique($errors);
261+
return array_values(array_unique($errors));
261262
}
262263

263264

0 commit comments

Comments
 (0)