Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(make:*)"
]
}
}
4 changes: 2 additions & 2 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

Expand All @@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
on:
pull_request:
push:
branches:
- master

name: "Validate"

jobs:
composer-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: shivammathur/setup-php@v2
with:
php-version: "8.3"

- run: composer validate --strict

tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version:
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
- "8.4"
dependencies:
- lowest
- highest
steps:
- uses: actions/checkout@v4

- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}

- run: composer update --no-interaction --no-progress ${{ matrix.dependencies == 'lowest' && '--prefer-lowest' || '' }}

- run: vendor/bin/phpunit
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.build/
.idea
vendor
composer.lock
.php-cs-fixer.cache
composer.lock
vendor
7 changes: 2 additions & 5 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<?php declare(strict_types=1);

use PhpCsFixer\Finder;
use function MLL\PhpCsFixerConfig\risky;

$finder = Finder::create()
$finder = PhpCsFixer\Finder::create()
->notPath('vendor')
->in(__DIR__)
->name('*.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return risky($finder);
return MLL\PhpCsFixerConfig\risky($finder);
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.PHONY: it
it: fix normalize ## Perform quality checks
it: fix normalize test ## Perform quality checks

.PHONY: help
help: ## Displays this list of targets with descriptions
Expand All @@ -16,5 +16,10 @@ fix: ## Format PHP
normalize: ## Normalize composer.json
composer normalize

.PHONY: test
test: ## Run PHPUnit tests
mkdir --parent .build/phpunit
vendor/bin/phpunit --cache-directory=.build/phpunit

vendor: composer.json ## Install dependencies through composer
composer install
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"kubawerlos/php-cs-fixer-custom-fixers": "^3.12"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.13"
"ergebnis/composer-normalize": "^2.13",
"phpunit/phpunit": "^9.6 || ^10.5 || ^11.0"
},
"autoload": {
"psr-4": {
Expand All @@ -29,6 +30,11 @@
"config.php"
]
},
"autoload-dev": {
"psr-4": {
"MLL\\PhpCsFixerConfig\\Tests\\": "tests/"
}
},
"config": {
"allow-plugins": {
"ergebnis/composer-normalize": true
Expand Down
5 changes: 5 additions & 0 deletions config.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,18 @@ function config(Finder $finder, array $ruleOverrides = []): Config
'less_and_greater' => false,
],

Fixer\PhpdocSimplifyArrayKeyFixer::NAME => true,

PhpCsFixerCustomFixers\Fixer\ConstructorEmptyBracesFixer::name() => true,
PhpCsFixerCustomFixers\Fixer\DeclareAfterOpeningTagFixer::name() => true, // Use native rule when added with https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues/2062
PhpCsFixerCustomFixers\Fixer\MultilinePromotedPropertiesFixer::name() => true,
];

return (new Config())
->registerCustomFixers(new PhpCsFixerCustomFixers\Fixers())
->registerCustomFixers([
new Fixer\PhpdocSimplifyArrayKeyFixer(),
])
->setFinder($finder)
->setRules(array_merge($safeRules, $ruleOverrides));
}
Expand Down
13 changes: 13 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
62 changes: 62 additions & 0 deletions src/Fixer/PhpdocSimplifyArrayKeyFixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php declare(strict_types=1);

namespace MLL\PhpCsFixerConfig\Fixer;

use PhpCsFixer\AbstractPhpdocTypesFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Tokens;

/**
* Simplifies PHPDoc definitions to array<T>, omitting explicit array-key defaults.
*/
final class PhpdocSimplifyArrayKeyFixer extends AbstractPhpdocTypesFixer
{
public const NAME = 'MLL/phpdoc_simplify_array_key';

public function getName(): string
{
return self::NAME;
}

public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'PHPDoc `array<T>` should be used instead of `array<array-key, T>`.',
[
new CodeSample(
<<<'PHP'
<?php
/**
* @param array<array-key, string> $x
* @param array<string|int, Foo> $y
* @return array<int|string, Foo>
*/

PHP
),
]
);
}

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_DOC_COMMENT);
}

protected function normalize(string $type): string
{
// Match: array<array-key, T> or array<int|string, T> or array<string|int, T>
// Uses [^\S\n]* (whitespace except newlines) to avoid matching multiline types,
// which are not supported due to AbstractPhpdocTypesFixer requiring line count preservation.
$ws = '[^\S\n]*'; // Whitespace except newlines

return Preg::replace(
"/\\barray<{$ws}(?:array-key|int{$ws}\\|{$ws}string|string{$ws}\\|{$ws}int){$ws},{$ws}/",
'array<',
$type
);
}
}
Loading