From e7a0ab180a90972a7f7b32469b84ea81d36db307 Mon Sep 17 00:00:00 2001 From: lotyp Date: Wed, 5 Jun 2024 20:30:07 +0300 Subject: [PATCH] ci: add psalm static analysis test: separate phpunit and pest tests test: add arch pest tests deps: add support for rector --- .github/workflows/static-analysis.yml | 63 ++++++++- .phive/phars.xml | 2 +- .pre-commit-config.yaml | 3 +- Makefile | 23 +++- README.md | 48 +++---- composer.json | 47 ++++--- composer.lock | 175 +++++++++++++++++-------- pest.xml.dist | 26 ++++ phpstan.neon.dist | 2 + phpunit.xml.dist | 12 +- psalm-baseline.xml | 37 ++++++ psalm.xml | 3 + rector.php | 29 ++++ src/ConfigBuilder.php | 2 +- tests/Arch/DebugTest.php | 8 ++ tests/Unit/ConfigBuilderTest.php | 84 ++++++++---- tests/Unit/RuleSets/DefaultSetTest.php | 51 +++++++ 17 files changed, 480 insertions(+), 135 deletions(-) create mode 100644 pest.xml.dist create mode 100644 psalm-baseline.xml create mode 100644 rector.php create mode 100644 tests/Arch/DebugTest.php create mode 100644 tests/Unit/RuleSets/DefaultSetTest.php diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index f7e9ca7..ca1186d 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -5,28 +5,32 @@ on: # yamllint disable-line rule:truthy branches: - master paths: + - 'phpstan*' + - 'psalm*' + - 'composer.*' - 'src/**' - 'tests/**' - - 'bin/trap' - '.php-cs-fixer.dist.php' pull_request: branches: - master paths: + - 'phpstan*' + - 'psalm*' + - 'composer.*' - 'src/**' - 'tests/**' - - 'bin/trap' - '.php-cs-fixer.dist.php' name: ๐Ÿ” Static analysis jobs: - static-analysis: + phpstan: timeout-minutes: 4 runs-on: ${{ matrix.os }} concurrency: cancel-in-progress: true - group: static-analysis-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: phpstan-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} strategy: fail-fast: true matrix: @@ -71,3 +75,54 @@ jobs: - name: ๐Ÿ” Run static analysis using phpstan/phpstan run: composer stan:ci + + psalm: + timeout-minutes: 4 + runs-on: ${{ matrix.os }} + concurrency: + cancel-in-progress: true + group: psalm-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + strategy: + fail-fast: true + matrix: + os: + - ubuntu-latest + php-version: + - '8.1' + dependencies: + - locked + steps: + - name: ๐Ÿ“ฆ Check out the codebase + uses: actions/checkout@v4.1.6 + + - name: ๐Ÿ› ๏ธ Setup PHP + uses: shivammathur/setup-php@2.30.4 + with: + php-version: ${{ matrix.php-version }} + extensions: none, ctype, curl, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, opcache, pcntl, posix + ini-values: error_reporting=E_ALL + coverage: xdebug + + - name: ๐Ÿ› ๏ธ Setup problem matchers + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: ๐Ÿค– Validate composer.json and composer.lock + run: composer validate --ansi --strict + + - name: ๐Ÿ” Get composer cache directory + uses: wayofdev/gh-actions/actions/composer/get-cache-directory@v3.1.0 + + - name: โ™ป๏ธ Restore cached dependencies installed with composer + uses: actions/cache@v4.0.2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('composer.lock') }} + restore-keys: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}- + + - name: ๐Ÿ“ฅ Install "${{ matrix.dependencies }}" dependencies + uses: wayofdev/gh-actions/actions/composer/install@v3.1.0 + with: + dependencies: ${{ matrix.dependencies }} + + - name: ๐Ÿ” Run static analysis using vimeo/psalm + run: composer psalm:ci diff --git a/.phive/phars.xml b/.phive/phars.xml index 2cd554e..4fef9af 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,5 +1,5 @@ - + diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d7bb7ee..6497c27 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,6 +29,7 @@ repos: description: Run markdownlint-cli2 on your Markdown files using the docker image language: docker_image types: [markdown] - entry: davidanson/markdownlint-cli2-rules:latest + entry: 'davidanson/markdownlint-cli2-rules:latest' + args: ['--config', '.github/.markdownlint.json'] ... diff --git a/Makefile b/Makefile index c2561f5..976dcef 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ ENVSUBST ?= $(BUILDER) envsubst YAML_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ -v $(PWD):/data \ cytopia/yamllint:latest \ + -c ./.github/.yamllint.yaml \ -f colored . ACTION_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ @@ -47,7 +48,8 @@ ACTION_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ MARKDOWN_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ -v $(shell pwd):/app \ --workdir /app \ - davidanson/markdownlint-cli2-rules:latest + davidanson/markdownlint-cli2-rules:latest \ + --config ".github/.markdownlint.json" PHIVE_RUNNER ?= $(DOCKER_COMPOSE) run --rm --no-deps app @@ -94,9 +96,9 @@ help: ## Show this menu @echo @echo ' ๐Ÿ“‘ Logs are stored in $(MAKE_LOGFILE)' @echo - @echo ' ๐Ÿ“ฆ Package php-cs-fixer-config (github.com/wayofdev/php-cs-fixer-config)' - @echo ' ๐Ÿค  Makefile Author Andrij Orlenko (github.com/lotyp)' - @echo ' ๐Ÿข ${YELLOW}Org wayofdev (github.com/wayofdev)${RST}' + @echo ' ๐Ÿ“ฆ Package php-cs-fixer-config (https://github.com/wayofdev/php-cs-fixer-config)' + @echo ' ๐Ÿค  Makefile Author Andrij Orlenko (https://github.com/lotyp)' + @echo ' ๐Ÿข ${YELLOW}Org wayofdev (https://github.com/wayofdev)${RST}' @echo .PHONY: help @@ -140,6 +142,10 @@ down: # Stops and removes containers of this project $(DOCKER_COMPOSE) down --remove-orphans --volumes .PHONY: down +stop: ## Stops all containers, without removing them + $(DOCKER_COMPOSE) stop +.PHONY: stop + restart: down up ## Runs down and up commands .PHONY: restart @@ -267,10 +273,17 @@ infect-ci: ## Runs infection โ€“ mutation testing framework with github output ( $(APP_COMPOSER) infect:ci .PHONY: lint-infect-ci -test: ## Run project php-unit and pest tests +test: test-unit test-arch ## Run project php-unit and pest tests +.PHONY: test + +test-unit: ## Run project php-unit tests $(APP_COMPOSER) test .PHONY: test +test-arch: ## Run project pest tests with architecture checks + $(APP_COMPOSER) test:arch +.PHONY: test-arch + test-cc: ## Run project php-unit and pest tests in coverage mode and build report $(APP_COMPOSER) test:cc .PHONY: test-cc diff --git a/README.md b/README.md index 74f254e..af371b1 100644 --- a/README.md +++ b/README.md @@ -73,30 +73,30 @@ composer req --dev wayofdev/cs-fixer-config ```php inDir(__DIR__ . '/src') ->inDir(__DIR__ . '/tests') ->addFiles([__FILE__]) ->getConfig() ; - + $config->setCacheFile(__DIR__ . '/.build/php-cs-fixer/php-cs-fixer.cache'); - + return $config; ``` ### โ†’ Composer Script * Add `scripts` section to `composer.json`: - + ```diff { "scripts": { @@ -126,11 +126,11 @@ composer req --dev wayofdev/cs-fixer-config +prepare: + mkdir -p .build/php-cs-fixer +.PHONY: prepare - + +lint-php: prepare ## Fixes code to follow coding standards using php-cs-fixer + $(APP_COMPOSER) cs:fix +.PHONY: lint-php - + +lint-diff: prepare ## Runs php-cs-fixer in dry-run mode and shows diff which will by applied + $(APP_COMPOSER) cs:diff +.PHONY: lint-diff @@ -148,7 +148,7 @@ composer req --dev wayofdev/cs-fixer-config ```yaml --- - + on: # yamllint disable-line rule:truthy pull_request: branches: @@ -156,9 +156,9 @@ composer req --dev wayofdev/cs-fixer-config push: branches: - master - + name: ๐Ÿงน Fix PHP coding standards - + jobs: coding-standards: timeout-minutes: 4 @@ -181,7 +181,7 @@ composer req --dev wayofdev/cs-fixer-config run: | git config --global core.autocrlf false git config --global core.eol lf - + - name: ๐Ÿ› ๏ธ Setup PHP uses: shivammathur/setup-php@2.30.4 with: @@ -189,40 +189,40 @@ composer req --dev wayofdev/cs-fixer-config extensions: none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter ini-values: error_reporting=E_ALL coverage: none - + - name: ๐Ÿ“ฆ Check out the codebase uses: actions/checkout@v4.1.5 - + - name: ๐Ÿ› ๏ธ Setup problem matchers run: | echo "::add-matcher::${{ runner.tool_cache }}/php.json" - + - name: ๐Ÿค– Validate composer.json and composer.lock run: composer validate --ansi --strict - + - name: ๐Ÿ” Get composer cache directory uses: wayofdev/gh-actions/actions/composer/get-cache-directory@v3.1.0 - + - name: โ™ป๏ธ Restore cached dependencies installed with composer uses: actions/cache@v4.0.2 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('composer.lock') }} restore-keys: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}- - + - name: ๐Ÿ“ฅ Install "${{ matrix.dependencies }}" dependencies with composer uses: wayofdev/gh-actions/actions/composer/install@v3.1.0 with: dependencies: ${{ matrix.dependencies }} - + - name: ๐Ÿ› ๏ธ Prepare environment run: make prepare - + - name: ๐Ÿšจ Run coding standards task run: composer cs:fix env: PHP_CS_FIXER_IGNORE_ENV: true - + - name: ๐Ÿ“ค Commit and push changed files back to GitHub uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: @@ -278,7 +278,7 @@ To use via composer script commands: * Runs php-cs-fixer in dry-run mode and shows diff which will by applied: ```bash - make lint-diff + make lint-diff ```
@@ -320,7 +320,7 @@ You are more than welcome. Before contributing, kindly check our [contribution g * **Discord:** Join our community on [Discord](https://discord.gg/CE3TcCC5vr).

- Codecov + Discord Link Follow on Twitter (X)

diff --git a/composer.json b/composer.json index 5dbdf80..d304c4f 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,7 @@ "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "~0.19.0", + "rector/rector": "^1.1", "roave/infection-static-analysis-plugin": "^1.35", "vimeo/psalm": "^5.23.1" }, @@ -49,7 +50,7 @@ }, "autoload-dev": { "psr-4": { - "WayOfDev\\PhpCsFixer\\Config\\Tests\\": "tests/" + "WayOfDev\\Tests\\": "tests/" } }, "config": { @@ -74,19 +75,35 @@ } }, "scripts": { - "cs:diff": "php vendor/bin/php-cs-fixer fix --dry-run -v --diff", - "cs:fix": "php vendor/bin/php-cs-fixer fix -v", - "infect": "XDEBUG_MODE=coverage php vendor/bin/roave-infection-static-analysis-plugin --configuration=infection.json.dist", - "infect:ci": "XDEBUG_MODE=coverage php vendor/bin/roave-infection-static-analysis-plugin --ansi --configuration=infection.json.dist --logger-github --ignore-msi-with-no-mutations --only-covered", - "psalm": "php vendor/bin/psalm --show-info=true", - "psalm:baseline": "php vendor/bin/psalm --set-baseline=psalm-baseline.xml", - "psalm:ci": "php vendor/bin/psalm --output-format=github --shepherd --show-info=false --stats --threads=4", - "refactor": "php vendor/bin/rector process --config=rector.php", - "refactor:ci": "php vendor/bin/rector process --config=rector.php --dry-run --ansi", - "stan": "php vendor/bin/phpstan analyse --memory-limit=2G", - "stan:baseline": "php vendor/bin/phpstan analyse --generate-baseline --memory-limit=2G --allow-empty-baseline", - "stan:ci": "php vendor/bin/phpstan analyse --memory-limit=2G --error-format=github", - "test": "XDEBUG_MODE=coverage php vendor/bin/pest", - "test:cc": "XDEBUG_MODE=coverage php vendor/bin/pest --coverage --coverage-clover=.build/phpunit/logs/clover.xml" + "cs:diff": "php-cs-fixer fix --dry-run -v --diff", + "cs:fix": "php-cs-fixer fix -v", + "infect": [ + "@putenv XDEBUG_MODE=coverage", + "roave-infection-static-analysis-plugin" + ], + "infect:ci": [ + "@putenv XDEBUG_MODE=coverage", + "roave-infection-static-analysis-plugin --ansi --logger-github --ignore-msi-with-no-mutations --only-covered" + ], + "psalm": "psalm --show-info=true", + "psalm:baseline": "psalm --set-baseline=psalm-baseline.xml", + "psalm:ci": "psalm --output-format=github --shepherd --show-info=false --stats --threads=4", + "refactor": "rector process --config=rector.php", + "refactor:ci": "rector process --config=rector.php --dry-run --ansi", + "stan": "phpstan analyse --memory-limit=2G", + "stan:baseline": "phpstan analyse --generate-baseline --memory-limit=2G --allow-empty-baseline", + "stan:ci": "phpstan analyse --memory-limit=2G --error-format=github", + "test": [ + "@putenv XDEBUG_MODE=coverage", + "pest --color=always" + ], + "test:arch": [ + "@putenv XDEBUG_MODE=coverage", + "pest --color=always --configuration pest.xml.dist" + ], + "test:cc": [ + "@putenv XDEBUG_MODE=coverage", + "pest --coverage --coverage-clover=.build/phpunit/logs/clover.xml" + ] } } diff --git a/composer.lock b/composer.lock index 63af873..9e71589 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b60b9cd5d95ddd26be3daf5a9b097dbf", + "content-hash": "f383c748c9c365420e939e598f62a637", "packages": [ { "name": "clue/ndjson-react", @@ -1248,16 +1248,16 @@ }, { "name": "symfony/console", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f" + "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", - "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "url": "https://api.github.com/repos/symfony/console/zipball/be5854cee0e8c7b110f00d695d11debdfa1a2a91", + "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91", "shasum": "" }, "require": { @@ -1322,7 +1322,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.7" + "source": "https://github.com/symfony/console/tree/v6.4.8" }, "funding": [ { @@ -1338,7 +1338,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1409,16 +1409,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f" + "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d84384f3f67de3cb650db64d685d70395dacfc3f", - "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", + "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", "shasum": "" }, "require": { @@ -1469,7 +1469,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.7" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" }, "funding": [ { @@ -1485,7 +1485,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1565,23 +1565,25 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "78dde75f8f6dbbca4ec436a4b0087f7af02076d4" + "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/78dde75f8f6dbbca4ec436a4b0087f7af02076d4", - "reference": "78dde75f8f6dbbca4ec436a4b0087f7af02076d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d37529150e7081c51b3c5d5718c55a04a9503f3", + "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3", "shasum": "" }, "require": { "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/process": "^5.4|^6.4" + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -1609,7 +1611,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.7" + "source": "https://github.com/symfony/filesystem/tree/v6.4.8" }, "funding": [ { @@ -1625,20 +1627,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/finder", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "511c48990be17358c23bf45c5d71ab85d40fb764" + "reference": "3ef977a43883215d560a2cecb82ec8e62131471c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/511c48990be17358c23bf45c5d71ab85d40fb764", - "reference": "511c48990be17358c23bf45c5d71ab85d40fb764", + "url": "https://api.github.com/repos/symfony/finder/zipball/3ef977a43883215d560a2cecb82ec8e62131471c", + "reference": "3ef977a43883215d560a2cecb82ec8e62131471c", "shasum": "" }, "require": { @@ -1673,7 +1675,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.7" + "source": "https://github.com/symfony/finder/tree/v6.4.8" }, "funding": [ { @@ -1689,20 +1691,20 @@ "type": "tidelift" } ], - "time": "2024-04-23T10:36:43+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed" + "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9a3c92b490716ba6771f5beced13c6eda7183eed", - "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", + "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", "shasum": "" }, "require": { @@ -1740,7 +1742,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.7" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.8" }, "funding": [ { @@ -1756,7 +1758,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2234,16 +2236,16 @@ }, { "name": "symfony/process", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "cdb1c81c145fd5aa9b0038bab694035020943381" + "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381", - "reference": "cdb1c81c145fd5aa9b0038bab694035020943381", + "url": "https://api.github.com/repos/symfony/process/zipball/8d92dd79149f29e89ee0f480254db595f6a6a2c5", + "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5", "shasum": "" }, "require": { @@ -2275,7 +2277,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.7" + "source": "https://github.com/symfony/process/tree/v6.4.8" }, "funding": [ { @@ -2291,7 +2293,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/service-contracts", @@ -2378,16 +2380,16 @@ }, { "name": "symfony/stopwatch", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "ffec95ba269e541eb2232126c0c20f83086b5c68" + "reference": "63e069eb616049632cde9674c46957819454b8aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ffec95ba269e541eb2232126c0c20f83086b5c68", - "reference": "ffec95ba269e541eb2232126c0c20f83086b5c68", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/63e069eb616049632cde9674c46957819454b8aa", + "reference": "63e069eb616049632cde9674c46957819454b8aa", "shasum": "" }, "require": { @@ -2420,7 +2422,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.7" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.8" }, "funding": [ { @@ -2436,20 +2438,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { "name": "symfony/string", - "version": "v6.4.7", + "version": "v6.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69" + "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69", - "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69", + "url": "https://api.github.com/repos/symfony/string/zipball/a147c0f826c4a1f3afb763ab8e009e37c877a44d", + "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d", "shasum": "" }, "require": { @@ -2506,7 +2508,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.7" + "source": "https://github.com/symfony/string/tree/v6.4.8" }, "funding": [ { @@ -2522,7 +2524,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-05-31T14:49:08+00:00" } ], "packages-dev": [ @@ -4720,16 +4722,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.29.0", + "version": "1.29.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc" + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/536889f2b340489d328f5ffb7b02bb6b183ddedc", - "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", "shasum": "" }, "require": { @@ -4761,9 +4763,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" }, - "time": "2024-05-06T12:04:23+00:00" + "time": "2024-05-31T08:52:43+00:00" }, { "name": "phpstan/phpstan", @@ -5453,6 +5455,65 @@ }, "time": "2024-03-15T10:43:15+00:00" }, + { + "name": "rector/rector", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "556509e2dcf527369892b7d411379c4a02f31859" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/556509e2dcf527369892b7d411379c4a02f31859", + "reference": "556509e2dcf527369892b7d411379c4a02f31859", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.11" + }, + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "suggest": { + "ext-dom": "To manipulate phpunit.xml via the custom-rule command" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" + ], + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2024-05-18T09:40:27+00:00" + }, { "name": "roave/infection-static-analysis-plugin", "version": "1.35.0", diff --git a/pest.xml.dist b/pest.xml.dist new file mode 100644 index 0000000..bfbd448 --- /dev/null +++ b/pest.xml.dist @@ -0,0 +1,26 @@ + + + + + + + + tests/Arch + + + + + src + + + diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 50c0f68..aa4c93c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -7,4 +7,6 @@ parameters: - src/ - tests/ - .php-cs-fixer.dist.php + excludePaths: + - tests/Arch tmpDir: .build/phpstan/ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 553c878..5f7902e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,19 +1,21 @@ + stderr="true" + beStrictAboutOutputDuringTests="true" +> - - tests + + tests/Unit @@ -28,7 +30,7 @@ - src + src diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 0000000..e12f68e --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + builder->getConfig()->getFinder()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/psalm.xml b/psalm.xml index 7fc22c7..f6563a6 100644 --- a/psalm.xml +++ b/psalm.xml @@ -18,6 +18,9 @@ + + + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..0abcf0d --- /dev/null +++ b/rector.php @@ -0,0 +1,29 @@ +cacheDirectory(__DIR__ . '/.build/rector/'); + + $rectorConfig->paths([ + __DIR__ . '/src/', + __DIR__ . '/tests/', + __DIR__ . '/.php-cs-fixer.dist.php', + __DIR__ . '/rector.php', + ]); + + $rectorConfig->phpVersion(ValueObject\PhpVersion::PHP_81); + + $rectorConfig->rules([ + Php81\Rector\Property\ReadOnlyPropertyRector::class, + ]); + + $rectorConfig->sets([ + PHPUnit\Set\PHPUnitSetList::PHPUNIT_100, + ]); +}; diff --git a/src/ConfigBuilder.php b/src/ConfigBuilder.php index af398df..69479a1 100644 --- a/src/ConfigBuilder.php +++ b/src/ConfigBuilder.php @@ -22,7 +22,7 @@ */ final class ConfigBuilder { - private Config $config; + private readonly Config $config; private function __construct(private readonly RuleSet $ruleSet) { diff --git a/tests/Arch/DebugTest.php b/tests/Arch/DebugTest.php new file mode 100644 index 0000000..4f0a096 --- /dev/null +++ b/tests/Arch/DebugTest.php @@ -0,0 +1,8 @@ +expect(['trap', 'dd', 'dump', 'exit', 'die', 'print_r', 'var_dump', 'echo', 'print']) + ->not + ->toBeUsed(); diff --git a/tests/Unit/ConfigBuilderTest.php b/tests/Unit/ConfigBuilderTest.php index 6459457..0802071 100644 --- a/tests/Unit/ConfigBuilderTest.php +++ b/tests/Unit/ConfigBuilderTest.php @@ -2,10 +2,12 @@ declare(strict_types=1); -namespace WayOfDev\PhpCsFixer\Config\Tests\Unit; +namespace WayOfDev\Tests\Unit; +use BadMethodCallException; use LogicException; use PhpCsFixer\Config; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use SplFileInfo; use WayOfDev\PhpCsFixer\Config\ConfigBuilder; @@ -24,9 +26,7 @@ protected function setUp(): void $this->builder = ConfigBuilder::createFromRuleSet(new DefaultSet()); } - /** - * @test - */ + #[Test] public function it_retrieves_default_options(): void { $config = $this->builder->getConfig(); @@ -36,9 +36,7 @@ public function it_retrieves_default_options(): void self::assertTrue($config->getUsingCache()); } - /** - * @test - */ + #[Test] public function it_overrides_default_options(): void { /** @var Config $config */ @@ -52,9 +50,7 @@ public function it_overrides_default_options(): void self::assertFalse($config->getUsingCache()); } - /** - * @test - */ + #[Test] public function it_has_no_directories_by_default(): void { $this->expectException(LogicException::class); @@ -62,9 +58,7 @@ public function it_has_no_directories_by_default(): void [...$this->builder->getConfig()->getFinder()]; } - /** - * @test - */ + #[Test] public function it_adds_directories(): void { $finder = $this->builder @@ -80,9 +74,7 @@ public function it_adds_directories(): void self::assertContains(realpath(__DIR__ . '/../../src/ConfigBuilder.php'), $items); } - /** - * @test - */ + #[Test] public function it_adds_files(): void { $finder = $this->builder @@ -97,9 +89,7 @@ public function it_adds_files(): void self::assertContains(__FILE__, $items); } - /** - * @test - */ + #[Test] public function it_adds_default_rules(): void { $rules = $this->builder @@ -114,9 +104,7 @@ public function it_adds_default_rules(): void self::assertEmpty(array_diff_assoc($expected, $rules)); } - /** - * @test - */ + #[Test] public function it_overrides_default_rules(): void { $rules = ConfigBuilder::createFromRuleSet(new DefaultSet(['@Symfony' => false])) @@ -131,6 +119,58 @@ public function it_overrides_default_rules(): void self::assertEmpty(array_diff_assoc($expected, $rules)); } + #[Test] + public function it_excludes_directories(): void + { + $finder = $this->builder + ->exclude([__DIR__ . '/../../src/RuleSets']) + ->inDir(__DIR__ . '/../../src') + ->getConfig() + ->getFinder() + ; + + $items = $this->finderToArray($finder); + + self::assertNotContains(__DIR__ . '/../../src/RuleSets/DefaultSet.php', $items); + } + + #[Test] + public function it_calls_methods_on_config(): void + { + $config = $this->builder + ->setRiskyAllowed(false) + ->getConfig() + ; + + self::assertFalse($config->getRiskyAllowed()); + } + + #[Test] + public function it_throws_exception_on_invalid_method_call(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Method "PhpCsFixer\Config::invalidMethod" does not exists.'); + + // @phpstan-ignore-next-line + $this->builder->invalidMethod(); + } + + #[Test] + public function it_sets_parallel_config_with_custom_parameters(): void + { + /** @var Config $config */ + $config = $this->builder + ->useParallelConfig(4, 10, 600) + ->getConfig() + ; + + $parallelConfig = $config->getParallelConfig(); + + self::assertSame(4, $parallelConfig->getMaxProcesses()); + self::assertSame(10, $parallelConfig->getFilesPerProcess()); + self::assertSame(600, $parallelConfig->getProcessTimeout()); + } + /** * @param iterable $finder * diff --git a/tests/Unit/RuleSets/DefaultSetTest.php b/tests/Unit/RuleSets/DefaultSetTest.php new file mode 100644 index 0000000..40c4377 --- /dev/null +++ b/tests/Unit/RuleSets/DefaultSetTest.php @@ -0,0 +1,51 @@ +name()); + } + + #[Test] + public function it_allows_risky_rules(): void + { + $ruleSet = new DefaultSet(); + + self::assertTrue($ruleSet->allowRisky()); + } + + #[Test] + public function it_merges_custom_rules_with_default_rules(): void + { + $customRules = [ + '@Symfony' => false, + 'custom_rule' => true, + ]; + + $ruleSet = new DefaultSet($customRules); + + $rules = $ruleSet->rules(); + + $expectedRules = [ + '@Symfony' => false, + 'custom_rule' => true, + ]; + + self::assertArrayHasKey('custom_rule', $rules); + self::assertEmpty(array_diff_assoc($expectedRules, $rules)); + } +}