Skip to content

[0.x] Adds support for specifying custom rules in pint.json #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
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
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,36 @@ However, if you wish, you may enable or disable specific rules in your `pint.jso

Pint is built on top of [PHP-CS-Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer). Therefore, you may use any of its rules to fix code style issues in your project: [PHP-CS-Fixer Configurator](https://mlocati.github.io/php-cs-fixer-configurator/).

### Custom Fixers

If you have your own custom rules that you have created as per PHP-CS-Fixer's [documentation](https://cs.symfony.com/doc/custom_rules.html), you may enable them in
Pint using the `fixers` configuration option:

```json
{
"fixers": [
"App\\Fixers\\ExceptionSuffixFixer"
]
}
```

If you wish to configure options for a custom fixer, you may do so from the `rules` option:

```json
{
"fixers": [
"App\\Fixers\\ExceptionSuffixFixer"
],
"rules": {
"Fixers/ExceptionSuffixFixer": {
"suffix": "Exception"
}
}
}
```

The key for the rule should match the return value of the `getName` method in your custom fixer.

<a name="exclude-folders"></a>
### Exclude Folders

Expand Down
12 changes: 11 additions & 1 deletion app/Factories/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Support\Project;
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
use PhpCsFixer\Fixer\FixerInterface;

class ConfigurationFactory
{
Expand Down Expand Up @@ -60,9 +61,18 @@ public static function preset($rules)
$finder->{$method}($arguments);
}

$fixers = array_map(fn (string $fixer) => new $fixer(), $localConfiguration->fixers());

$rules = array_merge(
array_fill_keys(array_map(fn (FixerInterface $fixer) => $fixer->getName(), $fixers), true),
$rules,
$localConfiguration->rules(),
);

return (new Config())
->setFinder($finder)
->setRules(array_merge($rules, $localConfiguration->rules()))
->registerCustomFixers($fixers)
->setRules($rules)
->setRiskyAllowed(true)
->setUsingCache(true)
->registerCustomFixers([
Expand Down
10 changes: 10 additions & 0 deletions app/Repositories/ConfigurationJsonRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public function rules()
return $this->get()['rules'] ?? [];
}

/**
* Gets a list of custom rules to use.
*
* @return array<int, string>
*/
public function fixers()
{
return $this->get()['fixers'] ?? [];
}

/**
* Gets the preset option.
*
Expand Down
14 changes: 14 additions & 0 deletions tests/Feature/CustomFixersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

it('runs custom fixers', function () {
[$statusCode, $output] = run('default', [
'path' => base_path('tests/Fixtures/fixers'),
]);

expect($statusCode)->toBe(1)
->and($output->fetch())
->toContain('FAIL')
->toContain('1 file, 1 style issue')
->toContain('⨯ tests/Fixtures/fixers/empty.php')
->toContain('Laravel/test_custom_fixer');
});
7 changes: 7 additions & 0 deletions tests/Fixtures/fixers/empty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

/**
* This file should be emptied by the TestCustomFixer rule.
*/

var_dump('foo bar');
5 changes: 5 additions & 0 deletions tests/Fixtures/fixers/pint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"fixers": [
"Tests\\Mocks\\TestCustomFixer"
]
}
50 changes: 50 additions & 0 deletions tests/Mocks/TestCustomFixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Tests\Mocks;

use PhpCsFixer\Fixer\FixerInterface;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo;

class TestCustomFixer implements FixerInterface
{
public function isCandidate(Tokens $tokens): bool
{
return true;
}

public function isRisky(): bool
{
return true;
}

public function fix(SplFileInfo $file, Tokens $tokens): void
{
$tokens->clearRange(0, $tokens->count() - 1);
}

public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Removes all code in files called empty.php',
[]
);
}

public function getName(): string
{
return "Laravel/test_custom_fixer";
}

public function getPriority(): int
{
return 0;
}

public function supports(SplFileInfo $file): bool
{
return $file->getFilename() === 'empty.php';
}
}
9 changes: 9 additions & 0 deletions tests/Unit/Repositories/ConfigurationJsonRepositoryTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use App\Repositories\ConfigurationJsonRepository;
use Tests\Mocks\TestCustomFixer;

it('works without json file', function () {
$repository = new ConfigurationJsonRepository(null, 'psr12');
Expand Down Expand Up @@ -32,3 +33,11 @@

expect($repository->preset())->toBe('laravel');
});

it('may have fixer options', function () {
$repository = new ConfigurationJsonRepository(dirname(__DIR__, 2).'/Fixtures/fixers/pint.json', null);

expect($repository->fixers())->toBe([
TestCustomFixer::class
]);
});