refactor: Cleanup git state - commit all staged changes

Major refactoring cleanup:
- Add new controller architecture (class-controller-*.php)
- Add new settings-v2 UI (views/settings-v2/)
- Add new CSS architecture (agentic-sidebar.css, tokens)
- Add esbuild build pipeline (scripts/build.js, package.json)
- Add composer dependencies (vendor/)
- Add frontend src directory (assets/js/src/index.jsx)
- Add documentation files
- Remove old/obsolete files (class-settings.php, old CSS)

This commits all pending changes from previous refactoring efforts.
This commit is contained in:
Dwindi Ramadhana
2026-06-17 05:27:58 +07:00
parent d3f142222c
commit 690991c526
7963 changed files with 941566 additions and 67372 deletions

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection;
use EliasHaeussler\PHPUnitAttributes\Attribute\RequiresPackage;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use PHPUnit\Framework\TestCase;
/** @coversNothing */
#[RequiresPackage('nikic/php-parser', '>= 5.2')]
final class AsymmetricAccessorTest extends TestCase
{
public function testAsymmetricAccessor(): void
{
$file = __DIR__ . '/data/PHP84/AsymmetricAccessor.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\AsymmetricAccessor'];
self::assertEquals(
'public',
$class->getProperties()['\AsymmetricAccessor::$pizza']->getVisibility()->getReadVisibility(),
);
self::assertEquals(
'private',
$class->getProperties()['\AsymmetricAccessor::$pizza']->getVisibility()->getWriteVisibility(),
);
}
public function testAsyncPropertyPromotion(): void
{
$file = __DIR__ . '/data/PHP84/AsymmetricPropertyPromotion.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\AsymmetricPropertyPromotion'];
self::assertEquals(
'public',
$class->getProperties()['\AsymmetricPropertyPromotion::$pizza']->getVisibility()->getReadVisibility(),
);
self::assertEquals(
'protected',
$class->getProperties()['\AsymmetricPropertyPromotion::$pizza']->getVisibility()->getWriteVisibility(),
);
}
}

View File

@@ -0,0 +1,168 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\Class_;
use phpDocumentor\Reflection\Php\Constant;
use phpDocumentor\Reflection\Php\File as PhpFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\Object_;
/**
* @coversNothing
*/
final class ClassesTest extends MockeryTestCase
{
const FILE_PIZZA = __DIR__ . '/data/Pizza.php';
const FILE_LUIGI_PIZZA = __DIR__ . '/data/Luigi/Pizza.php';
/** @var ProjectFactory */
private $fixture;
/** @var Project */
private $project;
protected function setUp() : void
{
$this->fixture = ProjectFactory::createInstance();
$this->project = $this->fixture->create(
'MyProject',
[
new LocalFile(self::FILE_PIZZA),
new LocalFile(self::FILE_LUIGI_PIZZA),
]
);
}
public function testItHasAllConstants() : void
{
$file = $this->project->getFiles()[self::FILE_PIZZA];
$className = '\\Pizza';
$constantName = '\\Pizza::PACKAGING';
$class = $this->fetchClassFromFile($className, $file);
$this->assertArrayHasKey($constantName, $class->getConstants());
$constant = $class->getConstants()[$constantName];
$this->assertInstanceOf(Constant::class, $constant);
$this->assertArrayHasKey('\\OVEN_TEMPERATURE', $file->getConstants());
$this->assertArrayHasKey('\\MAX_OVEN_TEMPERATURE', $file->getConstants());
}
public function testTypedPropertiesReturnTheirType() : void
{
$fileName = self::FILE_LUIGI_PIZZA;
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
/** @var Class_ $pizzaClass */
$pizzaClass = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza'];
$this->assertArrayHasKey('\\Luigi\\Pizza::$size', $pizzaClass->getProperties());
$this->assertEquals(new Integer(), $pizzaClass->getProperties()['\\Luigi\\Pizza::$size']->getType());
}
public function testUsedTraitsAreIncludedInClass() : void
{
$fileName = self::FILE_LUIGI_PIZZA;
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
/** @var Class_ $pizzaClass */
$pizzaClass = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza'];
$this->assertEquals(['\\Luigi\\ExampleNestedTrait' => new Fqsen('\\Luigi\\ExampleNestedTrait')], $pizzaClass->getUsedTraits());
}
public function testWithNamespacedClass() : void
{
$fileName = self::FILE_LUIGI_PIZZA;
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi\\Pizza', $project->getFiles()[$fileName]->getClasses());
$this->assertEquals('\Pizza', $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getParent());
$this->assertArrayHasKey(
'\\Luigi\\Pizza::$instance',
$project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getProperties()
);
$methods = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getMethods();
$this->assertArrayHasKey(
'\\Luigi\\Pizza::__construct()',
$methods
);
$this->assertEquals('style', $methods['\\Luigi\\Pizza::__construct()']->getArguments()[0]->getName());
$this->assertEquals(
new Object_(new Fqsen('\\Luigi\\Pizza\Style')),
$methods['\\Luigi\\Pizza::__construct()']->getArguments()[0]->getType()
);
}
public function testWithUsedParent() : void
{
$fileName = __DIR__ . '/data/Luigi/StyleFactory.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi\\StyleFactory', $project->getFiles()[$fileName]->getClasses());
$this->assertEquals(
'\\Luigi\\Pizza\\PizzaComponentFactory',
$project->getFiles()[$fileName]->getClasses()['\\Luigi\\StyleFactory']->getParent()
);
}
public function testWithInterface() : void
{
$fileName = __DIR__ . '/data/Luigi/Valued.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\Valued', $project->getFiles()[$fileName]->getInterfaces());
}
public function testWithTrait() : void
{
$fileName = __DIR__ . '/data/Luigi/ExampleNestedTrait.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\ExampleNestedTrait', $project->getFiles()[$fileName]->getTraits());
}
private function fetchClassFromFile(string $className, PhpFile $file)
{
$this->assertArrayHasKey($className, $file->getClasses());
return $file->getClasses()[$className];
}
}

View File

@@ -0,0 +1,123 @@
<?php
declare(strict_types=1);
namespace integration;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\Php\Enum_;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Object_;
use PHPUnit\Framework\TestCase;
use phpDocumentor\Reflection\Types\String_;
/**
* @coversNothing
*/
final class EnumTest extends TestCase
{
const FILE = __DIR__ . '/data/Enums/base.php';
const BACKED_ENUM = __DIR__ . '/data/Enums/backedEnum.php';
const ENUM_WITH_CONSTANT = __DIR__ . '/data/Enums/enumWithConstant.php';
const ENUM_CONSUMER = __DIR__ . '/data/Enums/EnumConsumer.php';
/** @var ProjectFactory */
private $fixture;
/** @var Project */
private $project;
protected function setUp() : void
{
$this->fixture = ProjectFactory::createInstance();
$this->project = $this->fixture->create(
'Enums',
[
new LocalFile(self::FILE),
new LocalFile(self::BACKED_ENUM),
new LocalFile(self::ENUM_WITH_CONSTANT),
new LocalFile(self::ENUM_CONSUMER),
]
);
}
public function testFileHasEnum(): void
{
$file = $this->project->getFiles()[self::FILE];
$enum = $file->getEnums()['\MyNamespace\MyEnum'];
self::assertInstanceOf(Enum_::class, $enum);
self::assertCount(2, $enum->getCases());
self::assertNull($enum->getBackedType());
self::assertArrayHasKey('\MyNamespace\MyEnum::VALUE1', $enum->getCases());
self::assertArrayHasKey('\MyNamespace\MyEnum::VALUE2', $enum->getCases());
}
public function testEnumWithConstant(): void
{
$file = $this->project->getFiles()[self::ENUM_WITH_CONSTANT];
$enum = $file->getEnums()['\MyNamespace\MyEnumWithConstant'];
self::assertInstanceOf(Enum_::class, $enum);
self::assertCount(2, $enum->getConstants());
self::assertArrayHasKey('\MyNamespace\MyEnumWithConstant::MYCONST', $enum->getConstants());
self::assertSame("'MyConstValue'", $enum->getConstants()['\MyNamespace\MyEnumWithConstant::MYCONST']->getValue());
}
public function testBackedEnum(): void
{
$file = $this->project->getFiles()[self::BACKED_ENUM];
$enum = $file->getEnums()['\MyNamespace\MyBackedEnum'];
self::assertInstanceOf(Enum_::class, $enum);
self::assertCount(2, $enum->getCases());
self::assertEquals(new String_(), $enum->getBackedType());
self::assertArrayHasKey('\MyNamespace\MyBackedEnum::VALUE1', $enum->getCases());
self::assertArrayHasKey('\MyNamespace\MyBackedEnum::VALUE2', $enum->getCases());
self::assertSame("'this is value1'", $enum->getCases()['\MyNamespace\MyBackedEnum::VALUE1']->getValue());
self::assertSame("'this is value2'", $enum->getCases()['\MyNamespace\MyBackedEnum::VALUE2']->getValue());
}
public function testEnumSupportInProperty(): void
{
$file = $this->project->getFiles()[self::ENUM_CONSUMER];
$class = $file->getClasses()['\MyNamespace\EnumConsumer'];
self::assertEquals(
'\MyNamespace\MyEnum::VALUE1',
$class->getProperties()['\MyNamespace\EnumConsumer::$myEnum']->getDefault()
);
self::assertEquals(
new Object_(new Fqsen('\MyNamespace\MyEnum')),
$class->getProperties()['\MyNamespace\EnumConsumer::$myEnum']->getType()
);
}
public function testEnumSupportInMethod(): void
{
$file = $this->project->getFiles()[self::ENUM_CONSUMER];
$class = $file->getClasses()['\MyNamespace\EnumConsumer'];
$method = $class->getMethods()['\MyNamespace\EnumConsumer::consume()'];
self::assertEquals(
new Object_(new Fqsen('\MyNamespace\MyEnum')),
$method->getReturnType()
);
self::assertEquals(
new Object_(new Fqsen('\MyNamespace\MyEnum')),
$method->getArguments()[0]->getType()
);
self::assertEquals(
'\MyNamespace\MyEnum::VALUE1',
$method->getArguments()[0]->getDefault()
);
}
}

View File

@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace integration;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;
/**
* Integration tests to check the correct working of processing a namespace into a project.
*
* @coversNothing
*/
#[CoversNothing]
final class FileDocblockTest extends TestCase
{
/** @var ProjectFactory */
private $fixture;
protected function setUp() : void
{
$this->fixture = ProjectFactory::createInstance();
}
/**
* @dataProvider fileProvider
*/
public function testFileDocblock(string $fileName) : void
{
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertEquals(
'This file is part of phpDocumentor.',
$project->getFiles()[$fileName]->getDocBlock()->getSummary()
);
}
public static function fileProvider() : array
{
return [
[ __DIR__ . '/data/GlobalFiles/empty.php' ],
[ __DIR__ . '/data/GlobalFiles/empty_with_declare.php' ],
[ __DIR__ . '/data/GlobalFiles/empty_shebang.php' ],
[ __DIR__ . '/data/GlobalFiles/psr12.php' ],
[ __DIR__ . '/data/GlobalFiles/docblock_followed_by_html.php' ],
];
}
public function testConditionalFunctionDefine() : void
{
$fileName = __DIR__ . '/data/GlobalFiles/conditional_function.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertCount(
4,
$project->getFiles()[$fileName]->getFunctions()
);
}
public function testGlobalNamespacedFunctionDefine() : void
{
$fileName = __DIR__ . '/data/GlobalFiles/global_namspaced_function.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertCount(
1,
$project->getFiles()[$fileName]->getFunctions()
);
}
public function testFileWithInlineFunction() : void
{
$fileName = __DIR__ . '/data/GlobalFiles/inline_function.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertCount(
1,
$project->getFiles()[$fileName]->getClasses()
);
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace integration;
use EliasHaeussler\PHPUnitAttributes\Attribute\RequiresPackage;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Php\Visibility;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\String_;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;
#[RequiresPackage('nikic/php-parser', '>= 5.2')]
#[CoversNothing]
final class InterfacePropertyTest extends TestCase
{
public function testInterfacePropertiesAreParsed(): void
{
$file = __DIR__ . '/data/PHP84/InterfaceProperties.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$interfaces = $project->getFiles()[$file]->getInterfaces();
$hasId = $interfaces['\PHP84\HasId'];
$properties = $hasId->getProperties();
$this->assertCount(1, $properties);
$idProperty = $properties['\PHP84\HasId::$id'];
$this->assertEquals(new Integer(), $idProperty->getType());
$this->assertEquals(new Visibility(Visibility::PUBLIC_), $idProperty->getVisibility());
$this->assertCount(1, $idProperty->getHooks());
$this->assertEquals('get', $idProperty->getHooks()[0]->getName());
$hasName = $interfaces['\PHP84\HasName'];
$properties = $hasName->getProperties();
$this->assertCount(1, $properties);
$nameProperty = $properties['\PHP84\HasName::$name'];
$this->assertEquals(new String_(), $nameProperty->getType());
$this->assertCount(2, $nameProperty->getHooks());
}
}

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\Metadata;
final class Hook implements Metadata
{
private $hook;
public function __construct(string $hook)
{
$this->hook = $hook;
}
public function key(): string
{
return "project-metadata";
}
public function hook(): string
{
return $this->hook;
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\Metadata;
use phpDocumentor\Reflection\Php\Factory\ContextStack;
use phpDocumentor\Reflection\Php\ProjectFactoryStrategy;
use phpDocumentor\Reflection\Php\StrategyContainer;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Stmt\Expression;
final class HookStrategy implements ProjectFactoryStrategy
{
public function matches(ContextStack $context, object $object): bool
{
if ($object instanceof Expression === false) {
return false;
}
return $object->expr instanceof FuncCall && ((string)$object->expr->name) === 'hook';
}
public function create(ContextStack $context, object $object, StrategyContainer $strategies): void
{
$method = $context->peek();
$method->addMetadata(new Hook($object->expr->args[0]->value->value));
}
}

View File

@@ -0,0 +1,10 @@
<?php
class myHookUsingClass
{
public function test() {
echo "Do something";
hook('foo');
echo "finish";
}
}

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Metadata\HookStrategy;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
final class MetadataTest extends TestCase
{
const FILE = __DIR__ . '/Metadata/example.php';
public function testCustomMetadata(): void
{
$projectFactory = ProjectFactory::createInstance();
$projectFactory->addStrategy(new HookStrategy());
/** @var Project $project */
$project = $projectFactory->create('My project', [new LocalFile(self::FILE)]);
$class = $project->getFiles()[self::FILE]->getClasses()['\myHookUsingClass'];
self::assertArrayHasKey('project-metadata', $class->getMethods()['\myHookUsingClass::test()']->getMetadata());
}
}

View File

@@ -0,0 +1,230 @@
<?php
declare(strict_types=1);
namespace integration\PHP8;
use DateTimeImmutable;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\Location;
use phpDocumentor\Reflection\Php\Argument;
use phpDocumentor\Reflection\Php\Expression;
use phpDocumentor\Reflection\Php\Method;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Php\Property;
use phpDocumentor\Reflection\Php\Visibility;
use phpDocumentor\Reflection\Types\Array_;
use phpDocumentor\Reflection\Types\Context;
use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\String_;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
class ConstructorPromotionTest extends TestCase
{
private const FILE = __DIR__ . '/../data/PHP8/ConstructorPromotion.php';
private ProjectFactory $fixture;
private Project $project;
protected function setUp() : void
{
$this->fixture = ProjectFactory::createInstance();
$this->project = $this->fixture->create(
'PHP8',
[
new LocalFile(self::FILE),
]
);
}
public function testArgumentsAreReadCorrectly() : void
{
$file = $this->project->getFiles()[self::FILE];
$class = $file->getClasses()['\\PHP8\\ConstructorPromotion'];
$constructor = $this->expectedConstructorMethod();
$constructor->addArgument(new Argument('name', new String_(), "'default name'"));
$constructor->addArgument(
new Argument(
'email',
new Object_(new Fqsen('\\PHP8\\Email')),
new Expression(
'new {{ PHPDOCc27b34d4d91bc4d52190708db8447e09 }}()',
[
'{{ PHPDOCc27b34d4d91bc4d52190708db8447e09 }}' => new Fqsen('\\PHP8\\Email'),
],
)
)
);
$constructor->addArgument(new Argument('birth_date', new Object_(new Fqsen('\\' . DateTimeImmutable::class))));
$constructor->addArgument(
new Argument(
'created_at',
new Object_(new Fqsen('\\' . DateTimeImmutable::class)),
new Expression(
'new {{ PHPDOCf854926c6ee2b49d3385c30295984295 }}(\'now\')',
[
'{{ PHPDOCf854926c6ee2b49d3385c30295984295 }}' => new Fqsen('\\DateTimeImmutable')
]
)
)
);
$constructor->addArgument(
new Argument(
'uses_constants',
new Array_(),
new Expression(
'[{{ PHPDOC19b72d1f430d952a8dfe2384dd4e93dc }}]',
[
'{{ PHPDOC19b72d1f430d952a8dfe2384dd4e93dc }}' => new Fqsen('\self::DEFAULT_VALUE'),
],
),
),
);
self::assertEquals($constructor, $class->getMethods()['\PHP8\ConstructorPromotion::__construct()']);
}
public function testPropertiesAreCreated() : void
{
$file = $this->project->getFiles()[self::FILE];
$class = $file->getClasses()['\\PHP8\\ConstructorPromotion'];
self::assertEquals(
[
'\PHP8\ConstructorPromotion::$name' => $this->expectedNameProperty(),
'\PHP8\ConstructorPromotion::$email' => $this->expectedEmailProperty(),
'\PHP8\ConstructorPromotion::$birth_date' => $this->expectedBirthDateProperty(),
'\PHP8\ConstructorPromotion::$created_at' => $this->expectedCreatedAtProperty(),
'\PHP8\ConstructorPromotion::$uses_constants' => $this->expectedUsesConstantsProperty(),
],
$class->getProperties()
);
}
private function expectedConstructorMethod(): Method
{
return new Method(
new Fqsen('\PHP8\ConstructorPromotion::__construct()'),
new Visibility(Visibility::PUBLIC_),
new DocBlock(
'Constructor with promoted properties',
null,
[
new Param(
'name',
new String_(),
false,
new DocBlock\Description('my docblock name')
)
],
new Context('PHP8', ['DateTimeImmutable' => 'DateTimeImmutable'])
),
false,
false,
false,
new Location(18, 264),
new Location(31, 718)
);
}
private function expectedNameProperty(): Property
{
return new Property(
new Fqsen('\PHP8\ConstructorPromotion::$name'),
new Visibility(Visibility::PUBLIC_),
new DocBlock(
'Summary',
new DocBlock\Description('Description'),
[
new Var_('name', new String_(), new DocBlock\Description('property description'))
],
new Context('PHP8', ['DateTimeImmutable' => 'DateTimeImmutable'])
),
"'default name'",
false,
new Location(26),
new Location(26),
new String_()
);
}
private function expectedEmailProperty(): Property
{
return new Property(
new Fqsen('\PHP8\ConstructorPromotion::$email'),
new Visibility(Visibility::PROTECTED_),
null,
new Expression(
'new {{ PHPDOCc27b34d4d91bc4d52190708db8447e09 }}()',
[
'{{ PHPDOCc27b34d4d91bc4d52190708db8447e09 }}' => new Fqsen('\\PHP8\\Email'),
],
),
false,
new Location(27),
new Location(27),
New Object_(new Fqsen('\\PHP8\\Email')),
);
}
private function expectedBirthDateProperty(): Property
{
return new Property(
new Fqsen('\PHP8\ConstructorPromotion::$birth_date'),
new Visibility(Visibility::PRIVATE_),
null,
null,
false,
new Location(28),
new Location(28),
new Object_(new Fqsen('\\' . DateTimeImmutable::class))
);
}
private function expectedCreatedAtProperty(): Property
{
return new Property(
new Fqsen('\PHP8\ConstructorPromotion::$created_at'),
new Visibility(Visibility::PRIVATE_),
null,
new Expression(
'new {{ PHPDOCf854926c6ee2b49d3385c30295984295 }}(\'now\')',
[
'{{ PHPDOCf854926c6ee2b49d3385c30295984295 }}' => new Fqsen('\\DateTimeImmutable'),
],
),
false,
new Location(29),
new Location(29),
new Object_(new Fqsen('\\' . DateTimeImmutable::class)),
);
}
private function expectedUsesConstantsProperty()
{
return new Property(
new Fqsen('\PHP8\ConstructorPromotion::$uses_constants'),
new Visibility(Visibility::PRIVATE_),
null,
new Expression(
'[{{ PHPDOC19b72d1f430d952a8dfe2384dd4e93dc }}]',
[
'{{ PHPDOC19b72d1f430d952a8dfe2384dd4e93dc }}' => new Fqsen('\self::DEFAULT_VALUE'),
],
),
false,
new Location(30),
new Location(30),
new Array_(),
);
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace integration\PHP8;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Mixed_;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
final class MixedTypeTest extends TestCase
{
const FILE = __DIR__ . '/../data/PHP8/MixedType.php';
/** @var ProjectFactory */
private $fixture;
public function testSupportMixedType() : void
{
$this->fixture = ProjectFactory::createInstance();
/** @var Project $project */
$project = $this->fixture->create(
'PHP8',
[
new LocalFile(self::FILE),
]
);
$file = $project->getFiles()[self::FILE];
$class = $file->getClasses()['\PHP8\MixedType'];
self::assertEquals(new Mixed_(), $class->getMethods()['\PHP8\MixedType::getProperty()']->getReturnType());
self::assertEquals(new Mixed_(), $class->getMethods()['\PHP8\MixedType::setProperty()']->getArguments()[0]->getType());
self::assertEquals(new Mixed_(), $class->getProperties()['\PHP8\MixedType::$property']->getType());
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace integration\PHP8;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Mixed_;
use phpDocumentor\Reflection\Types\Static_;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
final class StaticTypeTest extends TestCase
{
const FILE = __DIR__ . '/../data/PHP8/StaticType.php';
/** @var ProjectFactory */
private $fixture;
public function testSupportStaticType() : void
{
$this->fixture = ProjectFactory::createInstance();
/** @var Project $project */
$project = $this->fixture->create(
'PHP8',
[
new LocalFile(self::FILE),
]
);
$file = $project->getFiles()[self::FILE];
$class = $file->getClasses()['\PHP8\StaticType'];
self::assertEquals(new Static_(), $class->getMethods()['\PHP8\StaticType::getProperty()']->getReturnType());
self::assertEquals(new Mixed_(), $class->getMethods()['\PHP8\StaticType::setProperty()']->getArguments()[0]->getType());
self::assertEquals(null, $class->getProperties()['\PHP8\StaticType::$property']->getType());
self::assertTrue($class->getProperties()['\PHP8\StaticType::$property']->isStatic());
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace integration\PHP8;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\Php\Project;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\False_;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\Mixed_;
use phpDocumentor\Reflection\Types\Null_;
use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\Static_;
use phpDocumentor\Reflection\Types\String_;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
final class UnionTypesTest extends TestCase
{
const FILE = __DIR__ . '/../data/PHP8/UnionTypes.php';
/** @var ProjectFactory */
private $fixture;
public function testUnionTypes() : void
{
$this->fixture = ProjectFactory::createInstance();
/** @var Project $project */
$project = $this->fixture->create(
'PHP8',
[
new LocalFile(self::FILE),
]
);
$file = $project->getFiles()[self::FILE];
$class = $file->getClasses()['\PHP8\UnionTypes'];
self::assertEquals(new Compound([new String_(), new Null_(), new Object_(new Fqsen('\Foo\Date'))]), $class->getMethods()['\PHP8\UnionTypes::union()']->getReturnType());
self::assertEquals(new Compound([new Integer(), new False_()]), $class->getMethods()['\PHP8\UnionTypes::union()']->getArguments()[0]->getType());
self::assertEquals(new Compound([new String_(), new Null_(), new False_()]), $class->getProperties()['\PHP8\UnionTypes::$property']->getType());
}
}

View File

@@ -0,0 +1,286 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\Class_;
use phpDocumentor\Reflection\Php\Expression;
use phpDocumentor\Reflection\Php\Function_;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\Null_;
use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\String_;
/**
* Integration tests to check the correct working of processing a file into a project.
*
* @coversNothing
*/
class ProjectCreationTest extends MockeryTestCase
{
/** @var ProjectFactory */
private $fixture;
protected function setUp() : void
{
$this->fixture = ProjectFactory::createInstance();
}
public function testCreateProjectWithFunctions() : void
{
$fileName = __DIR__ . '/data/simpleFunction.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$file = $project->getFiles()[$fileName];
$this->assertArrayHasKey('\simpleFunction()', $file->getFunctions());
/** @var Function_ $function */
$function = $file->getFunctions()['\simpleFunction()'];
$this->assertSame('\simpleFunction()', (string) $function->getFqsen());
$this->assertCount(1, $function->getArguments());
}
public function testCreateProjectWithClass() : void
{
$fileName = __DIR__ . '/data/Pizza.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Pizza', $project->getFiles()[$fileName]->getClasses());
$this->assertArrayHasKey(
'\\Pizza::PACKAGING',
$project->getFiles()[$fileName]->getClasses()['\\Pizza']->getConstants()
);
$constant = $project->getFiles()[$fileName]->getClasses()['\\Pizza']->getConstants()['\\Pizza::PACKAGING'];
$this->assertEquals('\'box\'', $constant->getValue());
}
public function testTypedPropertiesReturnTheirType() : void
{
$fileName = __DIR__ . '/data/Luigi/Pizza.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
/** @var Class_ $pizzaClass */
$pizzaClass = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza'];
$this->assertArrayHasKey('\\Luigi\\Pizza::$size', $pizzaClass->getProperties());
$this->assertEquals(new Integer(), $pizzaClass->getProperties()['\\Luigi\\Pizza::$size']->getType());
}
public function testFileWithDocBlock() : void
{
$fileName = __DIR__ . '/data/Pizza.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertInstanceOf(Docblock::class, $project->getFiles()[$fileName]->getDocBlock());
}
public function testWithNamespacedClass() : void
{
$fileName = __DIR__ . '/data/Luigi/Pizza.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi\\Pizza', $project->getFiles()[$fileName]->getClasses());
$this->assertEquals('\Pizza', $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getParent());
$this->assertArrayHasKey(
'\\Luigi\\Pizza::$instance',
$project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getProperties()
);
$methods = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getMethods();
$this->assertArrayHasKey(
'\\Luigi\\Pizza::__construct()',
$methods
);
$this->assertEquals('style', $methods['\\Luigi\\Pizza::__construct()']->getArguments()[0]->getName());
$this->assertEquals(
new Object_(new Fqsen('\\Luigi\\Pizza\Style')),
$methods['\\Luigi\\Pizza::__construct()']->getArguments()[0]->getType()
);
$sauceArgument = $methods['\\Luigi\\Pizza::__construct()']->getArguments()[1];
$this->assertEquals('sauce', $sauceArgument->getName());
$this->assertEquals(
new Php\Expression(
'{{ PHPDOC37a6259cc0c1dae299a7866489dff0bd }}',
[
'{{ PHPDOC37a6259cc0c1dae299a7866489dff0bd }}' => new Null_(),
],
),
$sauceArgument->getDefault(false)
);
}
public function testDocblockOfMethodIsProcessed() : void
{
$fileName = __DIR__ . '/data/Luigi/Pizza.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$methods = $project->getFiles()[$fileName]->getClasses()['\\Luigi\\Pizza']->getMethods();
$createInstanceMethod = $methods['\\Luigi\\Pizza::createInstance()'];
$this->assertInstanceOf(DocBlock::class, $createInstanceMethod->getDocBlock());
$docblock = $createInstanceMethod->getDocBlock();
/** @var Param[] $params */
$params = $docblock->getTagsByName('param');
/** @var Object_ $objectType */
$objectType = $params[0]->getType();
$this->assertEquals(new Fqsen('\Luigi\Pizza\Style'), $objectType->getFqsen());
}
public function testWithUsedParent() : void
{
$fileName = __DIR__ . '/data/Luigi/StyleFactory.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi\\StyleFactory', $project->getFiles()[$fileName]->getClasses());
$this->assertEquals(
'\\Luigi\\Pizza\\PizzaComponentFactory',
$project->getFiles()[$fileName]->getClasses()['\\Luigi\\StyleFactory']->getParent()
);
}
public function testWithInterface() : void
{
$fileName = __DIR__ . '/data/Luigi/Valued.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\Valued', $project->getFiles()[$fileName]->getInterfaces());
}
public function testWithTrait() : void
{
$fileName = __DIR__ . '/data/Luigi/ExampleNestedTrait.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\ExampleNestedTrait', $project->getFiles()[$fileName]->getTraits());
}
public function testWithGlobalConstants() : void
{
$fileName = __DIR__ . '/data/Luigi/constants.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\OVEN_TEMPERATURE', $project->getFiles()[$fileName]->getConstants());
$this->assertArrayHasKey('\\Luigi\\MAX_OVEN_TEMPERATURE', $project->getFiles()[$fileName]->getConstants());
$this->assertArrayHasKey('\\OUTSIDE_OVEN_TEMPERATURE', $project->getFiles()[$fileName]->getConstants());
$this->assertArrayHasKey('\\LuigiFoo\\_OUTSIDE_OVEN_TEMPERATURE', $project->getFiles()[$fileName]->getConstants());
}
public function testInterfaceExtends() : void
{
$fileName = __DIR__ . '/data/Luigi/Packing.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Luigi\\Packing', $project->getFiles()[$fileName]->getInterfaces());
$interface = current($project->getFiles()[$fileName]->getInterfaces());
$this->assertEquals(['\\Packing' => new Fqsen('\\Packing')], $interface->getParents());
}
public function testMethodReturnType() : void
{
$fileName = __DIR__ . '/data/Packing.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey('\\Packing', $project->getFiles()[$fileName]->getInterfaces());
$interface = current($project->getFiles()[$fileName]->getInterfaces());
$this->assertEquals(new String_(), $interface->getMethods()['\Packing::getName()']->getReturnType());
}
public function testFunctionContantDefaultIsResolved() : void
{
$fileName = __DIR__ . '/data/GlobalFiles/function_constant_default.php';
$project = $this->fixture->create(
'MyProject',
[new LocalFile($fileName)]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$functions = $project->getFiles()[$fileName]->getFunctions();
self::assertEquals(
new Expression(
'{{ PHPDOCa2f2ed4f8ebc2cbb4c21a29dc40ab61d }}',
[
'{{ PHPDOCa2f2ed4f8ebc2cbb4c21a29dc40ab61d }}' => new Fqsen('\Acme\Plugin::class'),
],
),
$functions['\foo()']->getArguments()[0]->getDefault(false)
);
self::assertEquals(
new Expression(
'{{ PHPDOCa8cfde6331bd59eb2ac96f8911c4b666 }}',
[
'{{ PHPDOCa8cfde6331bd59eb2ac96f8911c4b666 }}' => new Object_(),
],
),
$functions['\bar()']->getArguments()[0]->getDefault(false)
);
}
}

View File

@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use PHPUnit\Framework\TestCase;
/**
* Integration tests to check the correct working of processing a namespace into a project.
*
* @coversNothing
*/
class ProjectNamespaceTest extends TestCase
{
/**
* @var ProjectFactory
*/
private $fixture;
protected function setUp() : void
{
$this->fixture = $this->fixture = ProjectFactory::createInstance();
}
public function testWithNamespacedClass() : void
{
$fileName = __DIR__ . '/data/Luigi/Pizza.php';
$project = $this->fixture->create(
'My Project',
[ new LocalFile($fileName) ]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi', $project->getNamespaces());
$this->assertEquals(
['\\Luigi\\Pizza' => new Fqsen('\\Luigi\\Pizza')],
$project->getNamespaces()['\\Luigi']->getClasses()
);
}
public function testWithNamespacedConstant() : void
{
$fileName = __DIR__ . '/data/Luigi/constants.php';
$project = $this->fixture->create(
'My Project',
[ new LocalFile($fileName) ]
);
$this->assertArrayHasKey($fileName, $project->getFiles());
$this->assertArrayHasKey('\\Luigi', $project->getNamespaces());
$this->assertEquals(
[
'\\Luigi\\OVEN_TEMPERATURE' => new Fqsen('\\Luigi\\OVEN_TEMPERATURE'),
'\\Luigi\\MAX_OVEN_TEMPERATURE' => new Fqsen('\\Luigi\\MAX_OVEN_TEMPERATURE'),
],
$project->getNamespaces()['\\Luigi']->getConstants()
);
}
}

View File

@@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
namespace integration;
use EliasHaeussler\PHPUnitAttributes\Attribute\RequiresPackage;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Location;
use phpDocumentor\Reflection\Php\Argument;
use phpDocumentor\Reflection\Php\AsymmetricVisibility;
use phpDocumentor\Reflection\Php\Attribute;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Php\PropertyHook;
use phpDocumentor\Reflection\Php\Visibility;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\String_;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;
#[RequiresPackage('nikic/php-parser', '>= 5.2')]
#[CoversNothing]
final class PropertyHookTest extends TestCase
{
public function testPropertyHookWithDocblocks(): void
{
$file = __DIR__ . '/data/PHP84/PropertyHook.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\PropertyHook'];
$hooks = $class->getProperties()['\PropertyHook::$example']->getHooks();
$this->assertTrue($class->getProperties()['\PropertyHook::$example']->isVirtual());
$this->assertCount(2, $hooks);
$this->assertEquals('get', $hooks[0]->getName());
$this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[0]->getVisibility());
$this->assertCount(1, $hooks[0]->getAttributes());
$this->assertCount(0, $hooks[0]->getArguments());
$this->assertSame('Not sure this works, but it gets', $hooks[0]->getDocBlock()->getSummary());
$this->assertEquals('set', $hooks[1]->getName());
$this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[1]->getVisibility());
$this->assertCount(1, $hooks[1]->getAttributes());
$this->assertCount(1, $hooks[1]->getArguments());
$this->assertEquals(new Argument(
'value',
new Compound(
[
new String_(),
new Integer()
]
),
), $hooks[1]->getArguments()[0]);
$this->assertSame('Not sure this works, but it gets', $hooks[0]->getDocBlock()->getSummary());
}
public function testPropertyHookAsymmetric(): void
{
$file = __DIR__ . '/data/PHP84/PropertyHookAsymmetric.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\PropertyHook'];
$hooks = $class->getProperties()['\PropertyHook::$example']->getHooks();
$this->assertEquals(
new AsymmetricVisibility(
new Visibility(Visibility::PUBLIC_),
new Visibility(Visibility::PRIVATE_)
),
$class->getProperties()['\PropertyHook::$example']->getVisibility()
);
$this->assertTrue($class->getProperties()['\PropertyHook::$example']->isVirtual());
$this->assertCount(2, $hooks);
$this->assertEquals('get', $hooks[0]->getName());
$this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[0]->getVisibility());
$this->assertCount(0, $hooks[0]->getArguments());
$this->assertEquals('set', $hooks[1]->getName());
$this->assertEquals(new Visibility(Visibility::PRIVATE_), $hooks[1]->getVisibility());
$this->assertCount(1, $hooks[1]->getArguments());
$this->assertEquals(new Argument(
'value',
new Compound(
[
new String_(),
new Integer()
]
),
), $hooks[1]->getArguments()[0]);
}
public function testVirtualProperty(): void
{
$file = __DIR__ . '/data/PHP84/PropertyHookVirtual.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\PropertyHookVirtual'];
// Test get-only virtual property
$fullNameProperty = $class->getProperties()['\PropertyHookVirtual::$fullName'];
$this->assertTrue($fullNameProperty->isVirtual(), 'Property with getter that doesn\'t reference itself should be virtual');
$this->assertCount(1, $fullNameProperty->getHooks());
$this->assertEquals('get', $fullNameProperty->getHooks()[0]->getName());
// Test set-only virtual property
$compositeNameProperty = $class->getProperties()['\PropertyHookVirtual::$compositeName'];
$this->assertTrue($compositeNameProperty->isVirtual(), 'Property with setter that doesn\'t reference itself should be virtual');
$this->assertCount(1, $compositeNameProperty->getHooks());
$this->assertEquals('set', $compositeNameProperty->getHooks()[0]->getName());
// Test property with both get and set hooks that doesn't reference itself
$completeFullNameProperty = $class->getProperties()['\PropertyHookVirtual::$completeFullName'];
$this->assertTrue($completeFullNameProperty->isVirtual(), 'Property with getter and setter that don\'t reference itself should be virtual');
$this->assertCount(2, $completeFullNameProperty->getHooks());
$nonVirtualPropertyWithoutHooks = $class->getProperties()['\PropertyHookVirtual::$firstName'];
$this->assertFalse($nonVirtualPropertyWithoutHooks->isVirtual(), 'Property without hooks should not be virtual');
$this->assertCount(0, $nonVirtualPropertyWithoutHooks->getHooks());
// Test non-virtual property that references itself
$nonVirtualNameProperty = $class->getProperties()['\PropertyHookVirtual::$nonVirtualName'];
$this->assertFalse($nonVirtualNameProperty->isVirtual(), 'Property with hooks that reference itself should not be virtual');
$this->assertCount(2, $nonVirtualNameProperty->getHooks());
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace integration;
use phpDocumentor\Reflection\File\LocalFile;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\Nullable;
use phpDocumentor\Reflection\Types\String_;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;
#[CoversNothing]
final class TypedConstantTest extends TestCase
{
public function testTypedClassConstantsHaveType(): void
{
$file = __DIR__ . '/data/PHP83/TypedConstants.php';
$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('My project', [new LocalFile($file)]);
$class = $project->getFiles()[$file]->getClasses()['\PHP83\TypedConstants'];
$constants = $class->getConstants();
$this->assertEquals(new String_(), $constants['\PHP83\TypedConstants::NAME']->getType());
$this->assertEquals(new Integer(), $constants['\PHP83\TypedConstants::COUNT']->getType());
$this->assertEquals(new Compound([new String_(), new Integer()]), $constants['\PHP83\TypedConstants::UNION']->getType());
$this->assertEquals(new Nullable(new String_()), $constants['\PHP83\TypedConstants::NULLABLE']->getType());
$this->assertNull($constants['\PHP83\TypedConstants::UNTYPED']->getType());
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace MyNamespace;
class EnumConsumer
{
public MyEnum $myEnum = MyEnum::VALUE1;
public function consume(MyEnum $enum = MyEnum::VALUE1): MyEnum
{
$this->myEnum = $enum;
}
}

View File

@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace MyNamespace;
enum MyBackedEnum : string
{
case VALUE1 = 'this is value1';
case VALUE2 = 'this is value2';
}

View File

@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace MyNamespace;
enum MyEnum
{
case VALUE1;
case VALUE2;
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace MyNamespace;
enum MyEnumWithConstant
{
public const MYCONST = 'MyConstValue';
public const INT_CONST = 0;
}

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
if (!function_exists('h')) {
function h() {
}
} elseif(!function_exists('i')) {
if (true) {
function i()
{
}
}
} else {
function j() {
}
}
function a() {
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
?>
<h1>Test</h1>
<?php
require 'Pizza.php';

View File

@@ -0,0 +1,13 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
require 'Pizza.php';

View File

@@ -0,0 +1,15 @@
#!/bin/php
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
require 'Pizza.php';

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
require 'Pizza.php';

View File

@@ -0,0 +1,14 @@
<h1>Test</h1>
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
require 'Pizza.php';

View File

@@ -0,0 +1,7 @@
<?php
use Acme\Plugin;
function foo( $output = Plugin::class ) {}
function bar( $output = OBJECT ) {}

View File

@@ -0,0 +1,23 @@
<?php
/**
* setup.php - Document the file.
*
* File long description goes here.
*
* @author Test Sample
*/
namespace {
/**
* autoloader function.
*
* Function long description goes here.
*
* @param string $class Namespaced class name
* @return void
*/
function libAutoload($class){
echo 'Do something';
}
spl_autoload_register('libAutoload');
}

View File

@@ -0,0 +1,11 @@
<?php
class Foo {
public function test() {
function internal() {
return "yep";
}
return internal();
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
declare(strict_types=1);
require 'Pizza.php';

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace Luigi {
trait ExampleNestedTrait
{
private function exampleTraitMethod()
{
}
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace Luigi;
interface Packing extends \Packing
{
}

View File

@@ -0,0 +1,99 @@
<?php
// phpcs:ignoreFile
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace Luigi;
use Luigi\Pizza\Sauce;
use Luigi\Pizza\TomatoSauce;
#[\Food("Pizza")]
#[\Food(country: "Italy", originDate: Pizza::class)]
class Pizza extends \Pizza
{
const
/** @var string DELIVERY designates that the delivery method is to deliver the pizza to the customer. */
DELIVERY = 'delivery',
/** @var string PICKUP designates that the delivery method is that the customer picks the pizza up. */
PICKUP = 'pickup';
use ExampleNestedTrait;
/** @var static contains the active instance for this Pizza. */
static private $instance;
/**
* @var Pizza\Style $style
* @var Pizza\Sauce|null $sauce
* @var Pizza\Topping[] $toppings
*/
private $style, $sauce, $toppings;
/**
* The size of the pizza in centimeters, defaults to 20cm.
*/
public int $size = \Luigi\Pizza\SIZE_20CM;
var $legacy; // don't use this anymore!
protected
/** @var string $packaging The type of packaging for this Pizza */
$packaging = self::PACKAGING,
/** @var string $deliveryMethod Is the customer picking this pizza up or must it be delivered? */
$deliveryMethod;
private function __construct(Pizza\Style $style, Sauce|null $sauce = null)
{
$this->style = $style;
}
/**
* Creates a new instance of a Pizza.
*
* This method can be used to instantiate a new object of this class which can then be retrieved using
* {@see self::getInstance()}.
*
* @param Pizza\Style $style
*
* @see self::getInstance to retrieve the pizza object.
*
* @return void
*/
public static function createInstance(Pizza\Style $style)
{
self::$instance = new static($style);
}
/**
* @return self
*/
static function getInstance()
{
return self::$instance;
}
final public function setSauce(Pizza\Sauce $sauce)
{
$this->sauce = $sauce;
}
final public function addTopping(Pizza\Topping $topping)
{
$this->toppings[] = $topping;
}
public function setSize(&$size = \Luigi\Pizza\SIZE_20CM)
{
}
public function getPrice()
{
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace Luigi;
use Luigi\Pizza\PizzaComponentFactory;
final class StyleFactory extends PizzaComponentFactory
{
public function getPrice()
{
}
protected function calculatePrice()
{
}
}

View File

@@ -0,0 +1,27 @@
<?php
// phpcs:ignoreFile
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace Luigi;
/**
* Any class implementing this interface has an associated price.
*
* Using this interface we can easily add the price of all components in a pizza by checking for this interface and
* adding the prices together for all components.
*/
interface Valued
{
const BASE_PRICE = 1;
function getPrice();
}

View File

@@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace Luigi;
const OVEN_TEMPERATURE = 9001;
define('\\Luigi\\MAX_OVEN_TEMPERATURE', 9002);
define('OUTSIDE_OVEN_TEMPERATURE', 9002);
define(__NAMESPACE__ . 'Foo\\_OUTSIDE_OVEN_TEMPERATURE', 9002);
$v = 1;
define($v . '_OUTSIDE_OVEN_TEMPERATURE', 9002);
function in_function_define(){
define('IN_FUNCTION_OVEN_TEMPERATURE', 9003);
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace PHP8;
use DateTimeImmutable;
class ConstructorPromotion
{
private const DEFAULT_VALUE = 'default';
/**
* Constructor with promoted properties
*
* @param string $name my docblock name
*/
public function __construct(
/**
* Summary
*
* Description
*
* @var string $name property description
*/
public string $name = 'default name',
protected Email $email = new Email(),
private DateTimeImmutable $birth_date,
private DateTimeImmutable $created_at = new DateTimeImmutable('now'),
private array $uses_constants = [self::DEFAULT_VALUE],
) {}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace PHP8;
class MixedType
{
public mixed $property;
public function getProperty(): mixed
{
return $this->property;
}
public function setProperty(mixed $value): void
{
$this->property = $value;
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace PHP8;
class StaticType
{
//Static is not allowed here
public static $property;
public function getProperty(): static
{
return $this->property;
}
public function setProperty($value): void
{
$this->property = $value;
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace PHP8;
use Foo\Date;
class UnionTypes
{
private string|null|false $property;
public function union(int|false $test): string|null|Date
{
}
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace PHP83;
class TypedConstants
{
const string NAME = 'typed';
const int COUNT = 42;
const string|int UNION = 'either';
const ?string NULLABLE = null;
const UNTYPED = 'no type';
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
class AsymmetricAccessor
{
private(set) \Pizza $pizza;
}

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
class AsymmetricPropertyPromotion
{
public function __construct(
protected(set) Pizza $pizza,
) {}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace PHP84;
interface HasId
{
public int $id { get; }
}
interface HasName
{
public string $name { get; set; }
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
class PropertyHook
{
private bool $modified = false;
/** @var string this is my property */
#[Property(new DateTimeImmutable())]
public string $example = 'default value' {
/** Not sure this works, but it gets */
#[Getter(new DateTimeImmutable())]
get {
if ($this->modified) {
return $this->foo . ' (modified)';
}
return $this->foo;
}
/** Not sure this works, but it sets */
#[Setter(new DateTimeImmutable())]
set(string|int $value) {
$this->foo = strtolower($value);
$this->modified = true;
}
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
class PropertyHook
{
private bool $modified = false;
/** @var string this is my property */
#[Property(new DateTimeImmutable())]
public private(set) string $example = 'default value' {
get {
if ($this->modified) {
return $this->foo . ' (modified)';
}
return $this->foo;
}
set(string|int $value) {
$this->foo = strtolower($value);
$this->modified = true;
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
class PropertyHook
{
private bool $modified = false;
/** @param string $example this is my property */
public function __construct(
/** @var string this is my property */
#[Property(new DateTimeImmutable())]
public string $example = 'default value' {
/** Not sure this works, but it gets */
#[Getter(new DateTimeImmutable())]
get {
if ($this->modified) {
return $this->foo . ' (modified)';
}
return $this->foo;
}
/** Not sure this works, but it sets */
#[Setter(new DateTimeImmutable())]
set(string|int $value) {
$this->foo = strtolower($value);
$this->modified = true;
}
}
)
{
}
}

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
class PropertyHookVirtual
{
/**
* A virtual property that composes a full name from first and last name
*/
public string $fullName {
// This is a virtual property with a getter
// It doesn't reference $this->fullName
get {
return $this->firstName . ' ' . $this->lastName;
}
}
/**
* A virtual property that decomposes a full name into first and last name
*/
public string $compositeName {
// This is a virtual property with a setter
// It doesn't reference $this->compositeName
set(string $value) {
[$this->firstName, $this->lastName] = explode(' ', $value, 2);
}
}
/**
* A virtual property with both getter and setter
*/
public string $completeFullName {
// Getter doesn't reference $this->completeFullName
get {
return $this->firstName . ' ' . $this->lastName;
}
// Setter doesn't reference $this->completeFullName
set(string $value) {
[$this->firstName, $this->lastName] = explode(' ', $value, 2);
}
}
/**
* A non-virtual property that references itself in its hook
*/
public string $nonVirtualName {
get {
return $this->nonVirtualName ?? $this->firstName;
}
set(string $value) {
$this->nonVirtualName = $value;
}
}
public function __construct(
private string $firstName = 'John',
private string $lastName = 'Doe'
) {
}
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2015-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
interface Packing
{
public function getName(): string;
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
/**
* This needs a docblock to separate from
* file docblock
*/
const OVEN_TEMPERATURE = 9001;
define('MAX_OVEN_TEMPERATURE', 9002);
/**
* Pizza base class
*/
class Pizza
{
/**
* The packaging method used to transport the pizza.
*/
const PACKAGING = 'box';
}

View File

@@ -0,0 +1,8 @@
<?php
function simpleFunction(array $options = []): void
{
return;
}
exit();