diff --git a/.circleci/config.yml b/.circleci/config.yml index e6e36d0..6f32d20 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,56 +15,6 @@ orbs: executors: php_min: - resource_class: 'small' - environment: - <<: *env_app - <<: *env_composer - docker: - - - name: 'main' - image: 'cimg/php:7.2' - - php_plus1: - resource_class: 'small' - environment: - <<: *env_app - <<: *env_composer - docker: - - - name: 'main' - image: 'cimg/php:7.3' - - php_plus2: - resource_class: 'small' - environment: - <<: *env_app - <<: *env_composer - docker: - - - name: 'main' - image: 'cimg/php:7.4' - - php_plus3: - resource_class: 'small' - environment: - <<: *env_app - <<: *env_composer - docker: - - - name: 'main' - image: 'cimg/php:8.0' - - php_plus4: - resource_class: 'small' - environment: - <<: *env_app - <<: *env_composer - docker: - - - name: 'main' - image: 'cimg/php:8.1' - - php_plus5: resource_class: 'small' environment: <<: *env_app @@ -74,7 +24,7 @@ executors: name: 'main' image: 'cimg/php:8.2' - php_plus6: + php_plus1: resource_class: 'small' environment: <<: *env_app @@ -140,6 +90,11 @@ commands: name: 'Run PHPCS' command: |- "$(composer config 'bin-dir')/phpcs" + - + run: + name: 'Run PHPStan' + command: |- + "$(composer config 'bin-dir')/phpstan" analyze test: description: 'Run tests' @@ -211,8 +166,3 @@ workflows: executor: - 'php_min' - 'php_plus1' - - 'php_plus2' - - 'php_plus3' - - 'php_plus4' - - 'php_plus5' - - 'php_plus6' diff --git a/.editorconfig b/.editorconfig index 0d0b894..2596b86 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,9 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +[{.phpstan/,phpstan}*.neon] +indent_style = tab + [tests/fixtures/**] indent_style = unset indent_size = unset diff --git a/.gitignore b/.gitignore index de7157f..87986ee 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,9 @@ /phpcs.xml +### PHPStan. +/phpstan.neon + + ### PHPUnit. /phpunit.xml diff --git a/.phpstan/parameters.general.neon b/.phpstan/parameters.general.neon new file mode 100644 index 0000000..2c35cff --- /dev/null +++ b/.phpstan/parameters.general.neon @@ -0,0 +1,2 @@ +parameters: + level: 7 diff --git a/.phpstan/parameters.ignoreErrors.baseline.neon b/.phpstan/parameters.ignoreErrors.baseline.neon new file mode 100644 index 0000000..aab4991 --- /dev/null +++ b/.phpstan/parameters.ignoreErrors.baseline.neon @@ -0,0 +1,2 @@ +parameters: + ignoreErrors: [] diff --git a/.phpstan/parameters.ignoreErrors.custom.neon b/.phpstan/parameters.ignoreErrors.custom.neon new file mode 100644 index 0000000..f51e71c --- /dev/null +++ b/.phpstan/parameters.ignoreErrors.custom.neon @@ -0,0 +1,2 @@ +parameters: + ignoreErrors: [] diff --git a/.phpstan/parameters.paths.neon b/.phpstan/parameters.paths.neon new file mode 100644 index 0000000..ce78e04 --- /dev/null +++ b/.phpstan/parameters.paths.neon @@ -0,0 +1,4 @@ +parameters: + paths: + - ../src/ + - ../tests/src/ diff --git a/.phpstan/parameters.typeAliases.dev.neon b/.phpstan/parameters.typeAliases.dev.neon new file mode 100644 index 0000000..edd0d01 --- /dev/null +++ b/.phpstan/parameters.typeAliases.dev.neon @@ -0,0 +1,2 @@ +parameters: + typeAliases: {} diff --git a/.phpstan/parameters.typeAliases.prod.neon b/.phpstan/parameters.typeAliases.prod.neon new file mode 100644 index 0000000..edd0d01 --- /dev/null +++ b/.phpstan/parameters.typeAliases.prod.neon @@ -0,0 +1,2 @@ +parameters: + typeAliases: {} diff --git a/README.md b/README.md index 7051332..f43dc42 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # Mindscreen\YarnLock -[![CircleCI](https://circleci.com/gh/mindscreen/yarnlock/tree/master.svg?style=svg)](https://circleci.com/gh/mindscreen/yarnlock/?branch=master) -[![codecov](https://codecov.io/gh/mindscreen/yarnlock/branch/master/graph/badge.svg?token=HSF16OGPyr)](https://app.codecov.io/gh/mindscreen/yarnlock/branch/master) +[![CircleCI](https://circleci.com/gh/sweetchuck/mindscreen-yarnlock/tree/2.x.svg?style=svg)](https://circleci.com/gh/sweetchuck/mindscreen-yarnlock/?branch=2.x) +[![codecov](https://codecov.io/gh/sweetchuck/mindscreen-yarnlock/branch/2.x/graph/badge.svg?token=HSF16OGPyr)](https://app.codecov.io/gh/sweetchuck/mindscreen-yarnlock/branch/2.x) A php-package for parsing and evaluating the [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) format. + ## Basic Usage + ```php getPackagesByName('babel-core'); $babelCoreDependencies = $babelCorePackages[0]->getDependencies(); ``` + ## Package Depth -If you maybe don't just want all packages but only the direct dependencies plus one level of indirection, you have to go a little extra mile: + +If you maybe don't just want all packages but only the direct dependencies plus +one level of indirection, you have to go a little extra mile: + ```php =7.2", + "php": ">=8.2", "ext-ctype": "*" }, "require-dev": { - "phpunit/phpunit": "^8.5", - "squizlabs/php_codesniffer": "^3.9" + "jetbrains/phpstorm-attributes": "^1.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.0", + "squizlabs/php_codesniffer": "^3.9", + "symfony/filesystem": "^7.0" }, "autoload": { "psr-4": { @@ -37,10 +37,12 @@ "scripts": { "lint": [ "@lint:composer-validate", - "@lint:phpcs" + "@lint:phpcs", + "@lint:phpstan" ], "lint:composer-validate": "\"${COMPOSER_BINARY}\" validate", "lint:phpcs": "phpcs", + "lint:phpstan": "phpstan analyze", "test": [ "mkdir -p '.cache' 'reports/human' 'reports/machine'", "@test:phpunit" diff --git a/composer.lock b/composer.lock index cc9bb0e..daa4e59 100644 --- a/composer.lock +++ b/composer.lock @@ -4,78 +4,50 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3fcb13280e03896a6bd6c1c73d3760d8", + "content-hash": "2c3c1fc426b2e3b6899c4e60cf6aae39", "packages": [], "packages-dev": [ { - "name": "doctrine/instantiator", - "version": "1.5.0", + "name": "jetbrains/phpstorm-attributes", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "url": "https://github.com/JetBrains/phpstorm-attributes.git", + "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/JetBrains/phpstorm-attributes/zipball/a7a83ae5df4dd3c0875484483de19de8edf60a9f", + "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f", "shasum": "" }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" - }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "JetBrains\\PhpStorm\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" + "name": "JetBrains", + "homepage": "https://www.jetbrains.com" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "description": "PhpStorm specific attributes", "keywords": [ - "constructor", - "instantiate" + "attributes", + "jetbrains", + "phpstorm" ], "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "issues": "https://youtrack.jetbrains.com/newIssue?project=WI", + "source": "https://github.com/JetBrains/phpstorm-attributes/tree/1.0" }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2020-11-17T11:09:47+00:00" }, { "name": "myclabs/deep-copy", @@ -136,6 +108,64 @@ ], "time": "2023-03-08T13:26:56+00:00" }, + { + "name": "nikic/php-parser", + "version": "v5.0.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" + }, + "time": "2024-02-21T19:24:10+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -247,42 +277,108 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.10.59", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e607609388d3a6d418a50a49f7940e8086798281" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e607609388d3a6d418a50a49f7940e8086798281", + "reference": "e607609388d3a6d418a50a49f7940e8086798281", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2024-02-20T13:59:13+00:00" + }, { "name": "phpunit/php-code-coverage", - "version": "7.0.15", + "version": "11.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "819f92bba8b001d4363065928088de22f25a3a48" + "reference": "5e238e4b982cb272bf9faeee6f33af83d465d0e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48", - "reference": "819f92bba8b001d4363065928088de22f25a3a48", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5e238e4b982cb272bf9faeee6f33af83d465d0e2", + "reference": "5e238e4b982cb272bf9faeee6f33af83d465d0e2", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.3 || ^4.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "nikic/php-parser": "^5.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.0", + "phpunit/php-text-template": "^4.0", + "sebastian/code-unit-reverse-lookup": "^4.0", + "sebastian/complexity": "^4.0", + "sebastian/environment": "^7.0", + "sebastian/lines-of-code": "^3.0", + "sebastian/version": "^5.0", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" + "phpunit/phpunit": "^11.0" }, "suggest": { - "ext-xdebug": "^2.7.2" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "11.0-dev" } }, "autoload": { @@ -310,7 +406,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.15" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.0" }, "funding": [ { @@ -318,32 +415,32 @@ "type": "github" } ], - "time": "2021-07-26T12:20:09+00:00" + "time": "2024-02-02T06:03:46+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.5", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5" + "reference": "99e95c94ad9500daca992354fa09d7b99abe2210" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", - "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/99e95c94ad9500daca992354fa09d7b99abe2210", + "reference": "99e95c94ad9500daca992354fa09d7b99abe2210", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -370,7 +467,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.5" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.0" }, "funding": [ { @@ -378,26 +476,38 @@ "type": "github" } ], - "time": "2021-12-02T12:42:26+00:00" + "time": "2024-02-02T06:05:04+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5d8d9355a16d8cc5a1305b0a85342cfa420612be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5d8d9355a16d8cc5a1305b0a85342cfa420612be", + "reference": "5d8d9355a16d8cc5a1305b0a85342cfa420612be", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -414,41 +524,48 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "template" + "process" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.0" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-02-02T06:05:50+00:00" }, { - "name": "phpunit/php-timer", - "version": "2.1.3", + "name": "phpunit/php-text-template", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "d38f6cbff1cdb6f40b03c9811421561668cc133e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/d38f6cbff1cdb6f40b03c9811421561668cc133e", + "reference": "d38f6cbff1cdb6f40b03c9811421561668cc133e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -467,14 +584,15 @@ "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "timer" + "template" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.0" }, "funding": [ { @@ -482,33 +600,32 @@ "type": "github" } ], - "time": "2020-11-30T08:20:02+00:00" + "time": "2024-02-02T06:06:56+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "3.1.3", + "name": "phpunit/php-timer", + "version": "7.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "8a59d9e25720482ee7fcdf296595e08795b84dc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8a59d9e25720482ee7fcdf296595e08795b84dc5", + "reference": "8a59d9e25720482ee7fcdf296595e08795b84dc5", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -523,17 +640,19 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "tokenizer" + "timer" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.0" }, "funding": [ { @@ -541,53 +660,51 @@ "type": "github" } ], - "abandoned": true, - "time": "2021-07-26T12:15:06+00:00" + "time": "2024-02-02T06:08:01+00:00" }, { "name": "phpunit/phpunit", - "version": "8.5.36", + "version": "11.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9652df58e06a681429d8cfdaec3c43d6de581d5a" + "reference": "de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9652df58e06a681429d8cfdaec3c43d6de581d5a", - "reference": "9652df58e06a681429d8cfdaec3c43d6de581d5a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4", + "reference": "de24e7e7c67fbf437f7b6cd7bc919f2dc6fd89d4", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.0", + "myclabs/deep-copy": "^1.10.1", "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", - "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.12", - "phpunit/php-file-iterator": "^2.0.4", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", - "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.3", - "sebastian/exporter": "^3.1.5", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", - "sebastian/version": "^2.0.1" + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0", + "phpunit/php-file-iterator": "^5.0", + "phpunit/php-invoker": "^5.0", + "phpunit/php-text-template": "^4.0", + "phpunit/php-timer": "^7.0", + "sebastian/cli-parser": "^3.0", + "sebastian/code-unit": "^3.0", + "sebastian/comparator": "^6.0", + "sebastian/diff": "^6.0", + "sebastian/environment": "^7.0", + "sebastian/exporter": "^6.0", + "sebastian/global-state": "^7.0", + "sebastian/object-enumerator": "^6.0", + "sebastian/type": "^5.0", + "sebastian/version": "^5.0" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", - "phpunit/php-invoker": "To allow enforcing time limits" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -595,10 +712,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.5-dev" + "dev-main": "11.0-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -624,7 +744,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.36" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.0.3" }, "funding": [ { @@ -640,32 +760,146 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:52:15+00:00" + "time": "2024-02-10T06:31:16+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f", + "reference": "efd6ce5bb8131fe981e2f879dbd47605fbe0cc6f", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-02-02T05:48:04+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "6634549cb8d702282a04a774e36a7477d2bd9015" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6634549cb8d702282a04a774e36a7477d2bd9015", + "reference": "6634549cb8d702282a04a774e36a7477d2bd9015", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-02-02T05:50:41+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + "reference": "df80c875d3e459b45c6039e4d9b71d4fbccae25d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/df80c875d3e459b45c6039e4d9b71d4fbccae25d", + "reference": "df80c875d3e459b45c6039e4d9b71d4fbccae25d", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -687,7 +921,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.0" }, "funding": [ { @@ -695,34 +930,36 @@ "type": "github" } ], - "time": "2020-11-30T08:15:22+00:00" + "time": "2024-02-02T05:52:17+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.5", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "reference": "bd0f2fa5b9257c69903537b266ccb80fcf940db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/bd0f2fa5b9257c69903537b266ccb80fcf940db8", + "reference": "bd0f2fa5b9257c69903537b266ccb80fcf940db8", "shasum": "" }, "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -761,7 +998,66 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-02-02T05:53:45+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "88a434ad86150e11a606ac4866b09130712671f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/88a434ad86150e11a606ac4866b09130712671f0", + "reference": "88a434ad86150e11a606ac4866b09130712671f0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.0" }, "funding": [ { @@ -769,33 +1065,33 @@ "type": "github" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2024-02-02T05:55:19+00:00" }, { "name": "sebastian/diff", - "version": "3.0.4", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae" + "reference": "3e3f502419518897a923aa1c64d51f9def2e0aff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6296a0c086dd0117c1b78b059374d7fcbe7545ae", - "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3e3f502419518897a923aa1c64d51f9def2e0aff", + "reference": "3e3f502419518897a923aa1c64d51f9def2e0aff", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -827,7 +1123,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/3.0.4" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.0" }, "funding": [ { @@ -835,27 +1132,27 @@ "type": "github" } ], - "time": "2023-05-07T05:30:20+00:00" + "time": "2024-02-02T05:56:35+00:00" }, { "name": "sebastian/environment", - "version": "4.2.4", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" + "reference": "100d8b855d7180f79f9a9a5c483f2d960581c3ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/100d8b855d7180f79f9a9a5c483f2d960581c3ea", + "reference": "100d8b855d7180f79f9a9a5c483f2d960581c3ea", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" @@ -863,7 +1160,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -882,7 +1179,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -890,7 +1187,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.0.0" }, "funding": [ { @@ -898,34 +1196,34 @@ "type": "github" } ], - "time": "2020-11-30T07:53:42+00:00" + "time": "2024-02-02T05:57:54+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.5", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6" + "reference": "d0c0a93fc746b0c066037f1e7d09104129e868ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/73a9676f2833b9a7c36968f9d882589cd75511e6", - "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d0c0a93fc746b0c066037f1e7d09104129e868ff", + "reference": "d0c0a93fc746b0c066037f1e7d09104129e868ff", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/recursion-context": "^3.0" + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -960,14 +1258,15 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.5" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.0.0" }, "funding": [ { @@ -975,38 +1274,35 @@ "type": "github" } ], - "time": "2022-09-14T06:00:17+00:00" + "time": "2024-02-02T05:58:52+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.3", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0" + "reference": "590e7cbc6565fa2e26c3df4e629a34bb0bc00c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/66783ce213de415b451b904bfef9dda0cf9aeae0", - "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/590e7cbc6565fa2e26c3df4e629a34bb0bc00c17", + "reference": "590e7cbc6565fa2e26c3df4e629a34bb0bc00c17", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^8.0" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1025,13 +1321,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.3" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.0" }, "funding": [ { @@ -1039,34 +1336,33 @@ "type": "github" } ], - "time": "2023-08-02T09:23:32+00:00" + "time": "2024-02-02T05:59:33+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.4", + "name": "sebastian/lines-of-code", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "376c5b3f6b43c78fdc049740bca76a7c846706c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/376c5b3f6b43c78fdc049740bca76a7c846706c0", + "reference": "376c5b3f6b43c78fdc049740bca76a7c846706c0", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1081,14 +1377,16 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.0" }, "funding": [ { @@ -1096,32 +1394,34 @@ "type": "github" } ], - "time": "2020-11-30T07:40:27+00:00" + "time": "2024-02-02T06:00:36+00:00" }, { - "name": "sebastian/object-reflector", - "version": "1.1.2", + "name": "sebastian/object-enumerator", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f75f6c460da0bbd9668f43a3dde0ec0ba7faa678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f75f6c460da0bbd9668f43a3dde0ec0ba7faa678", + "reference": "f75f6c460da0bbd9668f43a3dde0ec0ba7faa678", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1139,11 +1439,12 @@ "email": "sebastian@phpunit.de" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.0" }, "funding": [ { @@ -1151,32 +1452,32 @@ "type": "github" } ], - "time": "2020-11-30T07:37:18+00:00" + "time": "2024-02-02T06:01:29+00:00" }, { - "name": "sebastian/recursion-context", - "version": "3.0.1", + "name": "sebastian/object-reflector", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "bb2a6255d30853425fd38f032eb64ced9f7f132d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/bb2a6255d30853425fd38f032eb64ced9f7f132d", + "reference": "bb2a6255d30853425fd38f032eb64ced9f7f132d", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1192,21 +1493,14 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.0" }, "funding": [ { @@ -1214,29 +1508,32 @@ "type": "github" } ], - "time": "2020-11-30T07:34:24+00:00" + "time": "2024-02-02T06:02:18+00:00" }, { - "name": "sebastian/resource-operations", - "version": "2.0.2", + "name": "sebastian/recursion-context", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "b75224967b5a466925c6d54e68edd0edf8dd4ed4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b75224967b5a466925c6d54e68edd0edf8dd4ed4", + "reference": "b75224967b5a466925c6d54e68edd0edf8dd4ed4", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1252,13 +1549,22 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.0" }, "funding": [ { @@ -1266,32 +1572,32 @@ "type": "github" } ], - "time": "2020-11-30T07:30:19+00:00" + "time": "2024-02-02T06:08:48+00:00" }, { "name": "sebastian/type", - "version": "1.1.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" + "reference": "b8502785eb3523ca0dd4afe9ca62235590020f3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8502785eb3523ca0dd4afe9ca62235590020f3f", + "reference": "b8502785eb3523ca0dd4afe9ca62235590020f3f", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1314,7 +1620,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.0.0" }, "funding": [ { @@ -1322,29 +1629,29 @@ "type": "github" } ], - "time": "2020-11-30T07:25:11+00:00" + "time": "2024-02-02T06:09:34+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "13999475d2cb1ab33cb73403ba356a814fdbb001" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/13999475d2cb1ab33cb73403ba356a814fdbb001", + "reference": "13999475d2cb1ab33cb73403ba356a814fdbb001", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1367,9 +1674,16 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.0" }, - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-02-02T06:10:47+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -1451,6 +1765,228 @@ ], "time": "2024-02-16T15:06:51+00:00" }, + { + "name": "symfony/filesystem", + "version": "v7.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12", + "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.0.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T15:02:46+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.2", @@ -1508,12 +2044,9 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.2", + "php": ">=8.2", "ext-ctype": "*" }, "platform-dev": [], - "platform-overrides": { - "php": "7.2" - }, "plugin-api-version": "2.6.0" } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index b4d3501..a5a083d 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -4,6 +4,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd"> + + ./src/ ./tests/src/ diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 0000000..c06b6e4 --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,7 @@ +includes: + - .phpstan/parameters.general.neon + - .phpstan/parameters.paths.neon + - .phpstan/parameters.ignoreErrors.baseline.neon + - .phpstan/parameters.ignoreErrors.custom.neon + - .phpstan/parameters.typeAliases.prod.neon + - .phpstan/parameters.typeAliases.dev.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b6bd97a..fb26989 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,34 +1,33 @@ - + + + ./src/ + + + - tests/src/Unit/ + ./tests/src/Unit/ - - - ./src/ - - + + + + + + + + + - - - - - - + + diff --git a/src/DependencyType.php b/src/DependencyType.php new file mode 100644 index 0000000..9a81a1c --- /dev/null +++ b/src/DependencyType.php @@ -0,0 +1,16 @@ +name; + } - /** - * Array of version strings satisfied by this package, - * e.g. version = "1.14.0" might satisfy "^1.0.0", "1.14.0", ... - * - * @var string[] - */ - protected $satisfies = []; + public function setName(string $name): static + { + $this->name = $name; - /** - * @var Package[] - */ - protected $dependencies = []; + return $this; + } - /** - * @var Package[] - */ - protected $devDependencies = []; + protected string $version = ''; - /** - * @var Package[] - */ - protected $peerDependencies = []; + public function getVersion(): string + { + return $this->version; + } - /** - * @var Package[] - */ - protected $optionalDependencies = []; + public function setVersion(string $version): static + { + $this->version = $version; + + return $this; + } /** * The distribution resolved for this package. - * - * @var string */ - protected $resolved; + protected string $resolved = ''; - /** - * Packages that require this package, i.e. packages who's dependencies are - * (in part) resolved by this one. - * - * @var Package[] - */ - protected $resolves = []; + public function getResolved(): string + { + return $this->resolved; + } + + public function setResolved(string $resolved): static + { + $this->resolved = $resolved; + + return $this; + } /** - * Depth in the dependency tree. Only initialized once the YarnLock computes - * the depth of all contained packages. + * Depth in the dependency tree. * - * @var int + * Only initialized once the YarnLock computes the depth of all contained + * packages. */ - protected $depth = null; + protected ?int $depth = null; - /** - * @return string - */ - public function getName() + public function getDepth(): ?int { - return $this->name; + return $this->depth; } - /** - * @param string $name - */ - public function setName($name) + public function setDepth(?int $depth): static { - $this->name = $name; + $this->depth = $depth; + + return $this; } /** - * @return string + * Array of version strings satisfied by this package, + * e.g. version = "1.14.0" might satisfy "^1.0.0", "1.14.0", ... + * + * @var string[] */ - public function getVersion() - { - return $this->version; - } + protected array $satisfies = []; /** - * @param string $version + * @return string[] */ - public function setVersion($version) + public function getSatisfiedVersions(): array { - $this->version = $version; + return $this->satisfies; } /** - * @return string + * @deprecated + * + * @see addSatisfiedVersion() */ - public function getResolved() + public function addVersion(string $versionString): static { - return $this->resolved; + return $this->addSatisfiedVersion($versionString); } - /** - * @param string $resolved - */ - public function setResolved($resolved) + public function addSatisfiedVersion(string $versionString): static { - $this->resolved = $resolved; + $this->satisfies[] = $versionString; + + return $this; } /** - * @return int|null + * @phpstan-var array> */ - public function getDepth() - { - return $this->depth; - } + #[ArrayShape([ + 'dependencies' => '\Mindscreen\YarnLock\Package[]', + 'optionalDependencies' => '\Mindscreen\YarnLock\Package[]', + 'devDependencies' => '\Mindscreen\YarnLock\Package[]', + 'peerDependencies' => '\Mindscreen\YarnLock\Package[]', + ])] + protected array $dependencies = [ + DependencyType::ProdRequired->value => [], + DependencyType::ProdOptional->value => [], + DependencyType::DevRequired->value => [], + DependencyType::PeerRequired->value => [], + ]; /** - * @param int $depth + * @return \Mindscreen\YarnLock\Package[] + * + * @see getProdRequiredDependencies() */ - public function setDepth($depth) + #[Deprecated( + reason: 'Ambiguous name', + replacement: '%class%::getProdRequiredDependencies()', + )] + public function getDependencies(): array { - $this->depth = $depth; + return $this->getProdRequiredDependencies(); } /** - * @param string $versionString + * @return \Mindscreen\YarnLock\Package[] */ - public function addVersion($versionString) + public function getProdRequiredDependencies(): array { - array_push($this->satisfies, $versionString); + return $this->dependencies[DependencyType::ProdRequired->value]; } /** - * @return string[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getSatisfiedVersions() + #[Deprecated( + reason: 'Inconsistent naming.', + replacement: '%class%::getProdOptionalDependencies', + )] + public function getOptionalDependencies(): array { - return $this->satisfies; + return $this->dependencies[DependencyType::ProdOptional->value]; } /** - * @return Package[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getDependencies() + public function getProdOptionalDependencies(): array { - return $this->dependencies; + return $this->dependencies[DependencyType::ProdOptional->value]; } /** - * @return Package[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getDevDependencies() + public function getDevRequiredDependencies(): array { - return $this->devDependencies; + return $this->dependencies[DependencyType::DevRequired->value]; } /** - * @return Package[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getPeerDependencies() + public function getPeerRequiredDependencies(): array { - return $this->peerDependencies; + return $this->dependencies[DependencyType::PeerRequired->value]; } /** - * @return Package[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getOptionalDependencies() + public function getAllDependencies(): array { - return $this->optionalDependencies; + return array_merge( + $this->getProdRequiredDependencies(), + $this->getProdOptionalDependencies(), + $this->getPeerRequiredDependencies(), + $this->getDevRequiredDependencies(), + ); } /** - * @return Package[] + * @return \Mindscreen\YarnLock\Package[] */ - public function getAllDependencies() + public function getDependenciesByType(DependencyType $type): array { - return array_merge( - $this->getDependencies(), - $this->getDevDependencies(), - $this->getOptionalDependencies(), - $this->getPeerDependencies() - ); + return match ($type) { + DependencyType::ProdRequired => $this->getProdRequiredDependencies(), + DependencyType::ProdOptional => $this->getProdOptionalDependencies(), + DependencyType::DevRequired => $this->getDevRequiredDependencies(), + DependencyType::PeerRequired => $this->getPeerRequiredDependencies(), + }; } /** - * @return Package[] + * Packages that require this package, i.e. packages who's dependencies are + * (in part) resolved by this one. + * + * @var \Mindscreen\YarnLock\Package[] */ - public function getResolves() + protected array $resolves = []; + + /** + * @return \Mindscreen\YarnLock\Package[] + */ + public function getResolves(): array { return $this->resolves; } /** - * @param Package $package * @internal */ - public function addResolves(Package $package) + public function addResolves(Package $package): static { - if ($this->resolves === null) { - $this->resolves = []; - } - if (in_array($package, $this->resolves)) { - return; + if (!in_array($package, $this->resolves)) { + $this->resolves[] = $package; } - $this->resolves[] = $package; + + return $this; } /** * Add a package as dependency to the current one. - * - * @param Package $package - * @param string $type */ - public function addDependency(Package $package, $type = self::DEPENDENCY_TYPE_DEFAULT) + public function addDependency(Package $package, DependencyType $type = DependencyType::ProdRequired): static { - $field = self::getDependencyField($type); - if (in_array($package, $this->$field)) { - return; + if (in_array($package, $this->dependencies[$type->value])) { + return $this; } - array_push($this->$field, $package); + + $this->dependencies[$type->value][] = $package; $package->addResolves($this); - } - /** - * Get the property-name and yarn-lock key for the given dependency-type. - * - * @param string $type - * @return string - */ - public static function getDependencyField($type) - { - $field = 'dependencies'; - switch ($type) { - case self::DEPENDENCY_TYPE_DEV: - $field = 'devDependencies'; - break; - case self::DEPENDENCY_TYPE_OPTIONAL: - $field = 'optionalDependencies'; - break; - case self::DEPENDENCY_TYPE_PEER: - $field = 'peerDependencies'; - break; - } - return $field; + return $this; } /** * Printing a package should contain it's name and version. - * - * @return string */ - public function __toString() + public function __toString(): string { return $this->getName() . '@' . $this->getVersion(); } diff --git a/src/Parser.php b/src/Parser.php index 43294c2..802805b 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -1,5 +1,7 @@ |\stdClass + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function parse($input, $assoc = false) + public function parse(string $input, bool $assoc = false): array|\stdClass { - if (!is_string($input)) { - throw new \InvalidArgumentException('Parser input is expected to be a string.', 1519142104); - } $data = new \stdClass(); $current = $data; $lines = explode("\n", $input); @@ -25,64 +24,81 @@ public function parse($input, $assoc = false) $indentationDepth = null; $indentationLevel = 0; $requireKey = false; - foreach ($lines as $l => $line) { - $l++; + foreach ($lines as $lineIndex => $line) { + $lineNumber = $lineIndex + 1; $line = rtrim($line); - if (empty($line)) { + + if ($line === '') { continue; } + if ($indentationCharacter === null && ctype_space($line[0])) { $indentationCharacter = $line[0]; } - for ($i = 0; $i < strlen($line); $i++) { - if (ctype_space($line[$i])) { - if ($line[$i] !== $indentationCharacter) { - throw new ParserException(sprintf('Mixed indentation characters at line %s', $l), 1519140104); + + for ($charIndex = 0; $charIndex < strlen($line); $charIndex++) { + $char = substr($line, $charIndex, 1); + if (ctype_space($char)) { + if ($char !== $indentationCharacter) { + throw new ParserException( + sprintf('Mixed indentation characters at line %s', $lineNumber), + ParserErrorCode::MixedIndentStyle->value, + ); } - } else { - if ($i > 0) { - $line = substr($line, $i); - if ($line[0] === '#') { - // comment - break; - } - if ($indentationDepth === null) { - $indentationDepth = $i; - } else { - if ($i % $indentationDepth !== 0) { - throw new ParserException( - sprintf('Indentation depth is not constant at line %s', $l), - 1519140379 - ); - } - - if ($i / $indentationDepth > $indentationLevel) { - throw new ParserException( - sprintf('Unexpected indentation at line %s', $l), - 1519140493 - ); - } - } - $newIndentationLevel = $i / $indentationDepth; - } else { - $newIndentationLevel = 0; + + continue; + } + + if ($charIndex > 0) { + $line = substr($line, $charIndex); + if ($line[0] === '#') { + // comment + break; } - if ($newIndentationLevel < $indentationLevel) { - if ($requireKey) { - throw new ParserException('Expecting property at line ' . $l, 1519142311); + + if ($indentationDepth === null) { + $indentationDepth = $charIndex; + } else { + if ($charIndex % $indentationDepth !== 0) { + throw new ParserException( + sprintf('Indentation depth is not constant at line %s', $lineNumber), + ParserErrorCode::MixedIndentSize->value, + ); } - for ($j = $indentationLevel; $j > $newIndentationLevel; $j--) { - $current = $current->__parent; + + if ($charIndex / $indentationDepth > $indentationLevel) { + throw new ParserException( + sprintf('Unexpected indentation at line %s', $lineNumber), + ParserErrorCode::UnexpectedIndentation->value, + ); } } - $indentationLevel = $newIndentationLevel; - break; + $newIndentationLevel = $charIndex / $indentationDepth; + } else { + $newIndentationLevel = 0; + } + + if ($newIndentationLevel < $indentationLevel) { + if ($requireKey) { + throw new ParserException( + sprintf('Expecting property at line %d', $lineNumber), + ParserErrorCode::MissingProperty->value, + ); + } + + for ($j = $indentationLevel; $j > $newIndentationLevel; $j--) { + $current = $current->__parent; + } } + $indentationLevel = $newIndentationLevel; + break; } - if ($line[0] === '#') { + + if (substr($line, 0, 1) === '#') { continue; } - if ($line[strlen($line) - 1] == ':') { + + if (str_ends_with($line, ':')) { $indentationLevel += 1; $currentKey = substr($line, 0, -1); $current->$currentKey = new \stdClass(); @@ -105,66 +121,89 @@ public function parse($input, $assoc = false) $parts = explode(' ', $line, 2); $currentKey = $parts[0]; if (count($parts) === 1) { - throw new ParserException('Expecting value at line ' . $l, 1519141916); + throw new ParserException( + sprintf('Expecting value at line %d', $lineNumber), + ParserErrorCode::MissingValue->value, + ); } $value = $parts[1]; } - $current->$currentKey = self::parseValue(ltrim($value)); + $current->$currentKey = static::parseValue(ltrim($value)); } } if ($requireKey) { - throw new ParserException('Unexpected EOF, expecting property', 1519142311); + throw new ParserException( + 'Unexpected EOF, expecting property', + ParserErrorCode::UnexpectedEof->value, + ); } - self::cleanupObject($data); + + static::cleanupObject($data); if ($assoc) { - return self::convertObjectToArray($data); + return static::convertObjectToArray($data); } + return $data; } - protected static function parseValue($input) + protected static function parseValue(string $input): mixed { if ($input === 'true') { return true; } + if ($input === 'false') { return false; } + if ($input === 'null') { return null; } - if ($input[0] === '"' && $input[strlen($input) - 1] === '"') { + + if (str_starts_with($input, '"') + && str_ends_with($input, '"') + ) { return substr($input, 1, -1); } + if (($value = filter_var($input, FILTER_VALIDATE_INT)) !== false) { return $value; } + if (($value = filter_var($input, FILTER_VALIDATE_FLOAT)) !== false) { return $value; } + return $input; } - protected static function cleanupObject(&$object) + protected static function cleanupObject(object $object): void { unset($object->__parent); - foreach (get_object_vars($object) as $key => $value) { + foreach (get_object_vars($object) as $value) { if ($value instanceof \stdClass) { - self::cleanupObject($value); + static::cleanupObject($value); } } } - protected static function convertObjectToArray($object) + /** + * @param array|object $object + * + * @return array + */ + protected static function convertObjectToArray(array|object $object): array { if (is_object($object)) { - $object = (array)$object; + $object = (array) $object; } + foreach ($object as $key => $value) { if (is_array($value) || is_object($value)) { - $object[$key] = self::convertObjectToArray($value); + $object[$key] = static::convertObjectToArray($value); } } + return $object; } @@ -173,63 +212,34 @@ protected static function convertObjectToArray($object) * e.g. `minimatch@^3.0.0, minimatch@^3.0.2, "minimatch@2 || 3"`, which would * fail when simply splitting on spaces. * - * @param string $key - * * @return string[] */ - public static function parseVersionStrings($key) + public static function parseVersionStrings(string $key): array { - $result = []; - if (strpos($key, '"') === false) { - $result = explode(',', $key); - } else { - $currentKey = ''; - $isString = false; - for ($i = 0; $i < strlen($key); $i++) { - if ($key[$i] == '"') { - if (!$isString) { - $isString = true; - continue; - } else { - $isString = false; - continue; - } - } - if (!$isString && $key[$i] == ',') { - $result[] = $currentKey; - $currentKey = ''; - continue; - } - $currentKey .= $key[$i]; - } - if (!empty($currentKey)) { - $result[] = $currentKey; + $parts = preg_split('/\s*,\s*/', trim($key)) ?: []; + foreach ($parts as &$part) { + if (str_starts_with($part, '"') && str_ends_with($part, '"')) { + $part = substr($part, 1, -1); } } - return array_map( - function ($e) { - return trim($e); - }, - $result - ); + return $parts; } /** * To avoid splitting on scoped package-names, every but the last @ are considered * package name. * - * @param string $versionString - * * @return string[] */ - public static function splitVersionString($versionString) + public static function splitVersionString(string $versionString): array { $parts = explode('@', $versionString); $version = array_pop($parts); + return [ implode('@', $parts), - $version + $version, ]; } } diff --git a/src/ParserErrorCode.php b/src/ParserErrorCode.php new file mode 100644 index 0000000..09c9d9c --- /dev/null +++ b/src/ParserErrorCode.php @@ -0,0 +1,39 @@ +parse($input); + // @phpstan-ignore-next-line $yarnLock = new static(); - $yarnLock->setPackages(self::evaluatePackages($yarnLockData)); + $yarnLock->setPackages(static::evaluatePackages($yarnLockData)); + return $yarnLock; } /** - * @param \stdClass $data - * @return array + * @return Package[] */ - protected static function evaluatePackages($data) + protected static function evaluatePackages(object $data): array { $packageVersionMap = []; $allPackages = []; @@ -56,7 +53,7 @@ protected static function evaluatePackages($data) $package->setResolved($dependencyInformation->resolved); foreach ($packageVersionStrings as &$packageVersionString) { $packageVersionString = Parser::splitVersionString($packageVersionString)[1]; - $package->addVersion($packageVersionString); + $package->addSatisfiedVersion($packageVersionString); $packageVersionMap[$packageName][$packageVersionString] = [ 'package' => $package, 'data' => $dependencyInformation, @@ -72,17 +69,13 @@ protected static function evaluatePackages($data) if (!empty($handledPackages[spl_object_id($package)])) { continue; } + $handledPackages[spl_object_id($package)] = true; $data = $packageInformation['data']; - foreach ([ - Package::DEPENDENCY_TYPE_DEFAULT, - Package::DEPENDENCY_TYPE_DEV, - Package::DEPENDENCY_TYPE_OPTIONAL, - Package::DEPENDENCY_TYPE_PEER, - ] as $dependencyType) { - $field = Package::getDependencyField($dependencyType); - if (isset($data->$field)) { - foreach ($data->$field as $dependencyName => $dependencyVersion) { + foreach (DependencyType::cases() as $dependencyType) { + $field = $dependencyType->value; + if (isset($data->{$field})) { + foreach ($data->{$field} as $dependencyName => $dependencyVersion) { $dependencyPackage = $packageVersionMap[$dependencyName][$dependencyVersion]['package']; $package->addDependency($dependencyPackage, $dependencyType); } @@ -94,11 +87,11 @@ protected static function evaluatePackages($data) } /** - * Get all packages resolved in this lock file + * Get all packages resolved in this lock file. * * @return Package[] */ - public function getPackages() + public function getPackages(): array { return $this->packages; } @@ -106,27 +99,27 @@ public function getPackages() /** * @param Package[] $packages */ - public function setPackages($packages) + public function setPackages(array $packages): static { $this->packages = $packages; + + return $this; } /** * A package might be required in multiple versions. * - * @param string $packageName - * * @return Package[] */ - public function getPackagesByName($packageName) + public function getPackagesByName(string $packageName): array { return array_values( array_filter( $this->packages, - function (Package $package) use ($packageName) { + function (Package $package) use ($packageName): bool { return $package->getName() === $packageName; - } - ) + }, + ), ); } @@ -135,12 +128,9 @@ function (Package $package) use ($packageName) { * (`getPackagesByDepth(0, 2)`) or starting from a certain depth (`getPackagesByDepth(1, null)`). * Note that $end is exclusive. * - * @param int $start - * @param int $end - * * @return Package[] */ - public function getPackagesByDepth($start, $end = 0) + public function getPackagesByDepth(int $start, ?int $end = 0): array { $this->calculateDepth(); if ($end === 0 || ($end !== null && $end < $start)) { @@ -150,13 +140,13 @@ public function getPackagesByDepth($start, $end = 0) return array_values( array_filter( $this->packages, - function (Package $package) use ($start, $end) { + function (Package $package) use ($start, $end): bool { $depth = $package->getDepth(); if ($depth === null) { return $end === null; } - $to = $end === null || ($depth < $end); + $to = $end === null || $depth < $end; return $depth >= $start && $to; } @@ -166,10 +156,8 @@ function (Package $package) use ($start, $end) { /** * Get the maximal dependency-tree depth. - * - * @return int */ - public function getDepth() + public function getDepth(): int { $this->calculateDepth(); @@ -178,7 +166,7 @@ public function getDepth() function ($d, Package $package) { return max($d, $package->getDepth()); }, - 0 + 0, ); } @@ -188,41 +176,33 @@ function ($d, Package $package) { * If no version is given and a package is resolved with multiple versions, * the first one will be returned. Consider using `getPackagesByName` and * filter for the version that fits your needs closest. - * - * @param string $name - * @param string $version - * - * @return Package|null */ - public function getPackage($name, $version = null) + public function getPackage(string $name, string $version = null): ?Package { $candidates = $this->getPackagesByName($name); if (count($candidates) < 1) { return null; } + if ($version === null) { return $candidates[0]; } + foreach ($candidates as $package) { - if ($package->getVersion() === $version) { - return $package; - } - if (in_array($version, $package->getSatisfiedVersions())) { + if ($package->getVersion() === $version + || in_array($version, $package->getSatisfiedVersions()) + ) { return $package; } } + return null; } /** * Checks whether a specific package is resolved in this lock file. - * - * @param string $name - * @param string $version - * - * @return bool */ - public function hasPackage($name, $version = null) + public function hasPackage(string $name, ?string $version = null): bool { return $this->getPackage($name, $version) !== null; } @@ -234,21 +214,23 @@ public function hasPackage($name, $version = null) * * @param Package[] $root */ - public function calculateDepth(array $root = null) + public function calculateDepth(?array $root = null): void { if ($this->depthCalculated) { return; } + if ($root === null) { $root = array_values( array_filter( $this->packages, - function (Package $p) { + function (Package $p): bool { return count($p->getResolves()) === 0; - } - ) + }, + ), ); } + /** @var Package $rootNode */ foreach ($root as $rootNode) { $this->calculateChildDepth($rootNode, 0); @@ -256,15 +238,12 @@ function (Package $p) { $this->depthCalculated = true; } - /** - * @param Package $node - * @param int $depth - */ - protected function calculateChildDepth(Package $node, $depth) + protected function calculateChildDepth(Package $node, int $depth): void { if ($node->getDepth() !== null && $node->getDepth() <= $depth) { return; } + $node->setDepth($depth); foreach ($node->getAllDependencies() as $dependency) { $this->calculateChildDepth($dependency, $depth + 1); diff --git a/tests/src/Unit/PackageTest.php b/tests/src/Unit/PackageTest.php index 85baf93..ab0c61d 100644 --- a/tests/src/Unit/PackageTest.php +++ b/tests/src/Unit/PackageTest.php @@ -1,15 +1,14 @@ setName('package1'); @@ -23,7 +22,7 @@ public function testAvoidDuplicates() $package1->addDependency($package2); $package2->addResolves($package1); - static::assertSame(1, count($package1->getDependencies())); - static::assertSame(1, count($package2->getResolves())); + static::assertCount(1, $package1->getProdRequiredDependencies()); + static::assertCount(1, $package2->getResolves()); } } diff --git a/tests/src/Unit/ParserTest.php b/tests/src/Unit/ParserTest.php index b857699..e891a47 100644 --- a/tests/src/Unit/ParserTest.php +++ b/tests/src/Unit/ParserTest.php @@ -1,21 +1,25 @@ expectException(\InvalidArgumentException::class); - $this->expectExceptionCode(1519142104); - $this->parser->parse(null); - } - - /** - * Comments don't have to follow indentation rules - * @throws ParserException - */ - public function testComments() - { - $fileContents = static::getInput('comments.txt'); - $result = $this->parser->parse($fileContents, true); static::assertSame( [ 'foo' => 4, @@ -51,42 +42,41 @@ public function testComments() ], 'baz' => true, ], - $result + $this->parser->parse(static::getInput('comments.txt'), true), ); } /** - * Using mixed indentation characters (like tab and space) should throw an exception - * @throws ParserException + * Using mixed indentation characters (like tab and space) should throw an exception. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMixedIndentations() + public function testMixedIndentations(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519140104); - $fileContents = static::getInput('mixed_indentation.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::MixedIndentStyle->value); + $this->parser->parse(static::getInput('mixed_indentation.txt'), true); } /** - * Inconsistent indentations should throw an exception - * @throws ParserException + * Inconsistent indentations should throw an exception. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMixedIndentationDepth() + public function testMixedIndentationDepth(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519140379); - $fileContents = static::getInput('mixed_indentation_depth.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::MixedIndentSize->value); + $this->parser->parse(static::getInput('mixed_indentation_depth.txt'), true); } /** - * Indentation should work with other indentation than two spaces - * @throws ParserException + * Indentation should work with other indentation than two spaces. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testDifferentIndentationDepth() + public function testDifferentIndentationDepth(): void { - $fileContents = static::getInput('indentation_depth.txt'); - $result = $this->parser->parse($fileContents, true); static::assertSame( [ 'foo' => [ @@ -96,77 +86,79 @@ public function testDifferentIndentationDepth() ], ], ], - $result + $this->parser->parse(static::getInput('indentation_depth.txt'), true), ); } /** - * A key-value cannot be further indented as the previous one - * @throws ParserException + * A key-value cannot be further indented as the previous one. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testUnexpectedIndentation() + public function testUnexpectedIndentation(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519140493); - $fileContents = static::getInput('unexpected_indentation.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::UnexpectedIndentation->value); + $this->parser->parse(static::getInput('unexpected_indentation.txt'), true); } /** - * An array key requires following properties - * @throws ParserException + * An array key requires following properties. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMissingProperty() + public function testMissingProperty(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519142311); - $fileContents = static::getInput('missing_property.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::MissingProperty->value); + $this->parser->parse(static::getInput('missing_property.txt'), true); } /** - * Comments following an array key should still require properties - * @throws ParserException + * Comments following an array key should still require properties. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMissingProperty2() + public function testMissingProperty2(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519142311); - $fileContents = static::getInput('missing_property2.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::MissingProperty->value); + $this->parser->parse(static::getInput('missing_property2.txt'), true); } /** - * The input ending on an array object without values should throw an exception - * @throws ParserException + * The input ending on an array object without values should throw an exception. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMissingPropertyEof() + public function testMissingPropertyEof(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519142311); - $fileContents = static::getInput('missing_property_eof.txt'); - $this->parser->parse($fileContents, true); + $this->expectExceptionCode(ParserErrorCode::UnexpectedEof->value); + $this->parser->parse(static::getInput('missing_property_eof.txt'), true); } /** - * Keys without value should throw an exception - * @throws ParserException + * Keys without value should throw an exception. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testMissingPropertyValue() + public function testMissingPropertyValue(): void { $this->expectException(ParserException::class); - $this->expectExceptionCode(1519141916); + $this->expectExceptionCode(ParserErrorCode::MissingValue->value); $this->parser->parse('foo', true); } /** - * Different values should yield different value-types - * @throws ParserException + * Different values should yield different value-types. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testDataTypes() + public function testDataTypes(): void { - $fileContents = static::getInput('datatypes.txt'); - $result = $this->parser->parse($fileContents); + /** @var \stdClass $result */ + $result = $this->parser->parse(static::getInput('datatypes.txt')); static::assertSame(true, $result->bool_t); static::assertSame(false, $result->bool_f); static::assertSame(null, $result->unset); @@ -178,69 +170,85 @@ public function testDataTypes() } /** - * The parser should create a valid \stdClass structure - * @throws ParserException + * The parser should create a valid \stdClass structure. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testYarnExampleObject() + public function testYarnExampleObject(): void { - $fileContents = static::getInput('valid_input.txt'); - $result = $this->parser->parse($fileContents); - static::assertSame(true, $result instanceof \stdClass); - static::assertSame(4, count(get_object_vars($result))); - static::assertObjectHasAttribute('package-1@^1.0.0', $result); - $key = 'package-3@^3.0.0'; - $package3 = $result->$key; - static::assertObjectHasAttribute('version', $package3); - static::assertObjectHasAttribute('resolved', $package3); - static::assertObjectHasAttribute('dependencies', $package3); + $result = $this->parser->parse(static::getInput('valid_input.txt')); + + static::assertIsObject($result); + static::assertCount(4, get_object_vars($result)); + static::assertObjectHasProperty('package-1@^1.0.0', $result); + $package3 = $result->{'package-3@^3.0.0'}; + static::assertObjectHasProperty('version', $package3); + static::assertObjectHasProperty('resolved', $package3); + static::assertObjectHasProperty('dependencies', $package3); $package3_dependencies = $package3->dependencies; - static::assertSame(1, count(get_object_vars($package3_dependencies))); + static::assertCount(1, get_object_vars($package3_dependencies)); } /** - * The parser should create a valid array structure - * @throws ParserException + * The parser should create a valid array structure. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testYarnExampleArray() + public function testYarnExampleArray(): void { - $fileContents = static::getInput('valid_input.txt'); - $result = $this->parser->parse($fileContents, true); - static::assertSame(true, is_array($result)); - static::assertSame(4, count($result)); + $result = $this->parser->parse(static::getInput('valid_input.txt'), true); + static::assertIsArray($result); + static::assertCount(4, $result); static::assertArrayHasKey('package-1@^1.0.0', $result); $package3 = $result['package-3@^3.0.0']; static::assertArrayHasKey('version', $package3); static::assertArrayHasKey('resolved', $package3); static::assertArrayHasKey('dependencies', $package3); $package3_dependencies = $package3['dependencies']; - static::assertSame(true, is_array($package3_dependencies)); - static::assertSame(1, count($package3_dependencies)); + static::assertIsArray($package3_dependencies); + static::assertCount(1, $package3_dependencies); } /** - * Scoped packages names should not be split at the first '@' + * @return array */ - public function testVersionSplitting() + public static function casesVersionSplitting(): array { - static::assertSame( - ['gulp-sourcemaps', '2.6.4'], - Parser::splitVersionString('gulp-sourcemaps@2.6.4') - ); + return [ + 'a' => [ + 'expected' => ['gulp-sourcemaps', '2.6.4'], + 'versionString' => 'gulp-sourcemaps@2.6.4', + ], + 'b' => [ + 'expected' => ['@gulp-sourcemaps/identity-map', '1.X'], + 'versionString' => '@gulp-sourcemaps/identity-map@1.X', + ], + ]; + } + /** + * Scoped packages names should not be split at the first '@'. + * + * @param string[] $expected + */ + #[DataProvider('casesVersionSplitting')] + public function testVersionSplitting(array $expected, string $versionString): void + { static::assertSame( - ['@gulp-sourcemaps/identity-map', '1.X'], - Parser::splitVersionString('@gulp-sourcemaps/identity-map@1.X') + $expected, + Parser::splitVersionString($versionString), ); } /** - * Single-value keys should not be split at spaces if they are surrounded with quotes - * @throws ParserException + * Single-value keys should not be split at spaces if they are surrounded with quotes. + * + * @throws \Mindscreen\YarnLock\ParserException */ - public function testQuotedKeys() + public function testQuotedKeys(): void { - $fileContents = static::getInput('quoted-key.txt'); - $result = $this->parser->parse($fileContents, true); + /** @var array $result */ + $result = $this->parser->parse(static::getInput('quoted-key.txt'), true); $data = $result['test']; foreach (['foo', 'bar', 'foo bar', 'foobar'] as $item) { static::assertArrayHasKey($item, $data); @@ -248,26 +256,51 @@ public function testQuotedKeys() } } - public function testParseVersionStrings() + /** + * @return array + */ + public static function casesParseVersionStrings(): array { - $input = 'minimatch@^3.0.0, minimatch@^3.0.2, "minimatch@2 || 3"'; - $versionStrings = Parser::parseVersionStrings($input); - static::assertSame(['minimatch@^3.0.0', 'minimatch@^3.0.2', 'minimatch@2 || 3'], $versionStrings); - - $input = 'babel-types@^6.10.2, babel-types@^6.14.0, babel-types@^6.15.0'; - $versionStrings = Parser::parseVersionStrings($input); - static::assertSame(['babel-types@^6.10.2', 'babel-types@^6.14.0', 'babel-types@^6.15.0'], $versionStrings); - - $input = 'array-uniq@^1.0.1'; - $versionStrings = Parser::parseVersionStrings($input); - static::assertSame(['array-uniq@^1.0.1'], $versionStrings); - - $input = '"cssom@>= 0.3.0 < 0.4.0", cssom@0.3.x'; - $versionStrings = Parser::parseVersionStrings($input); - static::assertSame(['cssom@>= 0.3.0 < 0.4.0', 'cssom@0.3.x'], $versionStrings); + return [ + 'a' => [ + 'expected' => [ + 'minimatch@^3.0.0', 'minimatch@^3.0.2', 'minimatch@2 || 3', + ], + 'key' => 'minimatch@^3.0.0, minimatch@^3.0.2, "minimatch@2 || 3"', + ], + 'b' => [ + 'expected' => [ + 'babel-types@^6.10.2', 'babel-types@^6.14.0', 'babel-types@^6.15.0', + ], + 'key' => 'babel-types@^6.10.2, babel-types@^6.14.0, babel-types@^6.15.0', + ], + 'c' => [ + 'expected' => [ + 'array-uniq@^1.0.1', + ], + 'key' => 'array-uniq@^1.0.1', + ], + 'd' => [ + 'expected' => [ + 'cssom@>= 0.3.0 < 0.4.0', 'cssom@0.3.x' + ], + 'key' => '"cssom@>= 0.3.0 < 0.4.0", cssom@0.3.x', + ], + 'e' => [ + 'expected' => [ + 'graceful-readlink@>= 1.0.0' + ], + 'key' => '"graceful-readlink@>= 1.0.0"', + ], + ]; + } - $input = '"graceful-readlink@>= 1.0.0"'; - $versionStrings = Parser::parseVersionStrings($input); - static::assertSame(['graceful-readlink@>= 1.0.0'], $versionStrings); + /** + * @param string[] $expected + */ + #[DataProvider('casesParseVersionStrings')] + public function testParseVersionStrings(array $expected, string $key): void + { + static::assertSame($expected, Parser::parseVersionStrings($key)); } } diff --git a/tests/src/Unit/TestBase.php b/tests/src/Unit/TestBase.php index 36c41aa..7e83d62 100644 --- a/tests/src/Unit/TestBase.php +++ b/tests/src/Unit/TestBase.php @@ -1,8 +1,11 @@ expectException(\InvalidArgumentException::class); - $this->expectExceptionCode(1519201965); - YarnLock::fromString(null); - } - protected function setUp(): void { - $yarnLockContents = static::getInput('example-yarn-package.txt'); - $this->yarnLock = YarnLock::fromString($yarnLockContents); + parent::setUp(); + $this->yarnLock = YarnLock::fromString(static::getInput('example-yarn-package.txt')); } /** * A package should be found with every satisfying version string. */ - public function testPackageExists() + public function testPackageExists(): void { // babel-core@^6.0.0, babel-core@^6.11.4, babel-core@^6.14.0: static::assertTrue($this->yarnLock->hasPackage('babel-core')); @@ -50,18 +42,18 @@ public function testPackageExists() * Querying for an existing package with different satisfied versions should yield in the * correct package. Asking for a unknown package should return null. */ - public function testGetPackage() + public function testGetPackage(): void { $packageName = 'babel-core'; $package = $this->yarnLock->getPackage($packageName); - static::assertSame($packageName, $package->getName()); + static::assertEquals($packageName, $package->getName()); $packageVersion = '6.14.0'; $package = $this->yarnLock->getPackage($packageName, $packageVersion); - static::assertSame($packageVersion, $package->getVersion()); + static::assertEquals($packageVersion, $package->getVersion()); $package = $this->yarnLock->getPackage($packageName, '^6.11.4'); - static::assertSame($packageVersion, $package->getVersion()); + static::assertEquals($packageVersion, $package->getVersion()); $package = $this->yarnLock->getPackage('foo'); static::assertNull($package); @@ -70,32 +62,34 @@ public function testGetPackage() /** * The maximal depth of the dependency tree */ - public function testDepth() + public function testDepth(): void { static::assertSame(10, $this->yarnLock->getDepth()); } /** * Helper to stringify packages. - * @param Package[] $packages + * + * @param \Mindscreen\YarnLock\Package[] $packages + * * @return string[] */ - protected function getPackageStrings(array $packages) + protected function getPackageStrings(array $packages): array { return array_values( array_map( - function (Package $p) { + function (Package $p): string { return $p->__toString(); }, - $packages - ) + $packages, + ), ); } /** * The argument syntax should return correct subsets */ - public function testGetPackagesByDepth() + public function testGetPackagesByDepth(): void { $rootPackages = [ $this->yarnLock->getPackage('lodash', '^4.16.2'), @@ -103,14 +97,14 @@ public function testGetPackagesByDepth() ]; $this->yarnLock->calculateDepth($rootPackages); $depth0 = $this->yarnLock->getPackagesByDepth(0); - static::assertSame(count($rootPackages), count($depth0)); + static::assertEquals(count($rootPackages), count($depth0)); $depth1 = $this->yarnLock->getPackagesByDepth(1); $depth2 = $this->yarnLock->getPackagesByDepth(2); $depth12 = $this->yarnLock->getPackagesByDepth(1, 3); static::assertSame(count($depth1) + count($depth2), count($depth12)); - // should not be calculated again + // Should not be calculated again. $this->yarnLock->calculateDepth(); $depthStart = $this->yarnLock->getPackagesByDepth(0, 2); $depthRest = $this->yarnLock->getPackagesByDepth(2, null); @@ -121,10 +115,10 @@ public function testGetPackagesByDepth() /** * Packages can be required in multiple versions, each satisfying certain requirements. */ - public function testGetPackagesByName() + public function testGetPackagesByName(): void { $packages = $this->yarnLock->getPackagesByName('source-map'); - static::assertSame(4, count($packages)); + static::assertCount(4, $packages); $expectedVersions = [ ['^0.4.4'], ['^0.5.0', '^0.5.3', '~0.5.1'], @@ -132,39 +126,44 @@ public function testGetPackagesByName() ['0.1.32'], ]; $versions = array_map( - function (Package $p) { + function (Package $p): array { return $p->getSatisfiedVersions(); }, - $packages + $packages, ); - $versions = array_values($versions); - static::assertSame($expectedVersions, $versions); + + static::assertSame($expectedVersions, array_values($versions)); } /** * The package-name should contain name and actual version for every package */ - public function testPackageString() + public function testPackageString(): void { foreach ($this->yarnLock->getPackages() as $package) { - static::assertSame($package->getName() . '@' . $package->getVersion(), $package->__toString()); + static::assertSame( + $package->getName() . '@' . $package->getVersion(), + $package->__toString(), + ); } } /** - * The package-name should contain name and actual version for every package + * The package-name should contain name and actual version for every package. */ - public function testResolvedSet() + public function testResolvedSet(): void { foreach ($this->yarnLock->getPackages() as $package) { static::assertNotEmpty($package->getResolved()); } } - public function testYarnExample() + /** + * @throws \Mindscreen\YarnLock\ParserException + */ + public function testYarnExample(): void { - $yarnLockContents = static::getInput('deep.txt'); - $yarnLock = YarnLock::fromString($yarnLockContents); - static::assertSame(4, count($yarnLock->getPackages())); + $yarnLock = YarnLock::fromString(static::getInput('deep.txt')); + static::assertCount(4, $yarnLock->getPackages()); } }