v1.0 Initial commit of project
This commit is contained in:
46
vendor/symfony/property-info/Tests/Extractor/ConstructorExtractorTest.php
vendored
Normal file
46
vendor/symfony/property-info/Tests/Extractor/ConstructorExtractorTest.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyExtractor;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
|
||||
/**
|
||||
* @author Dmitrii Poddubnyi <dpoddubny@gmail.com>
|
||||
*/
|
||||
class ConstructorExtractorTest extends TestCase
|
||||
{
|
||||
private ConstructorExtractor $extractor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->extractor = new ConstructorExtractor([new DummyExtractor()]);
|
||||
}
|
||||
|
||||
public function testInstanceOf()
|
||||
{
|
||||
$this->assertInstanceOf(\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface::class, $this->extractor);
|
||||
}
|
||||
|
||||
public function testGetTypes()
|
||||
{
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_STRING)], $this->extractor->getTypes('Foo', 'bar', []));
|
||||
}
|
||||
|
||||
public function testGetTypesIfNoExtractors()
|
||||
{
|
||||
$extractor = new ConstructorExtractor([]);
|
||||
$this->assertNull($extractor->getTypes('Foo', 'bar', []));
|
||||
}
|
||||
}
|
||||
483
vendor/symfony/property-info/Tests/Extractor/PhpDocExtractorTest.php
vendored
Normal file
483
vendor/symfony/property-info/Tests/Extractor/PhpDocExtractorTest.php
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyCollection;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\PseudoTypeDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class PhpDocExtractorTest extends TestCase
|
||||
{
|
||||
private PhpDocExtractor $extractor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->extractor = new PhpDocExtractor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesProvider
|
||||
*/
|
||||
public function testExtract($property, ?array $type, $shortDescription, $longDescription)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
$this->assertSame($shortDescription, $this->extractor->getShortDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
$this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public function testParamTagTypeIsOmitted()
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType'));
|
||||
}
|
||||
|
||||
public static function invalidTypesProvider()
|
||||
{
|
||||
return [
|
||||
'pub' => ['pub', null, null],
|
||||
'stat' => ['stat', null, null],
|
||||
'bar' => ['bar', 'Bar.', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidTypesProvider
|
||||
*/
|
||||
public function testInvalid($property, $shortDescription, $longDescription)
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
|
||||
$this->assertSame($shortDescription, $this->extractor->getShortDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
|
||||
$this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testEmptyParamAnnotation()
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', 'foo'));
|
||||
$this->assertSame('Foo.', $this->extractor->getShortDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', 'foo'));
|
||||
$this->assertNull($this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', 'foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesWithNoPrefixesProvider
|
||||
*/
|
||||
public function testExtractTypesWithNoPrefixes($property, ?array $type = null)
|
||||
{
|
||||
$noPrefixExtractor = new PhpDocExtractor(null, [], [], []);
|
||||
|
||||
$this->assertEquals($type, $noPrefixExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public static function typesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null, 'Short description.', 'Long description.'],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)], 'This is bar', null],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)], 'Should be used.', null],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)], null, null],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)], null, null],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)], null, null],
|
||||
['foo5', null, null, null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')], null, null],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')], null, null],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))], null, null],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))], null, null],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, null, null)], null, null],
|
||||
['a', [new Type(Type::BUILTIN_TYPE_INT)], 'A.', null],
|
||||
['b', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')], 'B.', null],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_BOOL, true)], null, null],
|
||||
['ct', [new Type(Type::BUILTIN_TYPE_TRUE, true)], null, null],
|
||||
['cf', [new Type(Type::BUILTIN_TYPE_FALSE, true)], null, null],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_BOOL)], null, null],
|
||||
['dt', [new Type(Type::BUILTIN_TYPE_TRUE)], null, null],
|
||||
['df', [new Type(Type::BUILTIN_TYPE_FALSE)], null, null],
|
||||
['e', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))], null, null],
|
||||
['f', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))], null, null],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)], 'Nullable array.', null],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)], null, null],
|
||||
['i', [new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)], null, null],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')], null, null],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))], null, null],
|
||||
['donotexist', null, null, null],
|
||||
['staticGetter', null, null, null],
|
||||
['staticSetter', null, null, null],
|
||||
['emptyVar', null, 'This should not be removed.', null],
|
||||
['arrayWithKeys', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_STRING))], null, null],
|
||||
['arrayOfMixed', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), null)], null, null],
|
||||
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))], null, null],
|
||||
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null],
|
||||
['collectionAsObject', [new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyCollection::class, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING)])], null, null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideCollectionTypes
|
||||
*/
|
||||
public function testExtractCollection($property, ?array $type, $shortDescription, $longDescription)
|
||||
{
|
||||
$this->testExtract($property, $type, $shortDescription, $longDescription);
|
||||
}
|
||||
|
||||
public static function provideCollectionTypes()
|
||||
{
|
||||
return [
|
||||
['iteratorCollection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], new Type(Type::BUILTIN_TYPE_STRING))], null, null],
|
||||
['iteratorCollectionWithKey', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))], null, null],
|
||||
[
|
||||
'nestedIterators',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_OBJECT,
|
||||
false,
|
||||
'Iterator',
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_INT),
|
||||
new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))
|
||||
)],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
'arrayWithKeys',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_STRING),
|
||||
new Type(Type::BUILTIN_TYPE_STRING)
|
||||
)],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
'arrayWithKeysAndComplexValue',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_STRING),
|
||||
new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_INT),
|
||||
new Type(Type::BUILTIN_TYPE_STRING, true)
|
||||
)
|
||||
)],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesWithCustomPrefixesProvider
|
||||
*/
|
||||
public function testExtractTypesWithCustomPrefixes($property, ?array $type = null)
|
||||
{
|
||||
$customExtractor = new PhpDocExtractor(null, ['add', 'remove'], ['is', 'can']);
|
||||
|
||||
$this->assertEquals($type, $customExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public static function typesWithCustomPrefixesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null, 'Short description.', 'Long description.'],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)], 'This is bar', null],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)], 'Should be used.', null],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)], null, null],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)], null, null],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)], null, null],
|
||||
['foo5', null, null, null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')], null, null],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')], null, null],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))], null, null],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))], null, null],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, null, null)], null, null],
|
||||
['a', null, 'A.', null],
|
||||
['b', null, 'B.', null],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_BOOL, true)], null, null],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_BOOL)], null, null],
|
||||
['e', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))], null, null],
|
||||
['f', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))], null, null],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)], 'Nullable array.', null],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)], null, null],
|
||||
['i', [new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)], null, null],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')], null, null],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))], null, null],
|
||||
['nonNullableCollectionOfNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, true))], null, null],
|
||||
['nullableCollectionOfMultipleNonNullableElementTypes', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)])], null, null],
|
||||
['donotexist', null, null, null],
|
||||
['staticGetter', null, null, null],
|
||||
['staticSetter', null, null, null],
|
||||
];
|
||||
}
|
||||
|
||||
public static function typesWithNoPrefixesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null, 'Short description.', 'Long description.'],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)], 'This is bar', null],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)], 'Should be used.', null],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)], null, null],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)], null, null],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)], null, null],
|
||||
['foo5', null, null, null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
null,
|
||||
null,
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')], null, null],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')], null, null],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))], null, null],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))], null, null],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, null, null)], null, null],
|
||||
['a', null, 'A.', null],
|
||||
['b', null, 'B.', null],
|
||||
['c', null, null, null],
|
||||
['d', null, null, null],
|
||||
['e', null, null, null],
|
||||
['f', null, null, null],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)], 'Nullable array.', null],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)], null, null],
|
||||
['i', [new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)], null, null],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')], null, null],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))], null, null],
|
||||
['donotexist', null, null, null],
|
||||
['staticGetter', null, null, null],
|
||||
['staticSetter', null, null, null],
|
||||
];
|
||||
}
|
||||
|
||||
public function testReturnNullOnEmptyDocBlock()
|
||||
{
|
||||
$this->assertNull($this->extractor->getShortDescription(EmptyDocBlock::class, 'foo'));
|
||||
}
|
||||
|
||||
public static function dockBlockFallbackTypesProvider()
|
||||
{
|
||||
return [
|
||||
'pub' => [
|
||||
'pub', [new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
],
|
||||
'protAcc' => [
|
||||
'protAcc', [new Type(Type::BUILTIN_TYPE_INT)],
|
||||
],
|
||||
'protMut' => [
|
||||
'protMut', [new Type(Type::BUILTIN_TYPE_BOOL)],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dockBlockFallbackTypesProvider
|
||||
*/
|
||||
public function testDocBlockFallback($property, $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DockBlockFallback', $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesDefinedByTraitsProvider
|
||||
*/
|
||||
public function testPropertiesDefinedByTraits(string $property, Type $type)
|
||||
{
|
||||
$this->assertEquals([$type], $this->extractor->getTypes(DummyUsingTrait::class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesDefinedByTraitsProvider(): array
|
||||
{
|
||||
return [
|
||||
['propertyInTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
['propertyInTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
|
||||
['propertyInTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
['propertyInExternalTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
['propertyInExternalTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
['propertyInExternalTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider methodsDefinedByTraitsProvider
|
||||
*/
|
||||
public function testMethodsDefinedByTraits(string $property, Type $type)
|
||||
{
|
||||
$this->assertEquals([$type], $this->extractor->getTypes(DummyUsingTrait::class, $property));
|
||||
}
|
||||
|
||||
public static function methodsDefinedByTraitsProvider(): array
|
||||
{
|
||||
return [
|
||||
['methodInTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
['methodInTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
|
||||
['methodInTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
['methodInExternalTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
['methodInExternalTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
['methodInExternalTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesStaticTypeProvider
|
||||
*/
|
||||
public function testPropertiesStaticType(string $class, string $property, Type $type)
|
||||
{
|
||||
$this->assertEquals([$type], $this->extractor->getTypes($class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesStaticTypeProvider(): array
|
||||
{
|
||||
return [
|
||||
[ParentDummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)],
|
||||
[Dummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesParentTypeProvider
|
||||
*/
|
||||
public function testPropertiesParentType(string $class, string $property, ?array $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes($class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesParentTypeProvider(): array
|
||||
{
|
||||
return [
|
||||
[ParentDummy::class, 'parentAnnotationNoParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'parent')]],
|
||||
[Dummy::class, 'parentAnnotation', [new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
|
||||
];
|
||||
}
|
||||
|
||||
public function testUnknownPseudoType()
|
||||
{
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'scalar')], $this->extractor->getTypes(PseudoTypeDummy::class, 'unknownPseudoType'));
|
||||
}
|
||||
|
||||
public function testGenericInterface()
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider constructorTypesProvider
|
||||
*/
|
||||
public function testExtractConstructorTypes($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypesFromConstructor('Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummy', $property));
|
||||
}
|
||||
|
||||
public static function constructorTypesProvider()
|
||||
{
|
||||
return [
|
||||
['date', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['timezone', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeZone')]],
|
||||
['dateObject', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeInterface')]],
|
||||
['dateTime', null],
|
||||
['ddd', null],
|
||||
['mixed', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider pseudoTypesProvider
|
||||
*/
|
||||
public function testPseudoTypes($property, array $type)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\PseudoTypesDummy', $property));
|
||||
}
|
||||
|
||||
public static function pseudoTypesProvider(): array
|
||||
{
|
||||
return [
|
||||
['classString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['classStringGeneric', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['htmlEscapedString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['lowercaseString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['nonEmptyLowercaseString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['nonEmptyString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['numericString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['traitString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['positiveInt', [new Type(Type::BUILTIN_TYPE_INT, false, null)]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider promotedPropertyProvider
|
||||
*/
|
||||
public function testExtractPromotedProperty(string $property, ?array $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes(Php80Dummy::class, $property));
|
||||
}
|
||||
|
||||
public static function promotedPropertyProvider(): array
|
||||
{
|
||||
return [
|
||||
['promoted', null],
|
||||
['promotedAndMutated', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyDocBlock
|
||||
{
|
||||
public $foo;
|
||||
}
|
||||
|
||||
class OmittedParamTagTypeDocBlock
|
||||
{
|
||||
/**
|
||||
* The type is omitted here to ensure that the extractor doesn't choke on missing types.
|
||||
*
|
||||
* @param $omittedTagType
|
||||
*/
|
||||
public function setOmittedType(array $omittedTagType)
|
||||
{
|
||||
}
|
||||
}
|
||||
583
vendor/symfony/property-info/Tests/Extractor/PhpStanExtractorTest.php
vendored
Normal file
583
vendor/symfony/property-info/Tests/Extractor/PhpStanExtractorTest.php
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Clazz;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummyWithoutDocBlock;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultValue;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyCollection;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyGeneric;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\IFace;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80PromotedDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\RootDummy\RootDummyItem;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\AnotherNamespace\DummyInAnotherNamespace;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
|
||||
require_once __DIR__.'/../Fixtures/Extractor/DummyNamespace.php';
|
||||
|
||||
/**
|
||||
* @author Baptiste Leduc <baptiste.leduc@gmail.com>
|
||||
*/
|
||||
class PhpStanExtractorTest extends TestCase
|
||||
{
|
||||
private PhpStanExtractor $extractor;
|
||||
private PhpDocExtractor $phpDocExtractor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->extractor = new PhpStanExtractor();
|
||||
$this->phpDocExtractor = new PhpDocExtractor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesProvider
|
||||
*/
|
||||
public function testExtract($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public function testParamTagTypeIsOmitted()
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes(PhpStanOmittedParamTagTypeDocBlock::class, 'omittedType'));
|
||||
}
|
||||
|
||||
public static function invalidTypesProvider()
|
||||
{
|
||||
return [
|
||||
'pub' => ['pub'],
|
||||
'stat' => ['stat'],
|
||||
'foo' => ['foo'],
|
||||
'bar' => ['bar'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidTypesProvider
|
||||
*/
|
||||
public function testInvalid($property)
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesWithNoPrefixesProvider
|
||||
*/
|
||||
public function testExtractTypesWithNoPrefixes($property, ?array $type = null)
|
||||
{
|
||||
$noPrefixExtractor = new PhpStanExtractor([], [], []);
|
||||
|
||||
$this->assertEquals($type, $noPrefixExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public static function typesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)]],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)]],
|
||||
['foo5', null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))]],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], null)]],
|
||||
['a', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['b', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_BOOL, true)]],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_BOOL)]],
|
||||
['e', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))]],
|
||||
['f', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)]],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')]],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))]],
|
||||
['donotexist', null],
|
||||
['staticGetter', null],
|
||||
['staticSetter', null],
|
||||
['emptyVar', null],
|
||||
['arrayWithKeys', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
['arrayOfMixed', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), null)]],
|
||||
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)]],
|
||||
['rootDummyItems', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, RootDummyItem::class))]],
|
||||
['rootDummyItem', [new Type(Type::BUILTIN_TYPE_OBJECT, false, RootDummyItem::class)]],
|
||||
['collectionAsObject', [new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyCollection::class, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING)])]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideCollectionTypes
|
||||
*/
|
||||
public function testExtractCollection($property, ?array $type = null)
|
||||
{
|
||||
$this->testExtract($property, $type);
|
||||
}
|
||||
|
||||
public static function provideCollectionTypes()
|
||||
{
|
||||
return [
|
||||
['iteratorCollection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, null, new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
['iteratorCollectionWithKey', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
[
|
||||
'nestedIterators',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_OBJECT,
|
||||
false,
|
||||
'Iterator',
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_INT),
|
||||
new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))
|
||||
)],
|
||||
],
|
||||
[
|
||||
'arrayWithKeys',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_STRING),
|
||||
new Type(Type::BUILTIN_TYPE_STRING)
|
||||
)],
|
||||
],
|
||||
[
|
||||
'arrayWithKeysAndComplexValue',
|
||||
[new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_STRING),
|
||||
new Type(
|
||||
Type::BUILTIN_TYPE_ARRAY,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_INT),
|
||||
new Type(Type::BUILTIN_TYPE_STRING, true)
|
||||
)
|
||||
)],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesWithCustomPrefixesProvider
|
||||
*/
|
||||
public function testExtractTypesWithCustomPrefixes($property, ?array $type = null)
|
||||
{
|
||||
$customExtractor = new PhpStanExtractor(['add', 'remove'], ['is', 'can']);
|
||||
|
||||
$this->assertEquals($type, $customExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property));
|
||||
}
|
||||
|
||||
public static function typesWithCustomPrefixesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)]],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)]],
|
||||
['foo5', null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))]],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], null)]],
|
||||
['a', null],
|
||||
['b', null],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_BOOL, true)]],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_BOOL)]],
|
||||
['e', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))]],
|
||||
['f', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)]],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')]],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))]],
|
||||
['donotexist', null],
|
||||
['staticGetter', null],
|
||||
['staticSetter', null],
|
||||
];
|
||||
}
|
||||
|
||||
public static function typesWithNoPrefixesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', null],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['foo2', [new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
['foo3', [new Type(Type::BUILTIN_TYPE_CALLABLE)]],
|
||||
['foo4', [new Type(Type::BUILTIN_TYPE_NULL)]],
|
||||
['foo5', null],
|
||||
[
|
||||
'files',
|
||||
[
|
||||
new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')),
|
||||
new Type(Type::BUILTIN_TYPE_RESOURCE),
|
||||
],
|
||||
],
|
||||
['bal', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]],
|
||||
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['nestedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING, false)))]],
|
||||
['mixedCollection', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], null)]],
|
||||
['a', null],
|
||||
['b', null],
|
||||
['c', null],
|
||||
['d', null],
|
||||
['e', null],
|
||||
['f', null],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
|
||||
['h', [new Type(Type::BUILTIN_TYPE_STRING, true)]],
|
||||
['j', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTimeImmutable')]],
|
||||
['nullableCollectionOfNonNullableElements', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT, false))]],
|
||||
['donotexist', null],
|
||||
['staticGetter', null],
|
||||
['staticSetter', null],
|
||||
];
|
||||
}
|
||||
|
||||
public static function dockBlockFallbackTypesProvider()
|
||||
{
|
||||
return [
|
||||
'pub' => [
|
||||
'pub', [new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
],
|
||||
'protAcc' => [
|
||||
'protAcc', [new Type(Type::BUILTIN_TYPE_INT)],
|
||||
],
|
||||
'protMut' => [
|
||||
'protMut', [new Type(Type::BUILTIN_TYPE_BOOL)],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dockBlockFallbackTypesProvider
|
||||
*/
|
||||
public function testDocBlockFallback($property, $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DockBlockFallback', $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesDefinedByTraitsProvider
|
||||
*/
|
||||
public function testPropertiesDefinedByTraits(string $property, Type $type)
|
||||
{
|
||||
$this->assertEquals([$type], $this->extractor->getTypes(DummyUsingTrait::class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesDefinedByTraitsProvider(): array
|
||||
{
|
||||
return [
|
||||
['propertyInTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
|
||||
['propertyInTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
|
||||
['propertyInTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
['dummyInAnotherNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyInAnotherNamespace::class)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesStaticTypeProvider
|
||||
*/
|
||||
public function testPropertiesStaticType(string $class, string $property, Type $type)
|
||||
{
|
||||
$this->assertEquals([$type], $this->extractor->getTypes($class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesStaticTypeProvider(): array
|
||||
{
|
||||
return [
|
||||
[ParentDummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)],
|
||||
[Dummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider propertiesParentTypeProvider
|
||||
*/
|
||||
public function testPropertiesParentType(string $class, string $property, ?array $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes($class, $property));
|
||||
}
|
||||
|
||||
public static function propertiesParentTypeProvider(): array
|
||||
{
|
||||
return [
|
||||
[ParentDummy::class, 'parentAnnotationNoParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'parent')]],
|
||||
[Dummy::class, 'parentAnnotation', [new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider constructorTypesProvider
|
||||
*/
|
||||
public function testExtractConstructorTypes($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypesFromConstructor('Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummy', $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider constructorTypesProvider
|
||||
*/
|
||||
public function testExtractConstructorTypesReturnNullOnEmptyDocBlock($property)
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypesFromConstructor(ConstructorDummyWithoutDocBlock::class, $property));
|
||||
}
|
||||
|
||||
public static function constructorTypesProvider()
|
||||
{
|
||||
return [
|
||||
['date', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['timezone', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeZone')]],
|
||||
['dateObject', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeInterface')]],
|
||||
['dateTime', null],
|
||||
['ddd', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider unionTypesProvider
|
||||
*/
|
||||
public function testExtractorUnionTypes(string $property, ?array $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DummyUnionType', $property));
|
||||
}
|
||||
|
||||
public static function unionTypesProvider(): array
|
||||
{
|
||||
return [
|
||||
['a', [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['b', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])])]],
|
||||
['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, false, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_OBJECT, false, \Traversable::class, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
|
||||
['f', null],
|
||||
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider pseudoTypesProvider
|
||||
*/
|
||||
public function testPseudoTypes($property, array $type)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\PhpStanPseudoTypesDummy', $property));
|
||||
}
|
||||
|
||||
public static function pseudoTypesProvider(): array
|
||||
{
|
||||
return [
|
||||
['classString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['classStringGeneric', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['htmlEscapedString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['lowercaseString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['nonEmptyLowercaseString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['nonEmptyString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['numericString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['traitString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['interfaceString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['literalString', [new Type(Type::BUILTIN_TYPE_STRING, false, null)]],
|
||||
['positiveInt', [new Type(Type::BUILTIN_TYPE_INT, false, null)]],
|
||||
['negativeInt', [new Type(Type::BUILTIN_TYPE_INT, false, null)]],
|
||||
['nonEmptyArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
|
||||
['nonEmptyList', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))]],
|
||||
['scalar', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_BOOL)]],
|
||||
['number', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
['numeric', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
['arrayKey', [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['double', [new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
];
|
||||
}
|
||||
|
||||
public function testDummyNamespace()
|
||||
{
|
||||
$this->assertEquals(
|
||||
[new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')],
|
||||
$this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DummyNamespace', 'dummy')
|
||||
);
|
||||
}
|
||||
|
||||
public function testDummyNamespaceWithProperty()
|
||||
{
|
||||
$phpStanTypes = $this->extractor->getTypes(\B\Dummy::class, 'property');
|
||||
$phpDocTypes = $this->phpDocExtractor->getTypes(\B\Dummy::class, 'property');
|
||||
|
||||
$this->assertEquals('A\Property', $phpStanTypes[0]->getClassName());
|
||||
$this->assertEquals($phpDocTypes[0]->getClassName(), $phpStanTypes[0]->getClassName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider intRangeTypeProvider
|
||||
*/
|
||||
public function testExtractorIntRangeType(string $property, ?array $types)
|
||||
{
|
||||
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\IntRangeDummy', $property));
|
||||
}
|
||||
|
||||
public static function intRangeTypeProvider(): array
|
||||
{
|
||||
return [
|
||||
['a', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
['b', [new Type(Type::BUILTIN_TYPE_INT, true)]],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php80TypesProvider
|
||||
*/
|
||||
public function testExtractPhp80Type(string $class, $property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes($class, $property, []));
|
||||
}
|
||||
|
||||
public static function php80TypesProvider()
|
||||
{
|
||||
return [
|
||||
[Php80Dummy::class, 'promotedWithDocCommentAndType', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
[Php80Dummy::class, 'promotedWithDocComment', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
[Php80Dummy::class, 'promotedAndMutated', [new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
[Php80Dummy::class, 'promoted', null],
|
||||
[Php80Dummy::class, 'collection', [new Type(Type::BUILTIN_TYPE_ARRAY, collection: true, collectionValueType: new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
[Php80PromotedDummy::class, 'promoted', null],
|
||||
];
|
||||
}
|
||||
|
||||
public function testGenericInterface()
|
||||
{
|
||||
$this->assertEquals(
|
||||
[
|
||||
new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: \BackedEnum::class,
|
||||
collectionValueType: new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_STRING,
|
||||
)
|
||||
),
|
||||
],
|
||||
$this->extractor->getTypes(Dummy::class, 'genericInterface')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<Type> $expectedTypes
|
||||
* @dataProvider genericsProvider
|
||||
*/
|
||||
public function testGenericsLegacy(string $property, array $expectedTypes)
|
||||
{
|
||||
$this->assertEquals($expectedTypes, $this->extractor->getTypes(DummyGeneric::class, $property));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array{0: string, 1: list<Type>}>
|
||||
*/
|
||||
public static function genericsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
'basicClass',
|
||||
[
|
||||
new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Clazz::class,
|
||||
collectionValueType: new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Dummy::class,
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
yield [
|
||||
'nullableClass',
|
||||
[
|
||||
new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Clazz::class,
|
||||
nullable: true,
|
||||
collectionValueType: new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Dummy::class,
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
yield [
|
||||
'basicInterface',
|
||||
[
|
||||
new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: IFace::class,
|
||||
collectionValueType: new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Dummy::class,
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
yield [
|
||||
'nullableInterface',
|
||||
[
|
||||
new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: IFace::class,
|
||||
nullable: true,
|
||||
collectionValueType: new Type(
|
||||
builtinType: Type::BUILTIN_TYPE_OBJECT,
|
||||
class: Dummy::class,
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class PhpStanOmittedParamTagTypeDocBlock
|
||||
{
|
||||
/**
|
||||
* The type is omitted here to ensure that the extractor doesn't choke on missing types.
|
||||
*
|
||||
* @param $omittedTagType
|
||||
*/
|
||||
public function setOmittedType(array $omittedTagType)
|
||||
{
|
||||
}
|
||||
}
|
||||
793
vendor/symfony/property-info/Tests/Extractor/ReflectionExtractorTest.php
vendored
Normal file
793
vendor/symfony/property-info/Tests/Extractor/ReflectionExtractorTest.php
vendored
Normal file
@@ -0,0 +1,793 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
|
||||
use Symfony\Component\PropertyInfo\PropertyReadInfo;
|
||||
use Symfony\Component\PropertyInfo\PropertyWriteInfo;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\AsymmetricVisibility;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultValue;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\NotInstantiable;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended2;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\SnakeCaseDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\VirtualProperties;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ReflectionExtractorTest extends TestCase
|
||||
{
|
||||
private ReflectionExtractor $extractor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->extractor = new ReflectionExtractor();
|
||||
}
|
||||
|
||||
public function testGetProperties()
|
||||
{
|
||||
$this->assertSame(
|
||||
[
|
||||
'bal',
|
||||
'parent',
|
||||
'collection',
|
||||
'collectionAsObject',
|
||||
'nestedCollection',
|
||||
'mixedCollection',
|
||||
'B',
|
||||
'Guid',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'nullableCollectionOfNonNullableElements',
|
||||
'nonNullableCollectionOfNullableElements',
|
||||
'nullableCollectionOfMultipleNonNullableElementTypes',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'arrayWithKeys',
|
||||
'arrayWithKeysAndComplexValue',
|
||||
'arrayOfMixed',
|
||||
'listOfStrings',
|
||||
'parentAnnotation',
|
||||
'genericInterface',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
'foo4',
|
||||
'foo5',
|
||||
'files',
|
||||
'propertyTypeStatic',
|
||||
'parentAnnotationNoParent',
|
||||
'rootDummyItems',
|
||||
'rootDummyItem',
|
||||
'a',
|
||||
'DOB',
|
||||
'Id',
|
||||
'123',
|
||||
'self',
|
||||
'realParent',
|
||||
'xTotals',
|
||||
'YT',
|
||||
'date',
|
||||
'element',
|
||||
'c',
|
||||
'ct',
|
||||
'cf',
|
||||
'd',
|
||||
'dt',
|
||||
'df',
|
||||
'e',
|
||||
'f',
|
||||
],
|
||||
$this->extractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')
|
||||
);
|
||||
|
||||
$this->assertNull($this->extractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\NoProperties'));
|
||||
}
|
||||
|
||||
public function testGetPropertiesWithCustomPrefixes()
|
||||
{
|
||||
$customExtractor = new ReflectionExtractor(['add', 'remove'], ['is', 'can']);
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'bal',
|
||||
'parent',
|
||||
'collection',
|
||||
'collectionAsObject',
|
||||
'nestedCollection',
|
||||
'mixedCollection',
|
||||
'B',
|
||||
'Guid',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'nullableCollectionOfNonNullableElements',
|
||||
'nonNullableCollectionOfNullableElements',
|
||||
'nullableCollectionOfMultipleNonNullableElementTypes',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'arrayWithKeys',
|
||||
'arrayWithKeysAndComplexValue',
|
||||
'arrayOfMixed',
|
||||
'listOfStrings',
|
||||
'parentAnnotation',
|
||||
'genericInterface',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
'foo4',
|
||||
'foo5',
|
||||
'files',
|
||||
'propertyTypeStatic',
|
||||
'parentAnnotationNoParent',
|
||||
'rootDummyItems',
|
||||
'rootDummyItem',
|
||||
'date',
|
||||
'c',
|
||||
'ct',
|
||||
'cf',
|
||||
'd',
|
||||
'dt',
|
||||
'df',
|
||||
'e',
|
||||
'f',
|
||||
],
|
||||
$customExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetPropertiesWithNoPrefixes()
|
||||
{
|
||||
$noPrefixExtractor = new ReflectionExtractor([], [], []);
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'bal',
|
||||
'parent',
|
||||
'collection',
|
||||
'collectionAsObject',
|
||||
'nestedCollection',
|
||||
'mixedCollection',
|
||||
'B',
|
||||
'Guid',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'nullableCollectionOfNonNullableElements',
|
||||
'nonNullableCollectionOfNullableElements',
|
||||
'nullableCollectionOfMultipleNonNullableElementTypes',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'arrayWithKeys',
|
||||
'arrayWithKeysAndComplexValue',
|
||||
'arrayOfMixed',
|
||||
'listOfStrings',
|
||||
'parentAnnotation',
|
||||
'genericInterface',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
'foo4',
|
||||
'foo5',
|
||||
'files',
|
||||
'propertyTypeStatic',
|
||||
'parentAnnotationNoParent',
|
||||
'rootDummyItems',
|
||||
'rootDummyItem',
|
||||
],
|
||||
$noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesProvider
|
||||
*/
|
||||
public function testExtractors($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property, []));
|
||||
}
|
||||
|
||||
public static function typesProvider()
|
||||
{
|
||||
return [
|
||||
['a', null],
|
||||
['b', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['c', [new Type(Type::BUILTIN_TYPE_BOOL)]],
|
||||
['d', [new Type(Type::BUILTIN_TYPE_BOOL)]],
|
||||
['e', null],
|
||||
['f', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))]],
|
||||
['donotexist', null],
|
||||
['staticGetter', null],
|
||||
['staticSetter', null],
|
||||
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')]],
|
||||
['realParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
|
||||
['date', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTimeImmutable::class)]],
|
||||
['dates', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTimeImmutable::class))]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php7TypesProvider
|
||||
*/
|
||||
public function testExtractPhp7Type(string $class, string $property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes($class, $property, []));
|
||||
}
|
||||
|
||||
public static function php7TypesProvider()
|
||||
{
|
||||
return [
|
||||
[Php7Dummy::class, 'foo', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
|
||||
[Php7Dummy::class, 'bar', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||
[Php7Dummy::class, 'baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
[Php7Dummy::class, 'buz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy')]],
|
||||
[Php7Dummy::class, 'biz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Php7ParentDummy::class)]],
|
||||
[Php7Dummy::class, 'donotexist', null],
|
||||
[Php7ParentDummy::class, 'parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \stdClass::class)]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php71TypesProvider
|
||||
*/
|
||||
public function testExtractPhp71Type($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy', $property, []));
|
||||
}
|
||||
|
||||
public static function php71TypesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
|
||||
['buz', [new Type(Type::BUILTIN_TYPE_NULL)]],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_INT, true)]],
|
||||
['baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||
['donotexist', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php80TypesProvider
|
||||
*/
|
||||
public function testExtractPhp80Type($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy', $property, []));
|
||||
}
|
||||
|
||||
public static function php80TypesProvider()
|
||||
{
|
||||
return [
|
||||
['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
|
||||
['bar', [new Type(Type::BUILTIN_TYPE_INT, true)]],
|
||||
['timeout', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)]],
|
||||
['optional', [new Type(Type::BUILTIN_TYPE_INT, true), new Type(Type::BUILTIN_TYPE_FLOAT, true)]],
|
||||
['string', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Stringable'), new Type(Type::BUILTIN_TYPE_STRING)]],
|
||||
['payload', null],
|
||||
['data', null],
|
||||
['mixedProperty', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php81TypesProvider
|
||||
*/
|
||||
public function testExtractPhp81Type($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy', $property, []));
|
||||
}
|
||||
|
||||
public static function php81TypesProvider()
|
||||
{
|
||||
return [
|
||||
['nothing', null],
|
||||
['collection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Traversable'), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Countable')]],
|
||||
];
|
||||
}
|
||||
|
||||
public function testReadonlyPropertiesAreNotWriteable()
|
||||
{
|
||||
$this->assertFalse($this->extractor->isWritable(Php81Dummy::class, 'foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider php82TypesProvider
|
||||
*
|
||||
* @requires PHP 8.2
|
||||
*/
|
||||
public function testExtractPhp82Type($property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php82Dummy', $property, []));
|
||||
}
|
||||
|
||||
public static function php82TypesProvider(): iterable
|
||||
{
|
||||
yield ['nil', null];
|
||||
yield ['false', [new Type(Type::BUILTIN_TYPE_FALSE)]];
|
||||
yield ['true', [new Type(Type::BUILTIN_TYPE_TRUE)]];
|
||||
|
||||
// Nesting intersection and union types is not supported yet,
|
||||
// but we should make sure this kind of composite types does not crash the extractor.
|
||||
yield ['someCollection', null];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultValueProvider
|
||||
*/
|
||||
public function testExtractWithDefaultValue($property, $type)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypes(DefaultValue::class, $property, []));
|
||||
}
|
||||
|
||||
public static function defaultValueProvider()
|
||||
{
|
||||
return [
|
||||
['defaultInt', [new Type(Type::BUILTIN_TYPE_INT, false)]],
|
||||
['defaultFloat', [new Type(Type::BUILTIN_TYPE_FLOAT, false)]],
|
||||
['defaultString', [new Type(Type::BUILTIN_TYPE_STRING, false)]],
|
||||
['defaultArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
|
||||
['defaultNull', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getReadableProperties
|
||||
*/
|
||||
public function testIsReadable($property, $expected)
|
||||
{
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property, [])
|
||||
);
|
||||
}
|
||||
|
||||
public static function getReadableProperties()
|
||||
{
|
||||
return [
|
||||
['bar', false],
|
||||
['baz', false],
|
||||
['parent', true],
|
||||
['a', true],
|
||||
['b', false],
|
||||
['c', true],
|
||||
['d', true],
|
||||
['e', false],
|
||||
['f', false],
|
||||
['Id', true],
|
||||
['id', true],
|
||||
['Guid', true],
|
||||
['guid', false],
|
||||
['element', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getWritableProperties
|
||||
*/
|
||||
public function testIsWritable($property, $expected)
|
||||
{
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->extractor->isWritable(Dummy::class, $property, [])
|
||||
);
|
||||
}
|
||||
|
||||
public static function getWritableProperties()
|
||||
{
|
||||
return [
|
||||
['bar', false],
|
||||
['baz', false],
|
||||
['parent', true],
|
||||
['a', false],
|
||||
['b', true],
|
||||
['c', false],
|
||||
['d', false],
|
||||
['e', true],
|
||||
['f', true],
|
||||
['Id', false],
|
||||
['Guid', true],
|
||||
['guid', false],
|
||||
];
|
||||
}
|
||||
|
||||
public function testIsReadableSnakeCase()
|
||||
{
|
||||
$this->assertTrue($this->extractor->isReadable(SnakeCaseDummy::class, 'snake_property'));
|
||||
$this->assertTrue($this->extractor->isReadable(SnakeCaseDummy::class, 'snake_readonly'));
|
||||
}
|
||||
|
||||
public function testIsWriteableSnakeCase()
|
||||
{
|
||||
$this->assertTrue($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_property'));
|
||||
$this->assertFalse($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_readonly'));
|
||||
// Ensure that it's still possible to write to the property using the (old) snake name
|
||||
$this->assertTrue($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_method'));
|
||||
}
|
||||
|
||||
public function testSingularize()
|
||||
{
|
||||
$this->assertTrue($this->extractor->isWritable(AdderRemoverDummy::class, 'analyses'));
|
||||
$this->assertTrue($this->extractor->isWritable(AdderRemoverDummy::class, 'feet'));
|
||||
$this->assertEquals(['analyses', 'feet'], $this->extractor->getProperties(AdderRemoverDummy::class));
|
||||
}
|
||||
|
||||
public function testPrivatePropertyExtractor()
|
||||
{
|
||||
$privateExtractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PRIVATE | ReflectionExtractor::ALLOW_PROTECTED);
|
||||
$properties = $privateExtractor->getProperties(Dummy::class);
|
||||
|
||||
$this->assertContains('bar', $properties);
|
||||
$this->assertContains('baz', $properties);
|
||||
|
||||
$this->assertTrue($privateExtractor->isReadable(Dummy::class, 'bar'));
|
||||
$this->assertTrue($privateExtractor->isReadable(Dummy::class, 'baz'));
|
||||
|
||||
$protectedExtractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED);
|
||||
$properties = $protectedExtractor->getProperties(Dummy::class);
|
||||
|
||||
$this->assertNotContains('bar', $properties);
|
||||
$this->assertContains('baz', $properties);
|
||||
|
||||
$this->assertFalse($protectedExtractor->isReadable(Dummy::class, 'bar'));
|
||||
$this->assertTrue($protectedExtractor->isReadable(Dummy::class, 'baz'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getInitializableProperties
|
||||
*/
|
||||
public function testIsInitializable(string $class, string $property, bool $expected)
|
||||
{
|
||||
$this->assertSame($expected, $this->extractor->isInitializable($class, $property));
|
||||
}
|
||||
|
||||
public static function getInitializableProperties(): array
|
||||
{
|
||||
return [
|
||||
[Php71Dummy::class, 'string', true],
|
||||
[Php71Dummy::class, 'intPrivate', true],
|
||||
[Php71Dummy::class, 'notExist', false],
|
||||
[Php71DummyExtended2::class, 'intWithAccessor', true],
|
||||
[Php71DummyExtended2::class, 'intPrivate', false],
|
||||
[NotInstantiable::class, 'foo', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider constructorTypesProvider
|
||||
*/
|
||||
public function testExtractTypeConstructor(string $class, string $property, ?array $type = null)
|
||||
{
|
||||
/* Check that constructor extractions works by default, and if passed in via context.
|
||||
Check that null is returned if constructor extraction is disabled */
|
||||
$this->assertEquals($type, $this->extractor->getTypes($class, $property, []));
|
||||
$this->assertEquals($type, $this->extractor->getTypes($class, $property, ['enable_constructor_extraction' => true]));
|
||||
$this->assertNull($this->extractor->getTypes($class, $property, ['enable_constructor_extraction' => false]));
|
||||
}
|
||||
|
||||
public static function constructorTypesProvider(): array
|
||||
{
|
||||
return [
|
||||
// php71 dummy has following constructor: __construct(string $string, int $intPrivate)
|
||||
[Php71Dummy::class, 'string', [new Type(Type::BUILTIN_TYPE_STRING, false)]],
|
||||
[Php71Dummy::class, 'intPrivate', [new Type(Type::BUILTIN_TYPE_INT, false)]],
|
||||
// Php71DummyExtended2 adds int $intWithAccessor
|
||||
[Php71DummyExtended2::class, 'intWithAccessor', [new Type(Type::BUILTIN_TYPE_INT, false)]],
|
||||
[Php71DummyExtended2::class, 'intPrivate', [new Type(Type::BUILTIN_TYPE_INT, false)]],
|
||||
[DefaultValue::class, 'foo', null],
|
||||
];
|
||||
}
|
||||
|
||||
public function testNullOnPrivateProtectedAccessor()
|
||||
{
|
||||
$barAcessor = $this->extractor->getReadInfo(Dummy::class, 'bar');
|
||||
$barMutator = $this->extractor->getWriteInfo(Dummy::class, 'bar');
|
||||
$bazAcessor = $this->extractor->getReadInfo(Dummy::class, 'baz');
|
||||
$bazMutator = $this->extractor->getWriteInfo(Dummy::class, 'baz');
|
||||
|
||||
$this->assertNull($barAcessor);
|
||||
$this->assertEquals(PropertyWriteInfo::TYPE_NONE, $barMutator->getType());
|
||||
$this->assertNull($bazAcessor);
|
||||
$this->assertEquals(PropertyWriteInfo::TYPE_NONE, $bazMutator->getType());
|
||||
}
|
||||
|
||||
public function testTypedProperties()
|
||||
{
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], $this->extractor->getTypes(Php74Dummy::class, 'dummy'));
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_BOOL, true)], $this->extractor->getTypes(Php74Dummy::class, 'nullableBoolProp'));
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))], $this->extractor->getTypes(Php74Dummy::class, 'stringCollection'));
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_INT, true)], $this->extractor->getTypes(Php74Dummy::class, 'nullableWithDefault'));
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)], $this->extractor->getTypes(Php74Dummy::class, 'collection'));
|
||||
$this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class))], $this->extractor->getTypes(Php74Dummy::class, 'nullableTypedCollection'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider readAccessorProvider
|
||||
*/
|
||||
public function testGetReadAccessor($class, $property, $found, $type, $name, $visibility, $static)
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
|
||||
$readAcessor = $extractor->getReadInfo($class, $property);
|
||||
|
||||
if (!$found) {
|
||||
$this->assertNull($readAcessor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assertNotNull($readAcessor);
|
||||
$this->assertSame($type, $readAcessor->getType());
|
||||
$this->assertSame($name, $readAcessor->getName());
|
||||
$this->assertSame($visibility, $readAcessor->getVisibility());
|
||||
$this->assertSame($static, $readAcessor->isStatic());
|
||||
}
|
||||
|
||||
public static function readAccessorProvider(): array
|
||||
{
|
||||
return [
|
||||
[Dummy::class, 'bar', true, PropertyReadInfo::TYPE_PROPERTY, 'bar', PropertyReadInfo::VISIBILITY_PRIVATE, false],
|
||||
[Dummy::class, 'baz', true, PropertyReadInfo::TYPE_PROPERTY, 'baz', PropertyReadInfo::VISIBILITY_PROTECTED, false],
|
||||
[Dummy::class, 'bal', true, PropertyReadInfo::TYPE_PROPERTY, 'bal', PropertyReadInfo::VISIBILITY_PUBLIC, false],
|
||||
[Dummy::class, 'parent', true, PropertyReadInfo::TYPE_PROPERTY, 'parent', PropertyReadInfo::VISIBILITY_PUBLIC, false],
|
||||
[Dummy::class, 'static', true, PropertyReadInfo::TYPE_METHOD, 'getStatic', PropertyReadInfo::VISIBILITY_PUBLIC, true],
|
||||
[Dummy::class, 'foo', true, PropertyReadInfo::TYPE_PROPERTY, 'foo', PropertyReadInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'foo', true, PropertyReadInfo::TYPE_METHOD, 'getFoo', PropertyReadInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'buz', true, PropertyReadInfo::TYPE_METHOD, 'getBuz', PropertyReadInfo::VISIBILITY_PUBLIC, false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider writeMutatorProvider
|
||||
*/
|
||||
public function testGetWriteMutator($class, $property, $allowConstruct, $found, $type, $name, $addName, $removeName, $visibility, $static)
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
|
||||
$writeMutator = $extractor->getWriteInfo($class, $property, [
|
||||
'enable_constructor_extraction' => $allowConstruct,
|
||||
'enable_getter_setter_extraction' => true,
|
||||
]);
|
||||
|
||||
if (!$found) {
|
||||
$this->assertEquals(PropertyWriteInfo::TYPE_NONE, $writeMutator->getType());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assertNotNull($writeMutator);
|
||||
$this->assertSame($type, $writeMutator->getType());
|
||||
|
||||
if (PropertyWriteInfo::TYPE_ADDER_AND_REMOVER === $writeMutator->getType()) {
|
||||
$this->assertNotNull($writeMutator->getAdderInfo());
|
||||
$this->assertSame($addName, $writeMutator->getAdderInfo()->getName());
|
||||
$this->assertNotNull($writeMutator->getRemoverInfo());
|
||||
$this->assertSame($removeName, $writeMutator->getRemoverInfo()->getName());
|
||||
}
|
||||
|
||||
if (PropertyWriteInfo::TYPE_CONSTRUCTOR === $writeMutator->getType()) {
|
||||
$this->assertSame($name, $writeMutator->getName());
|
||||
}
|
||||
|
||||
if (PropertyWriteInfo::TYPE_PROPERTY === $writeMutator->getType()) {
|
||||
$this->assertSame($name, $writeMutator->getName());
|
||||
$this->assertSame($visibility, $writeMutator->getVisibility());
|
||||
$this->assertSame($static, $writeMutator->isStatic());
|
||||
}
|
||||
|
||||
if (PropertyWriteInfo::TYPE_METHOD === $writeMutator->getType()) {
|
||||
$this->assertSame($name, $writeMutator->getName());
|
||||
$this->assertSame($visibility, $writeMutator->getVisibility());
|
||||
$this->assertSame($static, $writeMutator->isStatic());
|
||||
}
|
||||
}
|
||||
|
||||
public static function writeMutatorProvider(): array
|
||||
{
|
||||
return [
|
||||
[Dummy::class, 'bar', false, true, PropertyWriteInfo::TYPE_PROPERTY, 'bar', null, null, PropertyWriteInfo::VISIBILITY_PRIVATE, false],
|
||||
[Dummy::class, 'baz', false, true, PropertyWriteInfo::TYPE_PROPERTY, 'baz', null, null, PropertyWriteInfo::VISIBILITY_PROTECTED, false],
|
||||
[Dummy::class, 'bal', false, true, PropertyWriteInfo::TYPE_PROPERTY, 'bal', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Dummy::class, 'parent', false, true, PropertyWriteInfo::TYPE_PROPERTY, 'parent', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Dummy::class, 'staticSetter', false, true, PropertyWriteInfo::TYPE_METHOD, 'staticSetter', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, true],
|
||||
[Dummy::class, 'foo', false, true, PropertyWriteInfo::TYPE_PROPERTY, 'foo', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'bar', false, true, PropertyWriteInfo::TYPE_METHOD, 'setBar', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'string', false, false, '', '', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'string', true, true, PropertyWriteInfo::TYPE_CONSTRUCTOR, 'string', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71Dummy::class, 'baz', false, true, PropertyWriteInfo::TYPE_ADDER_AND_REMOVER, null, 'addBaz', 'removeBaz', PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended::class, 'bar', false, true, PropertyWriteInfo::TYPE_METHOD, 'setBar', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended::class, 'string', false, false, -1, '', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended::class, 'string', true, true, PropertyWriteInfo::TYPE_CONSTRUCTOR, 'string', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended::class, 'baz', false, true, PropertyWriteInfo::TYPE_ADDER_AND_REMOVER, null, 'addBaz', 'removeBaz', PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended2::class, 'bar', false, true, PropertyWriteInfo::TYPE_METHOD, 'setBar', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended2::class, 'string', false, false, '', '', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended2::class, 'string', true, false, '', '', null, null, PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
[Php71DummyExtended2::class, 'baz', false, true, PropertyWriteInfo::TYPE_ADDER_AND_REMOVER, null, 'addBaz', 'removeBaz', PropertyWriteInfo::VISIBILITY_PUBLIC, false],
|
||||
];
|
||||
}
|
||||
|
||||
public function testDisabledAdderAndRemoverReturnsError()
|
||||
{
|
||||
$writeMutator = $this->extractor->getWriteInfo(Php71Dummy::class, 'baz', [
|
||||
'enable_adder_remover_extraction' => false,
|
||||
]);
|
||||
|
||||
self::assertNotNull($writeMutator);
|
||||
self::assertSame(PropertyWriteInfo::TYPE_NONE, $writeMutator->getType());
|
||||
self::assertSame([\sprintf('The property "baz" in class "%s" can be defined with the methods "addBaz()", "removeBaz()" but the new value must be an array or an instance of \Traversable', Php71Dummy::class)], $writeMutator->getErrors());
|
||||
}
|
||||
|
||||
public function testGetWriteInfoReadonlyProperties()
|
||||
{
|
||||
$writeMutatorConstructor = $this->extractor->getWriteInfo(Php81Dummy::class, 'foo', ['enable_constructor_extraction' => true]);
|
||||
$writeMutatorWithoutConstructor = $this->extractor->getWriteInfo(Php81Dummy::class, 'foo', ['enable_constructor_extraction' => false]);
|
||||
|
||||
$this->assertSame(PropertyWriteInfo::TYPE_CONSTRUCTOR, $writeMutatorConstructor->getType());
|
||||
$this->assertSame(PropertyWriteInfo::TYPE_NONE, $writeMutatorWithoutConstructor->getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider extractConstructorTypesProvider
|
||||
*/
|
||||
public function testExtractConstructorTypes(string $property, ?array $type = null)
|
||||
{
|
||||
$this->assertEquals($type, $this->extractor->getTypesFromConstructor('Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummy', $property));
|
||||
}
|
||||
|
||||
public static function extractConstructorTypesProvider(): array
|
||||
{
|
||||
return [
|
||||
['timezone', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeZone')]],
|
||||
['date', null],
|
||||
['dateObject', null],
|
||||
['dateTime', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]],
|
||||
['ddd', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testAsymmetricVisibility()
|
||||
{
|
||||
$this->assertTrue($this->extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertTrue($this->extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($this->extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testAsymmetricVisibilityAllowPublicOnly()
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC);
|
||||
|
||||
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testAsymmetricVisibilityAllowProtectedOnly()
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PROTECTED);
|
||||
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testAsymmetricVisibilityAllowPrivateOnly()
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PRIVATE);
|
||||
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate'));
|
||||
$this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
|
||||
$this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testVirtualProperties()
|
||||
{
|
||||
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualNoSetHook'));
|
||||
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualSetHookOnly'));
|
||||
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualHook'));
|
||||
$this->assertFalse($this->extractor->isWritable(VirtualProperties::class, 'virtualNoSetHook'));
|
||||
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualSetHookOnly'));
|
||||
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualHook'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideAsymmetricVisibilityMutator
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testAsymmetricVisibilityMutator(string $property, string $readVisibility, string $writeVisibility)
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
|
||||
$readMutator = $extractor->getReadInfo(AsymmetricVisibility::class, $property);
|
||||
$writeMutator = $extractor->getWriteInfo(AsymmetricVisibility::class, $property, [
|
||||
'enable_getter_setter_extraction' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
|
||||
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
|
||||
$this->assertSame($readVisibility, $readMutator->getVisibility());
|
||||
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
|
||||
}
|
||||
|
||||
public static function provideAsymmetricVisibilityMutator(): iterable
|
||||
{
|
||||
yield ['publicPrivate', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
|
||||
yield ['publicProtected', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PROTECTED];
|
||||
yield ['protectedPrivate', PropertyReadInfo::VISIBILITY_PROTECTED, PropertyWriteInfo::VISIBILITY_PRIVATE];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideVirtualPropertiesMutator
|
||||
* @requires PHP 8.4
|
||||
*/
|
||||
public function testVirtualPropertiesMutator(string $property, string $readVisibility, string $writeVisibility)
|
||||
{
|
||||
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
|
||||
$readMutator = $extractor->getReadInfo(VirtualProperties::class, $property);
|
||||
$writeMutator = $extractor->getWriteInfo(VirtualProperties::class, $property, [
|
||||
'enable_getter_setter_extraction' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
|
||||
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
|
||||
$this->assertSame($readVisibility, $readMutator->getVisibility());
|
||||
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
|
||||
}
|
||||
|
||||
public static function provideVirtualPropertiesMutator(): iterable
|
||||
{
|
||||
yield ['virtualNoSetHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
|
||||
yield ['virtualSetHookOnly', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
|
||||
yield ['virtualHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
|
||||
}
|
||||
}
|
||||
63
vendor/symfony/property-info/Tests/Extractor/SerializerExtractorTest.php
vendored
Normal file
63
vendor/symfony/property-info/Tests/Extractor/SerializerExtractorTest.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\IgnorePropertyDummy;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
|
||||
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class SerializerExtractorTest extends TestCase
|
||||
{
|
||||
private SerializerExtractor $extractor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (class_exists(AttributeLoader::class)) {
|
||||
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
|
||||
} else {
|
||||
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
|
||||
}
|
||||
$this->extractor = new SerializerExtractor($classMetadataFactory);
|
||||
}
|
||||
|
||||
public function testGetProperties()
|
||||
{
|
||||
$this->assertEquals(
|
||||
['collection'],
|
||||
$this->extractor->getProperties(Dummy::class, ['serializer_groups' => ['a']])
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetPropertiesWithIgnoredProperties()
|
||||
{
|
||||
$this->assertSame(['visibleProperty'], $this->extractor->getProperties(IgnorePropertyDummy::class, ['serializer_groups' => ['a']]));
|
||||
}
|
||||
|
||||
public function testGetPropertiesWithAnyGroup()
|
||||
{
|
||||
$this->assertSame(['analyses', 'feet'], $this->extractor->getProperties(AdderRemoverDummy::class, ['serializer_groups' => null]));
|
||||
}
|
||||
|
||||
public function testGetPropertiesWithNonExistentClassReturnsNull()
|
||||
{
|
||||
$this->assertSame(null, $this->extractor->getProperties('NonExistent'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user