From d6eecf0d51c8114ce5e16c3dc0424c98520b171d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 17 Sep 2026 22:29:08 +0200 Subject: [PATCH 1/4] Add duplicated-code CI check via rector/swiss-knife --- .github/workflows/duplicated_code.yaml | 29 ++++++++++++++++++++++++++ composer.json | 1 + 2 files changed, 30 insertions(+) create mode 100644 .github/workflows/duplicated_code.yaml diff --git a/.github/workflows/duplicated_code.yaml b/.github/workflows/duplicated_code.yaml new file mode 100644 index 00000000..2f87364f --- /dev/null +++ b/.github/workflows/duplicated_code.yaml @@ -0,0 +1,29 @@ +name: Duplicated Code + +on: + pull_request: null + push: + branches: + - main + +env: + COMPOSER_ROOT_VERSION: "dev-main" + +jobs: + duplicated_code: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v4 + + - + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + coverage: none + + - uses: "ramsey/composer-install@v2" + + # fails when a large copy-pasted block (>= 150 tokens) is added + - run: composer duplicated-code diff --git a/composer.json b/composer.json index 65e26936..2c79668d 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,7 @@ }, "scripts": { "phpstan": "vendor/bin/phpstan analyse --ansi", + "duplicated-code": "vendor/bin/swiss-knife duplicated-code src rules --min-tokens 150 --min-lines 5", "rector": "vendor/bin/rector --ansi", "check-cs": "vendor/bin/ecs check --ansi", "fix-cs": "vendor/bin/ecs check --fix --ansi" From 0ec94f249b879639d8277500b40d01f639b93c4a Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 17 Sep 2026 20:29:48 +0000 Subject: [PATCH 2/4] [rector] Rector fixes --- .../MethodCall/DoctrineQueryBuilderSortDirectionRector.php | 4 +++- .../Attribute/DoctrineOrderByAttributeSortDirectionRector.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/rules/Orm32/Rector/MethodCall/DoctrineQueryBuilderSortDirectionRector.php b/rules/Orm32/Rector/MethodCall/DoctrineQueryBuilderSortDirectionRector.php index 363281d3..05285e51 100644 --- a/rules/Orm32/Rector/MethodCall/DoctrineQueryBuilderSortDirectionRector.php +++ b/rules/Orm32/Rector/MethodCall/DoctrineQueryBuilderSortDirectionRector.php @@ -4,6 +4,7 @@ namespace Rector\Doctrine\Orm32\Rector\MethodCall; +use PhpParser\Node\Expr; use PhpParser\Node; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\MethodCall; @@ -131,7 +132,7 @@ private function isTargetType(Node $node, string $className): bool /** * Extracts a normalized 'asc' or 'desc' string from Strings, Constants */ - private function resolveSortDirectionValue(Node\Expr $expr): ?string + private function resolveSortDirectionValue(Expr $expr): ?string { if ($expr instanceof ClassConstFetch) { $constName = $this->getName($expr->name); @@ -141,6 +142,7 @@ private function resolveSortDirectionValue(Node\Expr $expr): ?string if (in_array($normalized, ['asc', 'ascending'], true)) { return 'asc'; } + if (in_array($normalized, ['desc', 'descending'], true)) { return 'desc'; } diff --git a/rules/Orm37/Rector/Attribute/DoctrineOrderByAttributeSortDirectionRector.php b/rules/Orm37/Rector/Attribute/DoctrineOrderByAttributeSortDirectionRector.php index d43034c2..92378894 100644 --- a/rules/Orm37/Rector/Attribute/DoctrineOrderByAttributeSortDirectionRector.php +++ b/rules/Orm37/Rector/Attribute/DoctrineOrderByAttributeSortDirectionRector.php @@ -4,6 +4,7 @@ namespace Rector\Doctrine\Orm37\Rector\Attribute; +use PhpParser\Node\Expr; use PhpParser\Node; use PhpParser\Node\Attribute; use PhpParser\Node\Expr\Array_; @@ -103,7 +104,7 @@ public function refactor(Node $node): ?Node return $hasChanged ? $node : null; } - private function resolveSortDirectionValue(Node\Expr $expr): ?string + private function resolveSortDirectionValue(Expr $expr): ?string { if ($expr instanceof ClassConstFetch) { $constName = $this->getName($expr->name); @@ -113,6 +114,7 @@ private function resolveSortDirectionValue(Node\Expr $expr): ?string if (in_array($normalized, ['asc', 'ascending'], true)) { return 'asc'; } + if (in_array($normalized, ['desc', 'descending'], true)) { return 'desc'; } From 79bdddd5eeba6c080972e5deb7061e95ed077b33 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 17 Sep 2026 23:02:43 +0200 Subject: [PATCH 3/4] Require rector/swiss-knife ^2.5 for duplicated-code command --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2c79668d..f761c97b 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "phpunit/phpunit": "^13.3", "rector/jack": "^1.1", "rector/rector-src": "dev-main", - "rector/swiss-knife": "^2.4", + "rector/swiss-knife": "^2.5", "symplify/phpstan-rules": "^14.12", "tomasvotruba/class-leak": "^2.1.8", "tomasvotruba/type-coverage": "^2.3", From 8c420f48a2b220fd598263bfcfe6ec21b022fd91 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 18 Sep 2026 00:22:00 +0200 Subject: [PATCH 4/4] Bump rector/swiss-knife to ^2.6 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f761c97b..63e62d36 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "phpunit/phpunit": "^13.3", "rector/jack": "^1.1", "rector/rector-src": "dev-main", - "rector/swiss-knife": "^2.5", + "rector/swiss-knife": "^2.6", "symplify/phpstan-rules": "^14.12", "tomasvotruba/class-leak": "^2.1.8", "tomasvotruba/type-coverage": "^2.3",