Skip to content

Commit c6684dd

Browse files
committed
Nette\Application\UI\Multiplier factory can return null
1 parent 3320991 commit c6684dd

File tree

5 files changed

+104
-2
lines changed

5 files changed

+104
-2
lines changed

extension.neon

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ parameters:
77
stubFiles:
88
- stubs/Application/Routers/RouteList.stub
99
- stubs/Application/UI/Component.stub
10-
- stubs/Application/UI/Multiplier.stub
1110
- stubs/Application/UI/Presenter.stub
1211
- stubs/Caching/Cache.stub
1312
- stubs/ComponentModel/Component.stub
@@ -52,6 +51,11 @@ parameters:
5251
- forward
5352

5453
services:
54+
-
55+
class: PHPStan\Stubs\Nette\Application\StubFilesExtensionLoader
56+
tags:
57+
- phpstan.stubFilesExtension
58+
5559
-
5660
class: PHPStan\Reflection\Nette\HtmlClassReflectionExtension
5761
tags:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Stubs\Nette\Application;
4+
5+
use Composer\InstalledVersions;
6+
use OutOfBoundsException;
7+
use PHPStan\PhpDoc\StubFilesExtension;
8+
use function class_exists;
9+
use function dirname;
10+
use function version_compare;
11+
12+
class StubFilesExtensionLoader implements StubFilesExtension
13+
{
14+
15+
public function getFiles(): array
16+
{
17+
$path = dirname(dirname(dirname(dirname(__DIR__)))) . '/stubs';
18+
19+
try {
20+
$applicationVersion = class_exists(InstalledVersions::class)
21+
? InstalledVersions::getVersion('nette/application')
22+
: null;
23+
} catch (OutOfBoundsException $e) {
24+
$applicationVersion = null;
25+
}
26+
27+
$files = [];
28+
29+
if ($applicationVersion !== null && version_compare($applicationVersion, '3.2.5', '>=')) {
30+
$files[] = $path . '/Application/UI/Multiplier1.stub';
31+
} else {
32+
$files[] = $path . '/Application/UI/Multiplier.stub';
33+
}
34+
35+
return $files;
36+
}
37+
38+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Nette\Application\UI;
4+
5+
/**
6+
* @template T of \Nette\ComponentModel\IComponent|null
7+
*/
8+
final class Multiplier extends Component
9+
{
10+
/**
11+
* @param callable(string, self<T>) : T $factory
12+
*/
13+
public function __construct(callable $factory);
14+
15+
/**
16+
* @return T
17+
*/
18+
protected function createComponent(string $name): \Nette\ComponentModel\IComponent;
19+
}

tests/Type/Nette/MultiplierTest.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,30 @@
22

33
namespace PHPStan\Type\Nette;
44

5+
use Composer\InstalledVersions;
6+
use OutOfBoundsException;
57
use PHPStan\Testing\TypeInferenceTestCase;
8+
use function class_exists;
9+
use function version_compare;
610

711
class MultiplierTest extends TypeInferenceTestCase
812
{
913

1014
public function dataFileAsserts(): iterable
1115
{
12-
yield from self::gatherAssertTypes(__DIR__ . '/data/multiplier.php');
16+
try {
17+
$applicationVersion = class_exists(InstalledVersions::class)
18+
? InstalledVersions::getVersion('nette/application')
19+
: null;
20+
} catch (OutOfBoundsException $e) {
21+
$applicationVersion = null;
22+
}
23+
24+
if ($applicationVersion !== null && version_compare($applicationVersion, '3.2.5', '>=')) {
25+
yield from self::gatherAssertTypes(__DIR__ . '/data/multiplierApplication325.php');
26+
} else {
27+
yield from self::gatherAssertTypes(__DIR__ . '/data/multiplier.php');
28+
}
1329
}
1430

1531
/**
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types = 1);
2+
3+
use Nette\Application\UI\Form;
4+
use Nette\Application\UI\Multiplier;
5+
6+
use function PHPStan\Testing\assertType;
7+
8+
/** @var Multiplier<Form|null> $multiplier */
9+
$multiplier = new Multiplier(function (string $name): ?Form {
10+
if($name === 'foo') {
11+
return new Form();
12+
} else {
13+
return null;
14+
}
15+
});
16+
17+
assertType('Nette\Application\UI\Multiplier<Nette\Application\UI\Form|null>', $multiplier);
18+
19+
$form = $multiplier->createComponent('foo');
20+
21+
assertType(Form::class, $form);
22+
23+
$notSupportedForm = $multiplier->createComponent('notSupported');
24+
25+
assertType(null, $notSupportedForm);

0 commit comments

Comments
 (0)