summaryrefslogtreecommitdiff
path: root/vendor/sebastian/code-unit
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2022-03-22 12:24:31 +0300
committerAndrew Dolgov <[email protected]>2022-03-22 12:24:31 +0300
commit1c4f7ab3b838b23afb2ee4dab14acbf75956e952 (patch)
tree0a19274107d717efe92d2c0376cd3105fead5a11 /vendor/sebastian/code-unit
parent711662948768492e8d05b778a7d80eacaec368d2 (diff)
* add phpunit as a dev dependency
* add some basic tests for UrlHelper::rewrite_relative() * fix UrlHelper::rewrite_relative() to work better on non-absolute relative URL paths
Diffstat (limited to 'vendor/sebastian/code-unit')
-rw-r--r--vendor/sebastian/code-unit/.psalm/baseline.xml23
-rw-r--r--vendor/sebastian/code-unit/.psalm/config.xml16
-rw-r--r--vendor/sebastian/code-unit/ChangeLog.md65
-rw-r--r--vendor/sebastian/code-unit/LICENSE33
-rw-r--r--vendor/sebastian/code-unit/README.md17
-rw-r--r--vendor/sebastian/code-unit/composer.json50
-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
21 files changed, 1434 insertions, 0 deletions
diff --git a/vendor/sebastian/code-unit/.psalm/baseline.xml b/vendor/sebastian/code-unit/.psalm/baseline.xml
new file mode 100644
index 000000000..e44889190
--- /dev/null
+++ b/vendor/sebastian/code-unit/.psalm/baseline.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
+ <file src="src/Mapper.php">
+ <ArgumentTypeCoercion occurrences="16">
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$firstPart</code>
+ <code>$secondPart</code>
+ <code>$unit</code>
+ <code>$unit</code>
+ <code>$unit</code>
+ <code>$unit</code>
+ <code>$unit</code>
+ <code>$unit</code>
+ </ArgumentTypeCoercion>
+ </file>
+</files>
diff --git a/vendor/sebastian/code-unit/.psalm/config.xml b/vendor/sebastian/code-unit/.psalm/config.xml
new file mode 100644
index 000000000..a39e9a4c3
--- /dev/null
+++ b/vendor/sebastian/code-unit/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+ totallyTyped="true"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="https://getpsalm.org/schema/config"
+ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+ resolveFromConfigFile="false"
+ errorBaseline=".psalm/baseline.xml"
+>
+ <projectFiles>
+ <directory name="src" />
+ <ignoreFiles>
+ <directory name="vendor" />
+ </ignoreFiles>
+ </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/code-unit/ChangeLog.md b/vendor/sebastian/code-unit/ChangeLog.md
new file mode 100644
index 000000000..0978e651e
--- /dev/null
+++ b/vendor/sebastian/code-unit/ChangeLog.md
@@ -0,0 +1,65 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [1.0.8] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\CodeUnit\Exception` now correctly extends `\Throwable`
+
+## [1.0.7] - 2020-10-02
+
+### Fixed
+
+* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer attempts to create `CodeUnit` objects for code units that are not declared in userland
+
+## [1.0.6] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [1.0.5] - 2020-06-26
+
+### Fixed
+
+* [#3](https://github.com/sebastianbergmann/code-unit/issues/3): Regression in 1.0.4
+
+## [1.0.4] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [1.0.3] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [1.0.2] - 2020-04-30
+
+### Fixed
+
+* `Mapper::stringToCodeUnits()` raised the wrong exception for `Class::method` when a class named `Class` exists but does not have a method named `method`
+
+## [1.0.1] - 2020-04-27
+
+### Fixed
+
+* [#2](https://github.com/sebastianbergmann/code-unit/issues/2): `Mapper::stringToCodeUnits()` breaks when `ClassName<extended>` is used for class that extends built-in class
+
+## [1.0.0] - 2020-03-30
+
+* Initial release
+
+[1.0.8]: https://github.com/sebastianbergmann/code-unit/compare/1.0.7...1.0.8
+[1.0.7]: https://github.com/sebastianbergmann/code-unit/compare/1.0.6...1.0.7
+[1.0.6]: https://github.com/sebastianbergmann/code-unit/compare/1.0.5...1.0.6
+[1.0.5]: https://github.com/sebastianbergmann/code-unit/compare/1.0.4...1.0.5
+[1.0.4]: https://github.com/sebastianbergmann/code-unit/compare/1.0.3...1.0.4
+[1.0.3]: https://github.com/sebastianbergmann/code-unit/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/sebastianbergmann/code-unit/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/sebastianbergmann/code-unit/compare/1.0.0...1.0.1
+[1.0.0]: https://github.com/sebastianbergmann/code-unit/compare/530c3900e5db9bcb8516da545bef0d62536cedaa...1.0.0
diff --git a/vendor/sebastian/code-unit/LICENSE b/vendor/sebastian/code-unit/LICENSE
new file mode 100644
index 000000000..b99bc8ac4
--- /dev/null
+++ b/vendor/sebastian/code-unit/LICENSE
@@ -0,0 +1,33 @@
+sebastian/code-unit
+
+Copyright (c) 2020, Sebastian Bergmann <[email protected]>.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of Sebastian Bergmann nor the names of his
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/sebastian/code-unit/README.md b/vendor/sebastian/code-unit/README.md
new file mode 100644
index 000000000..d20227a9b
--- /dev/null
+++ b/vendor/sebastian/code-unit/README.md
@@ -0,0 +1,17 @@
+# sebastian/code-unit
+
+Collection of value objects that represent the PHP code units.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/code-unit
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/code-unit
+```
diff --git a/vendor/sebastian/code-unit/composer.json b/vendor/sebastian/code-unit/composer.json
new file mode 100644
index 000000000..5b86ec589
--- /dev/null
+++ b/vendor/sebastian/code-unit/composer.json
@@ -0,0 +1,50 @@
+{
+ "name": "sebastian/code-unit",
+ "description": "Collection of value objects that represent the PHP code units",
+ "type": "library",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "license": "BSD-3-Clause",
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues"
+ },
+ "prefer-stable": true,
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "config": {
+ "platform": {
+ "php": "7.3.0"
+ },
+ "optimize-autoloader": true,
+ "sort-packages": true
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "autoload-dev": {
+ "classmap": [
+ "tests/_fixture"
+ ],
+ "files": [
+ "tests/_fixture/file_with_multiple_code_units.php",
+ "tests/_fixture/function.php"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
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
+{
+}