diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..8b51ad81f07033854f0d5b9fb36b8d8da032cf94 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contributing to `sebastian/recursion-context` + +## Welcome! + +We look forward to your contributions! Here are some examples how you can contribute: + +* [Report a bug](https://github.com/sebastianbergmann/recursion-context/issues/new) +* [Send a pull request to fix a bug](https://github.com/sebastianbergmann/recursion-context/pulls) + +Please do not send pull requests that expand the scope of this project (see below). + + +## Any contributions you make will be under the BSD-3-Clause License + +When you submit code changes, your submissions are understood to be under the same [BSD-3-Clause License](https://github.com/sebastianbergmann/recursion-context/blob/main/LICENSE) that covers the project. By contributing to this project, you agree that your contributions will be licensed under its BSD-3-Clause License. + + +## Write bug reports with detail, background, and sample code + +[This is an example](https://github.com/sebastianbergmann/phpunit/issues/4376) of a bug report I wrote, and I think it's not too bad. + +In your bug report, please provide the following: + +* A quick summary and/or background +* Steps to reproduce + * Be specific! + * Give sample code if you can. +* What you expected would happen +* What actually happens +* Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + +Please post code and output as text ([using proper markup](https://guides.github.com/features/mastering-markdown/)). Do not post screenshots of code or output. + + +## Workflow for Pull Requests + +1. Fork the repository. +2. Create your branch from the oldest branch that is affected by the bug you plan to fix. +3. Implement your change and add tests for it. +4. Ensure the test suite passes. +5. Ensure the code complies with our coding guidelines (see below). +6. Send that pull request! + +Please make sure you have [set up your username and email address](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) for use with Git. Strings such as `silly nick name <root@localhost>` look really stupid in the commit history of a project. + +We encourage you to [sign your Git commits with your GPG key](https://docs.github.com/en/github/authenticating-to-github/signing-commits). + + +## Development + +This project uses [PHPUnit](https://phpunit.de/) for testing: + +```shell +./vendor/bin/phpunit +``` + +This project uses [PHPStan](https://phpstan.org/) for static analysis: + +```shell +./tools/phpstan +``` + +This project uses [PHP-CS-Fixer](https://cs.symfony.com/) to enforce coding guidelines: + +```shell +./tools/php-cs-fixer fix +``` + +The commands shown above require an autoloader script at `vendor/autoload.php`. This can be generated like so: + +```shell +./tools/composer dump-autoload +``` + +Please understand that we will not accept a pull request when its changes violate this project's coding guidelines or break the test suite. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a608e898134fcf3c75c08a61404edd959ef8a3b..4eb5a7dcd80fa09a22d4b541d854d2b99e58eeb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: name: "CI" env: - COMPOSER_ROOT_VERSION: "6.0-dev" + COMPOSER_ROOT_VERSION: "7.0.x-dev" permissions: contents: read @@ -61,9 +61,9 @@ jobs: fail-fast: false matrix: php-version: - - "8.2" - "8.3" - "8.4" + - "8.5" steps: - name: "Checkout" @@ -73,15 +73,21 @@ jobs: uses: "shivammathur/setup-php@v2" with: php-version: "${{ matrix.php-version }}" - coverage: "pcov" + coverage: "xdebug" - name: "Install dependencies with Composer" run: "./tools/composer update --no-ansi --no-interaction --no-progress" - name: "Run tests with PHPUnit" - run: "vendor/bin/phpunit --coverage-clover=coverage.xml" + run: "vendor/bin/phpunit --log-junit junit.xml --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" + - name: Upload test results to Codecov.io + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Upload code coverage data to Codecov.io + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.phive/phars.xml b/.phive/phars.xml index 4817da71b394359dd9a4e623de1ab849dab53d4c..e52e2ca21d6d97895edc3e9af711db6c5ec31b5d 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <phive xmlns="https://phar.io/phive"> - <phar name="php-cs-fixer" version="^3.59" installed="3.59.3" location="./tools/php-cs-fixer" copy="true"/> - <phar name="composer" version="^2.7" installed="2.7.7" location="./tools/composer" copy="true"/> - <phar name="phpstan" version="^1.11" installed="1.11.5" location="./tools/phpstan" copy="true"/> + <phar name="php-cs-fixer" version="^3.64" installed="3.68.0" location="./tools/php-cs-fixer" copy="true"/> + <phar name="composer" version="^2.8" installed="2.8.4" location="./tools/composer" copy="true"/> + <phar name="phpstan" version="^2.0" installed="2.1.1" location="./tools/phpstan" copy="true"/> </phive> diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 7d14230ebdf2aa5fcb86a467e62c2db119f0643c..74ac4bd7c5e77d5c652fbdf47983a70220933823 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -99,7 +99,7 @@ $config->setFinder($finder) 'explicit_string_variable' => true, 'fopen_flag_order' => true, 'full_opening_tag' => true, - 'fully_qualified_strict_types' => true, + 'fully_qualified_strict_types' => ['import_symbols' => true], 'function_declaration' => true, 'function_to_constant' => true, 'get_class_to_class_keyword' => true, @@ -135,7 +135,7 @@ $config->setFinder($finder) 'modernize_types_casting' => true, 'multiline_comment_opening_closing' => true, 'multiline_whitespace_before_semicolons' => true, - 'native_constant_invocation' => false, + 'native_constant_invocation' => true, 'native_function_casing' => false, 'native_function_invocation' => [ 'include' => [ @@ -158,7 +158,23 @@ $config->setFinder($finder) 'no_empty_comment' => true, 'no_empty_phpdoc' => true, 'no_empty_statement' => true, - 'no_extra_blank_lines' => true, + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'attribute', + 'break', + 'case', + 'continue', + 'curly_brace_block', + 'default', + 'extra', + 'parenthesis_brace_block', + 'return', + 'square_brace_block', + 'switch', + 'throw', + 'use', + ], + ], 'no_homoglyph_names' => true, 'no_leading_import_slash' => true, 'no_leading_namespace_whitespace' => true, @@ -197,6 +213,7 @@ $config->setFinder($finder) 'no_whitespace_in_blank_line' => true, 'non_printable_character' => true, 'normalize_index_brace' => true, + 'nullable_type_declaration_for_default_null_value' => true, 'object_operator_without_whitespace' => true, 'octal_notation' => true, 'operator_linebreak' => [ @@ -340,6 +357,8 @@ $config->setFinder($finder) 'whitespace_after_comma_in_array' => true, ]); -$config->setCacheFile(__DIR__ . '/.php-cs-fixer.cache/' . sha1(@trim((string) @shell_exec('git rev-parse --abbrev-ref HEAD')))); +$config->setCacheFile(__DIR__ . '/.php-cs-fixer.cache/' . json_decode((string) @file_get_contents('composer.json'), true)["extra"]["branch-alias"]["dev-main"] ?? 'unknown'); + +$config->setParallelConfig(\PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()); return $config; diff --git a/ChangeLog.md b/ChangeLog.md index 0fc1698236bbf9b6df3eec771e192a7616771aa3..53b640a944265822de81b8c515ea98ccd9e9f978 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,12 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. +## [7.0.0] - 2025-02-07 + +### Removed + +* This component is no longer supported on PHP 8.2 + ## [6.0.2] - 2024-07-03 ### Changed @@ -57,6 +63,7 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt * Tests etc. are now ignored for archive exports +[7.0.0]: https://github.com/sebastianbergmann/recursion-context/compare/6.0...7.0.0 [6.0.2]: https://github.com/sebastianbergmann/recursion-context/compare/6.0.1...6.0.2 [6.0.1]: https://github.com/sebastianbergmann/recursion-context/compare/6.0.0...6.0.1 [6.0.0]: https://github.com/sebastianbergmann/recursion-context/compare/5.0...6.0.0 diff --git a/LICENSE b/LICENSE index 5b4705a48d71526773da1aed0ce84464e4c94880..c5268a9168f8acfd38250813f0565f9792227c83 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2002-2024, Sebastian Bergmann +Copyright (c) 2002-2025, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 8137f1aea1a16746749a8e2de0dfe77205f59027..f1d87b6142f7a731714a76c258e053cc070734b7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[](https://packagist.org/packages/sebastian/recursion-context) +[](https://packagist.org/packages/sebastian/recursion-context) [](https://github.com/sebastianbergmann/recursion-context/actions) [](https://codecov.io/gh/sebastianbergmann/recursion-context) diff --git a/composer.json b/composer.json index 94e5be7cd4acf52bf7b64c40cdf4c0051f37d663..f37a207b384557ab327a8667781a9fb1cd725399 100644 --- a/composer.json +++ b/composer.json @@ -24,16 +24,16 @@ "prefer-stable": true, "config": { "platform": { - "php": "8.2.0" + "php": "8.3.0" }, "optimize-autoloader": true, "sort-packages": true }, "require": { - "php": ">=8.2" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^12.0" }, "autoload": { "classmap": [ @@ -42,7 +42,7 @@ }, "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } } } diff --git a/phpstan.neon b/phpstan.neon index 08566d07a495531f34abd8522c67f0c39eb68d96..e9a9e7e13a8945414577c267f4cbc7ccf7b81a10 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 9 + level: 10 paths: - src - tests diff --git a/phpunit.xml b/phpunit.xml index 911e767835b1224b2c7100d1e25eb41adfa89c9a..acd34e2f4ce35bebc35f9a0db2cb4146879549cc 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" - bootstrap="vendor/autoload.php" cacheDirectory=".phpunit.cache" executionOrder="depends,defects" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="true" beStrictAboutOutputDuringTests="true" + displayDetailsOnPhpunitDeprecations="true" + failOnPhpunitDeprecation="true" failOnRisky="true" failOnWarning="true" colors="true"> @@ -16,7 +17,7 @@ </testsuite> </testsuites> - <source> + <source ignoreIndirectDeprecations="true" restrictNotices="true" restrictWarnings="true"> <include> <directory>src</directory> </include> diff --git a/src/Context.php b/src/Context.php index 4e6160dd9850b75c7c4e736a35d51b2d9e11ff15..782e41d0c5d430faa357fa5bb4036c2ff3aac1af 100644 --- a/src/Context.php +++ b/src/Context.php @@ -16,6 +16,7 @@ use function array_pop; use function array_slice; use function count; use function is_array; +use function is_int; use function random_int; use function spl_object_id; use SplObjectStorage; @@ -43,6 +44,7 @@ final class Context public function __destruct() { foreach ($this->arrays as &$array) { + /* @phpstan-ignore function.alreadyNarrowedType */ if (is_array($array)) { array_pop($array); array_pop($array); @@ -57,9 +59,10 @@ final class Context * * @param-out T $value */ - public function add(array|object &$value): false|int|string + public function add(array|object &$value): int { if (is_array($value)) { + /* @phpstan-ignore paramOut.type */ return $this->addArray($value); } @@ -73,7 +76,7 @@ final class Context * * @param-out T $value */ - public function contains(array|object &$value): false|int|string + public function contains(array|object &$value): false|int { if (is_array($value)) { return $this->containsArray($value); @@ -140,7 +143,13 @@ final class Context { $end = array_slice($array, -2); - return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false; + if (isset($end[1]) && + $end[1] === $this->objects && + is_int($end[0])) { + return $end[0]; + } + + return false; } private function containsObject(object $value): false|int