Skip to content
Snippets Groups Projects
Commit 84acfadd authored by David Prévot's avatar David Prévot
Browse files

New upstream version 2.0.0

parents 7ba5bb02 a81fee9e
No related branches found
No related tags found
No related merge requests found
......@@ -6,75 +6,65 @@ on:
name: "CI"
permissions:
contents: read
jobs:
coding-guidelines:
name: "Coding Guidelines"
runs-on: "ubuntu-latest"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
name: Coding Guidelines
- name: "Run friendsofphp/php-cs-fixer"
run: "php7.4 ./tools/php-cs-fixer fix --diff-format=udiff --dry-run --show-progress=dots --using-cache=no --verbose"
type-checker:
name: "Type Checker"
runs-on: "ubuntu-latest"
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
- name: Checkout
uses: actions/checkout@v3
- name: "Update dependencies with composer"
run: "php7.4 ./tools/composer update --no-ansi --no-interaction --no-progress"
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
coverage: none
- name: "Run vimeo/psalm"
run: "php7.4 ./tools/psalm --config=.psalm/config.xml --no-progress --shepherd --show-info=false --stats"
- name: Run PHP-CS-Fixer
run: ./tools/php-cs-fixer fix --dry-run --show-progress=dots --using-cache=no --verbose
backward-compatibility:
name: Backward Compatibility
type-checker:
name: Type Checker
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
uses: actions/checkout@v3
- name: Install PHP with extensions
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
php-version: 8.1
coverage: none
extensions: intl
- name: Run roave/backward-compatibility-check
run: ./tools/roave-backward-compatibility-check --from=1.0.8
- name: Install dependencies with Composer
run: ./tools/composer update --no-interaction --no-ansi --no-progress
- name: Run Psalm
run: ./tools/psalm --config=.psalm/config.xml --no-progress --shepherd --show-info=false --stats
tests:
name: "Tests"
name: Tests
runs-on: "ubuntu-latest"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version:
- "7.3"
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
uses: "actions/checkout@v3"
- name: "Install PHP with extensions"
uses: "shivammathur/setup-php@v2"
......@@ -82,20 +72,21 @@ jobs:
php-version: "${{ matrix.php-version }}"
coverage: "pcov"
- name: "Cache dependencies installed with composer"
uses: "actions/cache@v1"
- name: "Cache dependencies installed with Composer"
uses: "actions/cache@v2"
with:
path: "~/.composer/cache"
key: "php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.json') }}"
restore-keys: "php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-"
- name: "Install dependencies with composer"
- name: "Install dependencies with Composer"
run: "./tools/composer update --no-ansi --no-interaction --no-progress"
- name: "Run tests with phpunit/phpunit"
- name: "Run tests with PHPUnit"
run: "vendor/bin/phpunit --coverage-clover=coverage.xml"
- name: "Send code coverage report to Codecov.io"
env:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"
run: "bash <(curl -s https://codecov.io/bash) || true"
/.idea
/.php_cs
/.php_cs.cache
/.phpunit.result.cache
/.php-cs-fixer.php
/.php-cs-fixer.cache
/.phpunit.cache
/composer.lock
/vendor
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="php-cs-fixer" version="^2.16" installed="2.16.4" location="./tools/php-cs-fixer" copy="true"/>
<phar name="psalm" version="^4.0" installed="4.0.1" location="./tools/psalm" copy="true"/>
<phar name="roave/backwardcompatibilitycheck" version="^5.0.0" installed="5.0.0" location="./tools/roave-backward-compatibility-check" copy="true"/>
<phar name="infection" version="^0.16.3" installed="0.18.2" location="./tools/infection" copy="true"/>
<phar name="php-cs-fixer" version="^3.0" installed="3.14.3" location="./tools/php-cs-fixer" copy="true"/>
<phar name="psalm" version="^5.0" installed="5.6.0" location="./tools/psalm" copy="true"/>
<phar name="infection" version="^0.26.1" installed="0.26.18" location="./tools/infection" copy="true"/>
<phar name="composer" version="^2.0.3" installed="2.5.1" location="./tools/composer" copy="true"/>
</phive>
......@@ -11,19 +11,22 @@ EOF;
$finder = PhpCsFixer\Finder::create()
->files()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests');
->in(__DIR__ . '/tests')
;
return PhpCsFixer\Config::create()
->setFinder($finder)
$config = new PhpCsFixer\Config;
$config->setFinder($finder)
->setRiskyAllowed(true)
->setRules([
'align_multiline_comment' => true,
'array_indentation' => true,
'array_push' => true,
'array_syntax' => ['syntax' => 'short'],
'backtick_to_shell_exec' => true,
'binary_operator_spaces' => [
'operators' => [
'=' => 'align',
'=>' => 'align',
'=' => 'align_single_space_minimal',
'=>' => 'align_single_space_minimal',
],
],
'blank_line_after_namespace' => true,
......@@ -32,9 +35,12 @@ return PhpCsFixer\Config::create()
'break',
'continue',
'declare',
'default',
'do',
'exit',
'for',
'foreach',
'goto',
'if',
'include',
'include_once',
......@@ -48,49 +54,90 @@ return PhpCsFixer\Config::create()
'yield',
],
],
'braces' => true,
'braces' => [
'position_after_anonymous_constructs' => 'next',
],
'cast_spaces' => true,
'class_attributes_separation' => ['elements' => ['const', 'method', 'property']],
'class_attributes_separation' => [
'elements' => [
'const' => 'one',
'method' => 'one',
'property' => 'only_if_meta'
]
],
'class_definition' => true,
'clean_namespace' => true,
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
'combine_nested_dirname' => true,
'compact_nullable_typehint' => true,
'concat_space' => ['spacing' => 'one'],
'constant_case' => true,
'declare_equal_normalize' => ['space' => 'none'],
'declare_strict_types' => true,
'dir_constant' => true,
'echo_tag_syntax' => true,
'elseif' => true,
'encoding' => true,
'ereg_to_preg' => true,
'explicit_indirect_variable' => true,
'explicit_string_variable' => true,
'fopen_flag_order' => true,
'full_opening_tag' => true,
'fully_qualified_strict_types' => true,
'function_declaration' => true,
'function_to_constant' => true,
'function_typehint_space' => true,
'get_class_to_class_keyword' => true,
'global_namespace_import' => [
'import_classes' => true,
'import_constants' => true,
'import_functions' => true,
],
'header_comment' => ['header' => $header, 'separate' => 'none'],
'heredoc_to_nowdoc' => true,
'implode_call' => true,
'include' => true,
'increment_style' => [
'style' => PhpCsFixer\Fixer\Operator\IncrementStyleFixer::STYLE_POST,
],
'indentation_type' => true,
'is_null' => true,
'lambda_not_used_import' => true,
'line_ending' => true,
'list_syntax' => ['syntax' => 'short'],
'logical_operators' => true,
'lowercase_cast' => true,
'lowercase_constants' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'method_argument_space' => ['ensure_fully_multiline' => true],
'magic_method_casing' => true,
'method_argument_space' => [
'on_multiline' => 'ensure_fully_multiline',
],
'modernize_types_casting' => true,
'multiline_comment_opening_closing' => true,
'multiline_whitespace_before_semicolons' => true,
'native_constant_invocation' => false,
'native_function_casing' => false,
'native_function_invocation' => false,
'new_with_braces' => false,
'native_function_invocation' => [
'include' => [
'@internal',
],
],
'native_function_type_declaration_casing' => true,
'new_with_braces' => [
'named_class' => false,
'anonymous_class' => false,
],
'no_alias_functions' => true,
'no_alias_language_construct_call' => true,
'no_alternative_syntax' => true,
'no_binary_string' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_blank_lines_before_namespace' => true,
'no_break_comment' => true,
'no_closing_tag' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
......@@ -104,31 +151,38 @@ return PhpCsFixer\Config::create()
'no_null_property_initialization' => true,
'no_php4_constructor' => true,
'no_short_bool_cast' => true,
'no_short_echo_tag' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_after_function_name' => true,
'no_spaces_around_offset' => true,
'no_spaces_inside_parenthesis' => true,
'no_superfluous_elseif' => true,
'no_superfluous_phpdoc_tags' => [
'allow_mixed' => true,
],
'no_trailing_comma_in_list_call' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_comma_in_singleline' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'no_trailing_whitespace_in_string' => true,
'no_unneeded_control_parentheses' => true,
'no_unneeded_curly_braces' => true,
'no_unneeded_final_method' => true,
'no_unneeded_import_alias' => true,
'no_unreachable_default_argument_value' => true,
'no_unset_cast' => true,
'no_unset_on_property' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'no_useless_sprintf' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'non_printable_character' => true,
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'operator_linebreak' => [
'only_booleans' => true,
'position' => 'end',
],
'ordered_class_elements' => [
'order' => [
'use_trait',
......@@ -164,42 +218,83 @@ return PhpCsFixer\Config::create()
'direction' => 'ascend',
'order' => 'alpha',
],
'ordered_traits' => true,
'php_unit_set_up_tear_down_visibility' => true,
'php_unit_test_case_static_method_calls' => [
'call_type' => 'this',
],
'phpdoc_add_missing_param_annotation' => false,
'phpdoc_align' => true,
'phpdoc_annotation_without_dot' => true,
'phpdoc_indent' => true,
'phpdoc_inline_tag_normalizer' => true,
'phpdoc_no_access' => true,
'phpdoc_no_alias_tag' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_order' => true,
'phpdoc_order_by_value' => [
'annotations' => [
'covers',
'dataProvider',
'throws',
'uses',
],
],
'phpdoc_return_self_reference' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => true,
'phpdoc_tag_casing' => true,
'phpdoc_tag_type' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_trim_consecutive_blank_line_separation' => true,
'phpdoc_types' => ['groups' => ['simple', 'meta']],
'phpdoc_types_order' => true,
'phpdoc_var_annotation_correct_order' => true,
'phpdoc_var_without_name' => true,
'pow_to_exponentiation' => true,
'protected_to_private' => true,
'return_assignment' => true,
'return_type_declaration' => ['space_before' => 'none'],
'self_accessor' => true,
'self_static_accessor' => true,
'semicolon_after_instruction' => true,
'set_type_to_cast' => true,
'short_scalar_cast' => true,
'simple_to_complex_string_variable' => true,
'simplified_null_return' => false,
'single_blank_line_at_eof' => true,
'single_class_element_per_statement' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_quote' => true,
'single_space_after_construct' => true,
'single_trait_insert_per_statement' => true,
'space_after_semicolon' => true,
'standardize_increment' => true,
'standardize_not_equals' => true,
'static_lambda' => true,
'strict_param' => true,
'string_line_ending' => true,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'switch_continue_to_break' => true,
'ternary_operator_spaces' => true,
'ternary_to_elvis_operator' => true,
'ternary_to_null_coalescing' => true,
'trailing_comma_in_multiline_array' => true,
'trailing_comma_in_multiline' => [
'elements' => [
'arrays'
]
],
'trim_array_spaces' => true,
'types_spaces' => [
'space' => 'none',
],
'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => [
......@@ -211,3 +306,5 @@ return PhpCsFixer\Config::create()
'void_return' => true,
'whitespace_after_comma_in_array' => true,
]);
return $config;
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
<files psalm-version="dev-master@">
<file src="src/CodeUnitCollection.php">
<ArgumentTypeCoercion occurrences="1">
<code>$codeUnits</code>
</ArgumentTypeCoercion>
</file>
<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>
<ArgumentTypeCoercion occurrences="9">
<code>$firstPart</code>
<code>$firstPart</code>
<code>$firstPart</code>
......@@ -17,7 +16,6 @@
<code>$unit</code>
<code>$unit</code>
<code>$unit</code>
<code>$unit</code>
</ArgumentTypeCoercion>
</file>
</files>
<?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"
......
......@@ -2,6 +2,18 @@
All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [2.0.0] - 2023-02-03
### Added
* Added `SebastianBergmann\CodeUnit\FileUnit` value object that represents a sourcecode file
### Removed
* `SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray()` has been removed
* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer supports `ClassName<*>`
* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0
## [1.0.8] - 2020-10-26
### Fixed
......@@ -54,6 +66,7 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
* Initial release
[2.0.0]: https://github.com/sebastianbergmann/code-unit/compare/1.0.8...2.0.0
[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
......
sebastian/code-unit
BSD 3-Clause License
Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
Copyright (c) 2020-2023, Sebastian Bergmann
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
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.
1. 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.
2. 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.
3. Neither the name of the copyright holder nor the names of its
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.
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 HOLDER 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.
[![Latest Stable Version](https://poser.pugx.org/sebastian/code-unit/v/stable.png)](https://packagist.org/packages/sebastian/code-unit)
[![CI Status](https://github.com/sebastianbergmann/code-unit/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/code-unit/actions)
[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/code-unit/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/code-unit)
[![codecov](https://codecov.io/gh/sebastianbergmann/code-unit/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/code-unit)
# sebastian/code-unit
Collection of value objects that represent the PHP code units.
......
# Security Policy
This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver.
**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.**
## Security Contact Information
After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`.
......@@ -22,10 +22,6 @@
<arg value="update"/>
<arg value="--force-accept-unsigned"/>
</exec>
<exec executable="${basedir}/tools/composer" taskname="composer">
<arg value="self-update"/>
</exec>
</target>
</project>
......@@ -16,14 +16,14 @@
},
"prefer-stable": true,
"require": {
"php": ">=7.3"
"php": ">=8.1"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
"phpunit/phpunit": "^10.0"
},
"config": {
"platform": {
"php": "7.3.0"
"php": "8.1.0"
},
"optimize-autoloader": true,
"sort-packages": true
......@@ -44,7 +44,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
"dev-main": "2.0-dev"
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
bootstrap="vendor/autoload.php"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
cacheDirectory=".phpunit.cache"
executionOrder="depends,defects"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
requireCoverageMetadata="true"
beStrictAboutCoverageMetadata="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="true"
verbose="true">
colors="true">
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
<directory>tests/unit</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
......
......@@ -9,6 +9,10 @@
*/
namespace SebastianBergmann\CodeUnit;
use function count;
use function file;
use function file_exists;
use function is_readable;
use function range;
use function sprintf;
use ReflectionClass;
......@@ -20,21 +24,13 @@ use ReflectionMethod;
*/
abstract class CodeUnit
{
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $sourceFileName;
private readonly string $name;
private readonly string $sourceFileName;
/**
* @var array
* @psalm-var list<int>
*/
private $sourceLines;
private readonly array $sourceLines;
/**
* @psalm-param class-string $className
......@@ -80,6 +76,23 @@ abstract class CodeUnit
);
}
/**
* @throws InvalidCodeUnitException
*/
public static function forFileWithAbsolutePath(string $path): FileUnit
{
self::ensureFileExistsAndIsReadable($path);
return new FileUnit(
$path,
$path,
range(
1,
count(file($path))
)
);
}
/**
* @psalm-param class-string $interfaceName
*
......@@ -260,6 +273,26 @@ abstract class CodeUnit
return false;
}
public function isFile(): bool
{
return false;
}
/**
* @throws InvalidCodeUnitException
*/
private static function ensureFileExistsAndIsReadable(string $path): void
{
if (!(file_exists($path) && is_readable($path))) {
throw new InvalidCodeUnitException(
sprintf(
'File "%s" does not exist or is not readable',
$path
)
);
}
}
/**
* @psalm-param class-string $className
*
......@@ -300,7 +333,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -338,7 +371,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -376,7 +409,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -396,7 +429,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -416,7 +449,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -436,7 +469,7 @@ abstract class CodeUnit
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......
......@@ -14,34 +14,29 @@ use function count;
use Countable;
use IteratorAggregate;
/**
* @template-implements IteratorAggregate<int, CodeUnit>
*
* @psalm-immutable
*/
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);
}
private readonly array $codeUnits;
return $collection;
}
public static function fromList(CodeUnit ...$items): self
public static function fromList(CodeUnit ...$codeUnits): self
{
return self::fromArray($items);
return new self($codeUnits);
}
private function __construct()
/**
* @psalm-param list<CodeUnit> $codeUnits
*/
private function __construct(array $codeUnits)
{
$this->codeUnits = $codeUnits;
}
/**
......@@ -69,16 +64,11 @@ final class CodeUnitCollection implements Countable, IteratorAggregate
public function mergeWith(self $other): self
{
return self::fromArray(
return new self(
array_merge(
$this->asArray(),
$other->asArray()
)
);
}
private function add(CodeUnit $item): void
{
$this->codeUnits[] = $item;
}
}
......@@ -11,17 +11,16 @@ namespace SebastianBergmann\CodeUnit;
use Iterator;
/**
* @template-implements Iterator<int, CodeUnit>
*/
final class CodeUnitCollectionIterator implements Iterator
{
/**
* @psalm-var list<CodeUnit>
*/
private $codeUnits;
/**
* @var int
*/
private $position = 0;
private array $codeUnits;
private int $position = 0;
public function __construct(CodeUnitCollection $collection)
{
......
......@@ -7,10 +7,18 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeUnit\Fixture;
namespace SebastianBergmann\CodeUnit;
use Exception;
class Issue5Exception extends Exception
/**
* @psalm-immutable
*/
final class FileUnit extends CodeUnit
{
/**
* @psalm-assert-if-true FileUnit $this
*/
public function isFile(): bool
{
return true;
}
}
......@@ -21,8 +21,7 @@ use function ksort;
use function method_exists;
use function sort;
use function sprintf;
use function str_replace;
use function strpos;
use function str_contains;
use function trait_exists;
use ReflectionClass;
use ReflectionFunction;
......@@ -64,41 +63,15 @@ final class Mapper
*/
public function stringToCodeUnits(string $unit): CodeUnitCollection
{
if (strpos($unit, '::') !== false) {
if (str_contains($unit, '::')) {
[$firstPart, $secondPart] = explode('::', $unit);
if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) {
if ($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->isUserDefinedMethod($firstPart, $secondPart)) {
return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart));
}
if ($this->isUserDefinedInterface($firstPart)) {
......@@ -122,7 +95,7 @@ final class Mapper
$units[] = CodeUnit::forTrait($trait->getName());
}
return CodeUnitCollection::fromArray($units);
return CodeUnitCollection::fromList(...$units);
}
if ($this->isUserDefinedInterface($unit)) {
......@@ -136,12 +109,6 @@ final class Mapper
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(
......@@ -152,128 +119,6 @@ final class Mapper
);
}
/**
* @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
*
......@@ -287,7 +132,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -309,7 +154,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -331,7 +176,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -353,7 +198,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -375,7 +220,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......@@ -405,7 +250,7 @@ final class Mapper
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e->getCode(),
$e
);
}
......
......@@ -7,17 +7,22 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeUnit\Fixture
{
namespace SebastianBergmann\CodeUnit\Fixture {
function f(): int
{
return 1;
}
}
namespace
{
namespace {
function f(): int
{
return 1;
}
class file
{
public function test(): void
{
}
}
}
......@@ -12,21 +12,20 @@ namespace SebastianBergmann\CodeUnit;
use function range;
use function realpath;
use Exception;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\UsesClass;
use PHPUnit\Framework\TestCase;
use SebastianBergmann\CodeUnit\Fixture\FixtureClass;
use SebastianBergmann\CodeUnit\Fixture\FixtureInterface;
use SebastianBergmann\CodeUnit\Fixture\FixtureTrait;
/**
* @covers \SebastianBergmann\CodeUnit\ClassMethodUnit
* @covers \SebastianBergmann\CodeUnit\CodeUnit
*
* @uses \SebastianBergmann\CodeUnit\CodeUnitCollection
* @uses \SebastianBergmann\CodeUnit\CodeUnitCollectionIterator
* @uses \SebastianBergmann\CodeUnit\Mapper
*
* @testdox ClassMethodUnit
*/
#[CoversClass(ClassMethodUnit::class)]
#[CoversClass(CodeUnit::class)]
#[UsesClass(CodeUnitCollection::class)]
#[UsesClass(CodeUnitCollectionIterator::class)]
#[UsesClass(Mapper::class)]
#[TestDox('ClassMethodUnit')]
final class ClassMethodUnitTest extends TestCase
{
public function testCanBeCreatedFromNameOfUserDefinedClassAndMethodName(): void
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment