Merge pull request #7 from silverstripeltd/feature/add-generics-to-injector

MNT Add generic type arguments to Injector
This commit is contained in:
Cameron Bryers 2023-11-15 14:00:10 +13:00 committed by GitHub
commit 265c986550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 6 deletions

View File

@ -61,7 +61,8 @@
"require-dev": {
"phpunit/phpunit": "^9.6",
"silverstripe/versioned": "^2",
"squizlabs/php_codesniffer": "^3.7"
"squizlabs/php_codesniffer": "^3.7",
"phpstan/phpstan": "^1.10"
},
"conflict": {
"egulias/email-validator": "^2",
@ -97,7 +98,8 @@
"SilverStripe\\Security\\Tests\\": "tests/php/Security/",
"SilverStripe\\View\\": "src/View/",
"SilverStripe\\View\\Tests\\": "tests/php/View/",
"SilverStripe\\Framework\\Tests\\Behaviour\\": "tests/behat/src/"
"SilverStripe\\Framework\\Tests\\Behaviour\\": "tests/behat/src/",
"SilverStripe\\Type\\Tests\\": "tests/php/Type/"
},
"files": [
"src/includes/constants.php"

View File

@ -966,12 +966,14 @@ class Injector implements ContainerInterface
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
*
* @param string $name The name of the service to retrieve. If not a registered
* @template T of object
* @param class-string<T> $name The name of the service to retrieve. If not a registered
* service, then a class of the given name is instantiated
* @param bool $asSingleton If set to false a new instance will be returned.
* If true a singleton will be returned unless the spec is type=prototype'
* @param array $constructorArgs Args to pass in to the constructor. Note: Ignored for singletons
* @return mixed Instance of the specified object
* @phpstan-return ($name is class-string<T> ? T : mixed) Instance of the specified object
*/
public function get($name, $asSingleton = true, $constructorArgs = [])
{
@ -1125,9 +1127,11 @@ class Injector implements ContainerInterface
*
* Additional parameters are passed through as
*
* @param string $name
* @template T of object
* @param class-string<T> $name
* @param mixed ...$argument arguments to pass to the constructor
* @return mixed A new instance of the specified object
* @phpstan-return ($name is class-string<T> ? T : mixed) A new instance of the specified object
*/
public function create($name, $argument = null)
{
@ -1139,9 +1143,11 @@ class Injector implements ContainerInterface
/**
* Creates an object with the supplied argument array
*
* @param string $name Name of the class to create an object of
* @template T
* @param class-string<T> $name Name of the class to create an object of
* @param array $constructorArgs Arguments to pass to the constructor
* @return mixed
* @phpstan-return ($name is class-string<T> ? T : mixed)
*/
public function createWithArgs($name, $constructorArgs)
{

View File

@ -15,8 +15,10 @@ use SilverStripe\Core\Manifest\ModuleManifest;
* way to access instance methods which don't rely on instance
* data (e.g. the custom SilverStripe static handling).
*
* @param string $className
* @template T of object
* @param class-string<T> $className
* @return mixed
* @phpstan-return ($className is class-string<T> ? T : mixed)
*/
function singleton($className)
{

View File

@ -0,0 +1,27 @@
<?php
namespace SilverStripe\Type\Tests;
use Generator;
use PHPStan\Testing\TypeInferenceTestCase;
use function glob;
class InjectorTypeTest extends TypeInferenceTestCase
{
public function typeFileAsserts(): Generator
{
$typeTests = glob(__DIR__ . '/data/injector-types.php') ?: [];
foreach ($typeTests as $typeTest) {
yield from $this->gatherAssertTypes($typeTest);
}
}
/**
* @dataProvider typeFileAsserts
*/
public function testFileAsserts(string $assertType, string $file, mixed ...$args): void
{
$this->assertFileAsserts($assertType, $file, ...$args);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace SilverStripe\Type\Tests\data;
use SilverStripe\Assets\File;
use SilverStripe\Core\Injector\Injector;
use function PHPStan\Testing\assertType;
assertType(
File::class,
Injector::inst()->get(File::class)
);
assertType(
File::class,
singleton(File::class)
);
assertType(
File::class,
Injector::inst()->create(File::class)
);
assertType(
File::class,
Injector::inst()->createWithArgs(File::class, ['Name' => 'Foo'])
);