summaryrefslogtreecommitdiff
path: root/vendor/sebastian/code-unit/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sebastian/code-unit/src')
-rw-r--r--vendor/sebastian/code-unit/src/ClassMethodUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/ClassUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/CodeUnit.php445
-rw-r--r--vendor/sebastian/code-unit/src/CodeUnitCollection.php84
-rw-r--r--vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php55
-rw-r--r--vendor/sebastian/code-unit/src/FunctionUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/InterfaceMethodUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/InterfaceUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/Mapper.php414
-rw-r--r--vendor/sebastian/code-unit/src/TraitMethodUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/TraitUnit.php24
-rw-r--r--vendor/sebastian/code-unit/src/exceptions/Exception.php16
-rw-r--r--vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php16
-rw-r--r--vendor/sebastian/code-unit/src/exceptions/NoTraitException.php16
-rw-r--r--vendor/sebastian/code-unit/src/exceptions/ReflectionException.php16
15 files changed, 1230 insertions, 0 deletions
diff --git a/vendor/sebastian/code-unit/src/ClassMethodUnit.php b/vendor/sebastian/code-unit/src/ClassMethodUnit.php
new file mode 100644
index 000000000..f9ddac29e
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/ClassMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class ClassMethodUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true ClassMethodUnit $this
+ */
+ public function isClassMethod(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/ClassUnit.php b/vendor/sebastian/code-unit/src/ClassUnit.php
new file mode 100644
index 000000000..3ba0ee661
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/ClassUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class ClassUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true ClassUnit $this
+ */
+ public function isClass(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnit.php b/vendor/sebastian/code-unit/src/CodeUnit.php
new file mode 100644
index 000000000..9e5cceb35
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnit.php
@@ -0,0 +1,445 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function range;
+use function sprintf;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+
+/**
+ * @psalm-immutable
+ */
+abstract class CodeUnit
+{
+ /**
+ * @var string
+ */
+ private $name;
+
+ /**
+ * @var string
+ */
+ private $sourceFileName;
+
+ /**
+ * @var array
+ * @psalm-var list<int>
+ */
+ private $sourceLines;
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forClass(string $className): ClassUnit
+ {
+ self::ensureUserDefinedClass($className);
+
+ $reflector = self::reflectorForClass($className);
+
+ return new ClassUnit(
+ $className,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forClassMethod(string $className, string $methodName): ClassMethodUnit
+ {
+ self::ensureUserDefinedClass($className);
+
+ $reflector = self::reflectorForClassMethod($className, $methodName);
+
+ return new ClassMethodUnit(
+ $className . '::' . $methodName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $interfaceName
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forInterface(string $interfaceName): InterfaceUnit
+ {
+ self::ensureUserDefinedInterface($interfaceName);
+
+ $reflector = self::reflectorForClass($interfaceName);
+
+ return new InterfaceUnit(
+ $interfaceName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $interfaceName
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forInterfaceMethod(string $interfaceName, string $methodName): InterfaceMethodUnit
+ {
+ self::ensureUserDefinedInterface($interfaceName);
+
+ $reflector = self::reflectorForClassMethod($interfaceName, $methodName);
+
+ return new InterfaceMethodUnit(
+ $interfaceName . '::' . $methodName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $traitName
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forTrait(string $traitName): TraitUnit
+ {
+ self::ensureUserDefinedTrait($traitName);
+
+ $reflector = self::reflectorForClass($traitName);
+
+ return new TraitUnit(
+ $traitName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $traitName
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forTraitMethod(string $traitName, string $methodName): TraitMethodUnit
+ {
+ self::ensureUserDefinedTrait($traitName);
+
+ $reflector = self::reflectorForClassMethod($traitName, $methodName);
+
+ return new TraitMethodUnit(
+ $traitName . '::' . $methodName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param callable-string $functionName
+ *
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public static function forFunction(string $functionName): FunctionUnit
+ {
+ $reflector = self::reflectorForFunction($functionName);
+
+ if (!$reflector->isUserDefined()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a user-defined function',
+ $functionName
+ )
+ );
+ }
+
+ return new FunctionUnit(
+ $functionName,
+ $reflector->getFileName(),
+ range(
+ $reflector->getStartLine(),
+ $reflector->getEndLine()
+ )
+ );
+ }
+
+ /**
+ * @psalm-param list<int> $sourceLines
+ */
+ private function __construct(string $name, string $sourceFileName, array $sourceLines)
+ {
+ $this->name = $name;
+ $this->sourceFileName = $sourceFileName;
+ $this->sourceLines = $sourceLines;
+ }
+
+ public function name(): string
+ {
+ return $this->name;
+ }
+
+ public function sourceFileName(): string
+ {
+ return $this->sourceFileName;
+ }
+
+ /**
+ * @psalm-return list<int>
+ */
+ public function sourceLines(): array
+ {
+ return $this->sourceLines;
+ }
+
+ public function isClass(): bool
+ {
+ return false;
+ }
+
+ public function isClassMethod(): bool
+ {
+ return false;
+ }
+
+ public function isInterface(): bool
+ {
+ return false;
+ }
+
+ public function isInterfaceMethod(): bool
+ {
+ return false;
+ }
+
+ public function isTrait(): bool
+ {
+ return false;
+ }
+
+ public function isTraitMethod(): bool
+ {
+ return false;
+ }
+
+ public function isFunction(): bool
+ {
+ return false;
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws InvalidCodeUnitException
+ */
+ private static function ensureUserDefinedClass(string $className): void
+ {
+ try {
+ $reflector = new ReflectionClass($className);
+
+ if ($reflector->isInterface()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is an interface and not a class',
+ $className
+ )
+ );
+ }
+
+ if ($reflector->isTrait()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is a trait and not a class',
+ $className
+ )
+ );
+ }
+
+ if (!$reflector->isUserDefined()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a user-defined class',
+ $className
+ )
+ );
+ }
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @psalm-param class-string $interfaceName
+ *
+ * @throws InvalidCodeUnitException
+ */
+ private static function ensureUserDefinedInterface(string $interfaceName): void
+ {
+ try {
+ $reflector = new ReflectionClass($interfaceName);
+
+ if (!$reflector->isInterface()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not an interface',
+ $interfaceName
+ )
+ );
+ }
+
+ if (!$reflector->isUserDefined()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a user-defined interface',
+ $interfaceName
+ )
+ );
+ }
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @psalm-param class-string $traitName
+ *
+ * @throws InvalidCodeUnitException
+ */
+ private static function ensureUserDefinedTrait(string $traitName): void
+ {
+ try {
+ $reflector = new ReflectionClass($traitName);
+
+ if (!$reflector->isTrait()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a trait',
+ $traitName
+ )
+ );
+ }
+
+ // @codeCoverageIgnoreStart
+ if (!$reflector->isUserDefined()) {
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a user-defined trait',
+ $traitName
+ )
+ );
+ }
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private static function reflectorForClass(string $className): ReflectionClass
+ {
+ try {
+ return new ReflectionClass($className);
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private static function reflectorForClassMethod(string $className, string $methodName): ReflectionMethod
+ {
+ try {
+ return new ReflectionMethod($className, $methodName);
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @psalm-param callable-string $functionName
+ *
+ * @throws ReflectionException
+ */
+ private static function reflectorForFunction(string $functionName): ReflectionFunction
+ {
+ try {
+ return new ReflectionFunction($functionName);
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollection.php b/vendor/sebastian/code-unit/src/CodeUnitCollection.php
new file mode 100644
index 000000000..f53db8a12
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnitCollection.php
@@ -0,0 +1,84 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function array_merge;
+use function count;
+use Countable;
+use IteratorAggregate;
+
+final class CodeUnitCollection implements Countable, IteratorAggregate
+{
+ /**
+ * @psalm-var list<CodeUnit>
+ */
+ private $codeUnits = [];
+
+ /**
+ * @psalm-param list<CodeUnit> $items
+ */
+ public static function fromArray(array $items): self
+ {
+ $collection = new self;
+
+ foreach ($items as $item) {
+ $collection->add($item);
+ }
+
+ return $collection;
+ }
+
+ public static function fromList(CodeUnit ...$items): self
+ {
+ return self::fromArray($items);
+ }
+
+ private function __construct()
+ {
+ }
+
+ /**
+ * @psalm-return list<CodeUnit>
+ */
+ public function asArray(): array
+ {
+ return $this->codeUnits;
+ }
+
+ public function getIterator(): CodeUnitCollectionIterator
+ {
+ return new CodeUnitCollectionIterator($this);
+ }
+
+ public function count(): int
+ {
+ return count($this->codeUnits);
+ }
+
+ public function isEmpty(): bool
+ {
+ return empty($this->codeUnits);
+ }
+
+ public function mergeWith(self $other): self
+ {
+ return self::fromArray(
+ array_merge(
+ $this->asArray(),
+ $other->asArray()
+ )
+ );
+ }
+
+ private function add(CodeUnit $item): void
+ {
+ $this->codeUnits[] = $item;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php
new file mode 100644
index 000000000..bdc86d888
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use Iterator;
+
+final class CodeUnitCollectionIterator implements Iterator
+{
+ /**
+ * @psalm-var list<CodeUnit>
+ */
+ private $codeUnits;
+
+ /**
+ * @var int
+ */
+ private $position = 0;
+
+ public function __construct(CodeUnitCollection $collection)
+ {
+ $this->codeUnits = $collection->asArray();
+ }
+
+ public function rewind(): void
+ {
+ $this->position = 0;
+ }
+
+ public function valid(): bool
+ {
+ return isset($this->codeUnits[$this->position]);
+ }
+
+ public function key(): int
+ {
+ return $this->position;
+ }
+
+ public function current(): CodeUnit
+ {
+ return $this->codeUnits[$this->position];
+ }
+
+ public function next(): void
+ {
+ $this->position++;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/FunctionUnit.php b/vendor/sebastian/code-unit/src/FunctionUnit.php
new file mode 100644
index 000000000..df76cf195
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/FunctionUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class FunctionUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true FunctionUnit $this
+ */
+ public function isFunction(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php
new file mode 100644
index 000000000..fcd44f41a
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class InterfaceMethodUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true InterfaceMethod $this
+ */
+ public function isInterfaceMethod(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/InterfaceUnit.php b/vendor/sebastian/code-unit/src/InterfaceUnit.php
new file mode 100644
index 000000000..5cf585bfd
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/InterfaceUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class InterfaceUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true InterfaceUnit $this
+ */
+ public function isInterface(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/Mapper.php b/vendor/sebastian/code-unit/src/Mapper.php
new file mode 100644
index 000000000..a72b3b0dd
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/Mapper.php
@@ -0,0 +1,414 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function array_keys;
+use function array_merge;
+use function array_unique;
+use function array_values;
+use function class_exists;
+use function explode;
+use function function_exists;
+use function interface_exists;
+use function ksort;
+use function method_exists;
+use function sort;
+use function sprintf;
+use function str_replace;
+use function strpos;
+use function trait_exists;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+
+final class Mapper
+{
+ /**
+ * @psalm-return array<string,list<int>>
+ */
+ public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array
+ {
+ $result = [];
+
+ foreach ($codeUnits as $codeUnit) {
+ $sourceFileName = $codeUnit->sourceFileName();
+
+ if (!isset($result[$sourceFileName])) {
+ $result[$sourceFileName] = [];
+ }
+
+ $result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines());
+ }
+
+ foreach (array_keys($result) as $sourceFileName) {
+ $result[$sourceFileName] = array_values(array_unique($result[$sourceFileName]));
+
+ sort($result[$sourceFileName]);
+ }
+
+ ksort($result);
+
+ return $result;
+ }
+
+ /**
+ * @throws InvalidCodeUnitException
+ * @throws ReflectionException
+ */
+ public function stringToCodeUnits(string $unit): CodeUnitCollection
+ {
+ if (strpos($unit, '::') !== false) {
+ [$firstPart, $secondPart] = explode('::', $unit);
+
+ if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) {
+ return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart));
+ }
+
+ if ($this->isUserDefinedClass($firstPart)) {
+ if ($secondPart === '<public>') {
+ return $this->publicMethodsOfClass($firstPart);
+ }
+
+ if ($secondPart === '<!public>') {
+ return $this->protectedAndPrivateMethodsOfClass($firstPart);
+ }
+
+ if ($secondPart === '<protected>') {
+ return $this->protectedMethodsOfClass($firstPart);
+ }
+
+ if ($secondPart === '<!protected>') {
+ return $this->publicAndPrivateMethodsOfClass($firstPart);
+ }
+
+ if ($secondPart === '<private>') {
+ return $this->privateMethodsOfClass($firstPart);
+ }
+
+ if ($secondPart === '<!private>') {
+ return $this->publicAndProtectedMethodsOfClass($firstPart);
+ }
+
+ if ($this->isUserDefinedMethod($firstPart, $secondPart)) {
+ return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart));
+ }
+ }
+
+ if ($this->isUserDefinedInterface($firstPart)) {
+ return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart));
+ }
+
+ if ($this->isUserDefinedTrait($firstPart)) {
+ return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart));
+ }
+ } else {
+ if ($this->isUserDefinedClass($unit)) {
+ $units = [CodeUnit::forClass($unit)];
+
+ foreach ($this->reflectorForClass($unit)->getTraits() as $trait) {
+ if (!$trait->isUserDefined()) {
+ // @codeCoverageIgnoreStart
+ continue;
+ // @codeCoverageIgnoreEnd
+ }
+
+ $units[] = CodeUnit::forTrait($trait->getName());
+ }
+
+ return CodeUnitCollection::fromArray($units);
+ }
+
+ if ($this->isUserDefinedInterface($unit)) {
+ return CodeUnitCollection::fromList(CodeUnit::forInterface($unit));
+ }
+
+ if ($this->isUserDefinedTrait($unit)) {
+ return CodeUnitCollection::fromList(CodeUnit::forTrait($unit));
+ }
+
+ if ($this->isUserDefinedFunction($unit)) {
+ return CodeUnitCollection::fromList(CodeUnit::forFunction($unit));
+ }
+
+ $unit = str_replace('<extended>', '', $unit);
+
+ if ($this->isUserDefinedClass($unit)) {
+ return $this->classAndParentClassesAndTraits($unit);
+ }
+ }
+
+ throw new InvalidCodeUnitException(
+ sprintf(
+ '"%s" is not a valid code unit',
+ $unit
+ )
+ );
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function publicMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function publicAndProtectedMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function publicAndPrivateMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function protectedMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function protectedAndPrivateMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function privateMethodsOfClass(string $className): CodeUnitCollection
+ {
+ return $this->methodsOfClass($className, ReflectionMethod::IS_PRIVATE);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function methodsOfClass(string $className, int $filter): CodeUnitCollection
+ {
+ $units = [];
+
+ foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) {
+ if (!$method->isUserDefined()) {
+ continue;
+ }
+
+ $units[] = CodeUnit::forClassMethod($className, $method->getName());
+ }
+
+ return CodeUnitCollection::fromArray($units);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function classAndParentClassesAndTraits(string $className): CodeUnitCollection
+ {
+ $units = [CodeUnit::forClass($className)];
+
+ $reflector = $this->reflectorForClass($className);
+
+ foreach ($this->reflectorForClass($className)->getTraits() as $trait) {
+ if (!$trait->isUserDefined()) {
+ // @codeCoverageIgnoreStart
+ continue;
+ // @codeCoverageIgnoreEnd
+ }
+
+ $units[] = CodeUnit::forTrait($trait->getName());
+ }
+
+ while ($reflector = $reflector->getParentClass()) {
+ if (!$reflector->isUserDefined()) {
+ break;
+ }
+
+ $units[] = CodeUnit::forClass($reflector->getName());
+
+ foreach ($reflector->getTraits() as $trait) {
+ if (!$trait->isUserDefined()) {
+ // @codeCoverageIgnoreStart
+ continue;
+ // @codeCoverageIgnoreEnd
+ }
+
+ $units[] = CodeUnit::forTrait($trait->getName());
+ }
+ }
+
+ return CodeUnitCollection::fromArray($units);
+ }
+
+ /**
+ * @psalm-param class-string $className
+ *
+ * @throws ReflectionException
+ */
+ private function reflectorForClass(string $className): ReflectionClass
+ {
+ try {
+ return new ReflectionClass($className);
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function isUserDefinedFunction(string $functionName): bool
+ {
+ if (!function_exists($functionName)) {
+ return false;
+ }
+
+ try {
+ return (new ReflectionFunction($functionName))->isUserDefined();
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function isUserDefinedClass(string $className): bool
+ {
+ if (!class_exists($className)) {
+ return false;
+ }
+
+ try {
+ return (new ReflectionClass($className))->isUserDefined();
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function isUserDefinedInterface(string $interfaceName): bool
+ {
+ if (!interface_exists($interfaceName)) {
+ return false;
+ }
+
+ try {
+ return (new ReflectionClass($interfaceName))->isUserDefined();
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function isUserDefinedTrait(string $traitName): bool
+ {
+ if (!trait_exists($traitName)) {
+ return false;
+ }
+
+ try {
+ return (new ReflectionClass($traitName))->isUserDefined();
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function isUserDefinedMethod(string $className, string $methodName): bool
+ {
+ if (!class_exists($className)) {
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ if (!method_exists($className, $methodName)) {
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ try {
+ return (new ReflectionMethod($className, $methodName))->isUserDefined();
+ // @codeCoverageIgnoreStart
+ } catch (\ReflectionException $e) {
+ throw new ReflectionException(
+ $e->getMessage(),
+ (int) $e->getCode(),
+ $e
+ );
+ }
+ // @codeCoverageIgnoreEnd
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/TraitMethodUnit.php b/vendor/sebastian/code-unit/src/TraitMethodUnit.php
new file mode 100644
index 000000000..a58f7249f
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/TraitMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class TraitMethodUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true TraitMethodUnit $this
+ */
+ public function isTraitMethod(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/TraitUnit.php b/vendor/sebastian/code-unit/src/TraitUnit.php
new file mode 100644
index 000000000..abddfc112
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/TraitUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class TraitUnit extends CodeUnit
+{
+ /**
+ * @psalm-assert-if-true TraitUnit $this
+ */
+ public function isTrait(): bool
+ {
+ return true;
+ }
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/Exception.php b/vendor/sebastian/code-unit/src/exceptions/Exception.php
new file mode 100644
index 000000000..74d0eeef8
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php
new file mode 100644
index 000000000..60a3da82b
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class InvalidCodeUnitException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php
new file mode 100644
index 000000000..e9b9b9c7a
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class NoTraitException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php
new file mode 100644
index 000000000..232012783
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class ReflectionException extends RuntimeException implements Exception
+{
+}