first commit
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
; top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
; Unix-style newlines
|
||||
[*]
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
@@ -0,0 +1,8 @@
|
||||
.vscode/
|
||||
build/
|
||||
vendor/
|
||||
composer.lock
|
||||
.php-cs-fixer.php
|
||||
*.neon
|
||||
*.cache
|
||||
phpunit.xml
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer;
|
||||
use Nexus\CsConfig\FixerGenerator;
|
||||
use Nexus\CsConfig\Ruleset\Nexus74;
|
||||
use PhpCsFixer\Finder;
|
||||
|
||||
$finder = Finder::create()
|
||||
->files()
|
||||
->in(__DIR__)
|
||||
->exclude(['build'])
|
||||
->append([__FILE__])
|
||||
;
|
||||
|
||||
$overrides = [];
|
||||
$options = [
|
||||
'finder' => $finder,
|
||||
'cacheFile' => 'build/.php-cs-fixer.cache',
|
||||
'customFixers' => FixerGenerator::create('src/Fixer', 'Nexus\\CsConfig\\Fixer'),
|
||||
'customRules' => [
|
||||
NoCodeSeparatorCommentFixer::name() => true,
|
||||
],
|
||||
];
|
||||
|
||||
return Factory::create(new Nexus74(), $overrides, $options)->forLibrary('Nexus CS Config', 'John Paul E. Balandan, CPA', 'paulbalandan@gmail.com', 2020);
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this library will be documented in this file:
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [v3.8.0](https://github.com/NexusPHP/cs-config/compare/v3.7.0...v3.8.0) - 2022-11-01
|
||||
|
||||
- Bump php-cs-fixer to v3.13
|
||||
- Add 'case_sensitive' option to 'general_phpdoc_annotation_remove'
|
||||
- Add 'closure_fn_spacing' option to 'function_declaration'
|
||||
|
||||
## [v3.7.0](https://github.com/NexusPHP/cs-config/compare/v3.6.0...v3.7.0) - 2022-10-15
|
||||
|
||||
- Use dependabot for updates
|
||||
- Bump php-cs-fixer version to v3.12
|
||||
- Use phpstan baseline
|
||||
- Update action workflows
|
||||
|
||||
## [v3.6.0](https://github.com/NexusPHP/cs-config/compare/v3.5.0...v3.6.0) - 2022-09-02
|
||||
|
||||
- Add new option to `phpdoc_separation`
|
||||
- Remove deprecated rules
|
||||
- Configure `no_trailing_comma_in_singleline`
|
||||
- Bump php-cs-fixer to ^3.11
|
||||
- Configure `whitespace_after_comma_in_array`
|
||||
- Use available option of `phpdoc_order`
|
||||
- Configure `no_multiple_statements_per_line` rule
|
||||
- Bump php-cs-fixer to v3.10
|
||||
- Fix PHPStan error
|
||||
|
||||
## [v3.5.0](https://github.com/NexusPHP/cs-config/compare/v3.4.0...v3.5.0) - 2022-07-11
|
||||
|
||||
- Change 'concat_space' to none
|
||||
- Configure new rules in v3.9.1
|
||||
- \[BC BREAK\] Drop Nexus73 ruleset
|
||||
- Suppress missing iterable value type hints
|
||||
- Remove use of deprecated rule
|
||||
- Deprecate `Nexus/space_after_comment_start`
|
||||
- Configure new rules in v3.8
|
||||
|
||||
## [v3.4.0](https://github.com/NexusPHP/cs-config/compare/v3.3.4...v3.4.0) - 2022-02-09
|
||||
|
||||
- Fix code style lint
|
||||
- Add Nexus81 ruleset
|
||||
- Deprecate Nexus73 ruleset
|
||||
- Bump php-cs-fixer version to v3.6
|
||||
- Bump php version to 7.4
|
||||
- Prune build workflow
|
||||
- Revert phpstan level to 8
|
||||
|
||||
## [v3.3.4](https://github.com/NexusPHP/cs-config/compare/v3.3.3...v3.3.4) - 2021-11-02
|
||||
|
||||
- Update to phpstan 1.0
|
||||
- Add ignored tags to `phpdoc_to_comment` rule
|
||||
|
||||
## [v3.3.3](https://github.com/NexusPHP/cs-config/compare/v3.3.2...v3.3.3) - 2021-10-06
|
||||
|
||||
- Enable `no_alternative_syntax` rule
|
||||
- Change class attributes separation to `none` except for methods
|
||||
- Remove operator override for braces in Nexus80
|
||||
- Add support for new fixers added in v3.2.0
|
||||
- Remove deprecated "tokens: use_trait" option
|
||||
- Use own custom fixers
|
||||
- Fix phpstan error on v0.12.99
|
||||
|
||||
## [v3.3.2](https://github.com/NexusPHP/cs-config/compare/v3.3.1...v3.3.2) - 2021-09-08
|
||||
|
||||
- Fix missing string substitution when `FixerGenerator::create()` fails
|
||||
|
||||
## [v3.3.1](https://github.com/NexusPHP/cs-config/compare/v3.3.0...v3.3.1) - 2021-08-31
|
||||
|
||||
- Fix case where comment is exactly `//`
|
||||
|
||||
## [v3.3.0](https://github.com/NexusPHP/cs-config/compare/v3.2.2...v3.3.0) - 2021-08-31
|
||||
|
||||
- Fix grammar usages
|
||||
- Enable all `class_definition` rules
|
||||
- Remove references to `liaison/cs-config`
|
||||
- Add NoCodeSeparatorCommentFixer
|
||||
- Add SpaceAfterCommentStartFixer
|
||||
- Add support for custom fixers
|
||||
- Remove `@internal` annotation from classes in public API
|
||||
- Bump to php-cs-fixer v3.1
|
||||
- Add FixerGenerator
|
||||
- Use phpstan's bleeding edge
|
||||
|
||||
## [v3.2.2](https://github.com/NexusPHP/cs-config/compare/v3.2.1...v3.2.2) - 2021-08-07
|
||||
|
||||
- Add support for `trait_import` in `class_attributes_separation`
|
||||
- Do not test on PHP 8.1 yet
|
||||
|
||||
## [v3.2.1](https://github.com/NexusPHP/cs-config/compare/v3.2.0...v3.2.1) - 2021-07-07
|
||||
|
||||
- Forbid running PHPStan on PHP8.1 (for now)
|
||||
- Standardize `phpunit.xml.dist` structure.
|
||||
- Remove `include/require` from statements requiring blank line before.
|
||||
- Fix for `AbstractRulesetTestCase` when configurable fixer is not yet defined by the ruleset.
|
||||
- \[Nexus80\] Enable `void_return` fixer
|
||||
- Limit excluded annotations to `@final` and `@no-final` only
|
||||
- \[Nexus80\] Enable `final_public_method_for_abstract_class`
|
||||
- \[Nexus80\] Enable `phpdoc_to_param_type` and `phpdoc_to_return_type`
|
||||
- Remove `@test` annotations from tests
|
||||
- Disable `php_unit_test_class_requires_covers`. Let PHPUnit do the job instead.
|
||||
|
||||
## [v3.2.0](https://github.com/NexusPHP/cs-config/compare/v3.1.1...v3.2.0) - 2021-06-19
|
||||
|
||||
- Enable PHP 8.1 build workflow
|
||||
- Forbid importing global functions and constants in addition to global classes
|
||||
- \[Possible BC break\] Refactored stricter `AbstractRulesetTestCase`
|
||||
- Removed superfluous PHPDoc tags if present in method signature
|
||||
- Changed default rule for `binary_operator_spaces` to `single_space` for all rulesets
|
||||
- Changed parent namespace to "Nexus"
|
||||
- Dropped `phpstan/phpstan-strict-rules`
|
||||
|
||||
## [v3.1.1](https://github.com/NexusPHP/cs-config/compare/v3.1.0...v3.1.1) - 2021-06-01
|
||||
|
||||
- Changed `native_constant_invocation` to fix only a subset of built in constants
|
||||
|
||||
## [v3.1.0](https://github.com/NexusPHP/cs-config/compare/v3.0.3...v3.1.0) - 2021-06-01
|
||||
|
||||
- Changed `native_constant_invocation` to fix all built in constants
|
||||
- Completed options for `native_function_invocation`
|
||||
- Changed `phpdoc_line_span` and `phpdoc_tag_type` rules
|
||||
- Allow `@author` tags in `general_phpdoc_annotation_remove` rule
|
||||
- Await `one_if_phpdoc` option for `class_attributes_separation`
|
||||
|
||||
## [v3.0.3](https://github.com/NexusPHP/cs-config/compare/v3.0.2...v3.0.3) - 2021-05-07
|
||||
|
||||
- Add test for checking missing built-in rules in ruleset
|
||||
- Optimize tests' execution times
|
||||
|
||||
## [v3.0.2](https://github.com/NexusPHP/cs-config/compare/v3.0.1...v3.0.2) - 2021-05-07
|
||||
|
||||
- Allow overriding of `AbstractRulesetTestCase::createRuleset()`
|
||||
|
||||
## [v3.0.1](https://github.com/NexusPHP/cs-config/compare/v3.0.0...v3.0.1) - 2021-05-07
|
||||
|
||||
- Update branch alias to `3.x-dev`
|
||||
- Fixed default cache file in `Factory`
|
||||
- Update references of old configuration in README
|
||||
- Fix `Nexus74` ruleset to enable `phpdoc_to_property_type`
|
||||
- Change attribute separation of `const` to `none` in `Nexus80` ruleset
|
||||
- Use descriptive names for rulesets
|
||||
|
||||
## [v3.0.0](https://github.com/NexusPHP/cs-config/compare/v2.2.1...v3.0.0) - 2021-05-06
|
||||
|
||||
- Update `friendsofphp/php-cs-fixer` to v3.0.0 Constitution
|
||||
- New ruleset: `Nexus80`, targeting PHP 8.0+
|
||||
- Add `Tachycardia` for profiling of slow tests
|
||||
- Build action is also run on schedule
|
||||
|
||||
## [v2.2.1](https://github.com/NexusPHP/cs-config/compare/v2.2.0...v2.2.1) - 2021-05-06
|
||||
|
||||
- Fixed faulty build action on running `php-cs-fixer`
|
||||
- Use range diffs in CHANGELOG
|
||||
|
||||
## [v2.2.0](https://github.com/NexusPHP/cs-config/compare/v2.1.5...v2.2.0) - 2021-05-06
|
||||
|
||||
- Update `friendsofphp/php-cs-fixer` to v2.19 Testament
|
||||
- Use `new FixerFactory()` instead of `FixerFactory::create()`
|
||||
- Add `phpdoc_to_property_type` and `trailing_comma_in_multiline` rules
|
||||
- Removed deprecated fixers from the rulesets
|
||||
- Removed deprecated fixer options from the rulesets
|
||||
- Renamed configuration file to `.php-cs-fixer.dist.php`
|
||||
|
||||
## [v2.1.5](https://github.com/NexusPHP/cs-config/compare/v2.1.4...v2.1.5) - 2021-02-20
|
||||
|
||||
### Fixed
|
||||
|
||||
- Removed the faulty `replace` section in composer.json causing halted installations
|
||||
- Fixed errors reported by PHPStan on level 8
|
||||
|
||||
## [v2.1.4](https://github.com/NexusPHP/cs-config/compare/v2.1.3...v2.1.4) - 2021-01-18
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for PHP 8
|
||||
- Bump `friendsofphp/php-cs-fixer` to v2.18.0 Remote Void
|
||||
|
||||
## [v2.1.3](https://github.com/NexusPHP/cs-config/compare/v2.1.2...v2.1.3) - 2021-01-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed a PHPStan error on the incorrect covariant return type of `Factory::invoke`.
|
||||
|
||||
## [v2.1.2](https://github.com/NexusPHP/cs-config/compare/v2.1.1...v2.1.2) - 2021-01-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed name of `Nexus74` ruleset which was erroneously set as `Nexus73`.
|
||||
- Fixed license format in `README`.
|
||||
|
||||
## [v2.1.1](https://github.com/NexusPHP/cs-config/compare/v2.1.0...v2.1.1) - 2020-12-12
|
||||
|
||||
### Changed
|
||||
|
||||
- `increment_style` fixer now uses the `['style' => 'pre']`. Previously, this was `post`.
|
||||
|
||||
## [v2.1.0](https://github.com/NexusPHP/cs-config/compare/v2.0.2...v2.0.2) - 2020-12-08
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for new fixers in [v2.17.0 Desert Beast](https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/tag/v2.17.0).
|
||||
- Added `Nexus74` ruleset for support on `use_arrow_functions` fixer.
|
||||
- Added testing for deprecated fixers.
|
||||
|
||||
### Changed
|
||||
|
||||
- `phpdoc_line_span` has been set to single for all classy elements.
|
||||
- `binary_operator_spaces` has been set to its default `single_space` for use in this library.
|
||||
|
||||
## [v2.0.2](https://github.com/NexusPHP/cs-config/compare/v2.0.1...v2.0.2) - 2020-12-01
|
||||
|
||||
### Fixed
|
||||
|
||||
- Re-release of previous release due to inconsistency in tagging process.
|
||||
|
||||
## [v2.0.1](https://github.com/NexusPHP/cs-config/compare/v2.0.0...v2.0.1) - 2020-12-01
|
||||
|
||||
### Changed
|
||||
|
||||
- `global_namespace_import` has its option `import_classes` set to `false`.
|
||||
- Renamed `phpunit.xml.dist`'s `cacheResultFile` attribute
|
||||
|
||||
## [v2.0.0](https://github.com/NexusPHP/cs-config/releases/tag/v2.0.0) - 2020-11-28
|
||||
|
||||
### Changed
|
||||
|
||||
- Initial release in this repository. See [MIGRATION](MIGRATION.md) for the detailed changes
|
||||
from its predecessor library.
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 John Paul E. Balandan, CPA
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+222
@@ -0,0 +1,222 @@
|
||||
# Nexus CS Config
|
||||
|
||||
[](https://php.net)
|
||||

|
||||
[](https://coveralls.io/github/NexusPHP/cs-config?branch=develop)
|
||||
[](//packagist.org/packages/nexusphp/cs-config)
|
||||
[](LICENSE)
|
||||
[](//packagist.org/packages/nexusphp/cs-config)
|
||||
|
||||
This library provides a factory for custom rulesets for [`friendsofphp/php-cs-fixer`][1].
|
||||
|
||||
[1]: https://github.com/FriendsOfPHP/PHP-CS-Fixer
|
||||
|
||||
## Installation
|
||||
|
||||
You can add this library as a local, per-project dependency to your project
|
||||
using [Composer](https://getcomposer.org/):
|
||||
|
||||
composer require nexusphp/cs-config
|
||||
|
||||
If you only need this library during development, for instance to run your project's test suite,
|
||||
then you should add it as a development-time dependency:
|
||||
|
||||
composer require --dev nexusphp/cs-config
|
||||
|
||||
## Configuration
|
||||
|
||||
* Create a `.php-cs-fixer.dist.php` at the root of your project:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Ruleset\Nexus73;
|
||||
|
||||
return Factory::create(new Nexus73())->forProjects();
|
||||
|
||||
```
|
||||
|
||||
* Include the cache file in your `.gitignore`. By
|
||||
default, the cache file will be saved in the project root.
|
||||
|
||||
```diff
|
||||
vendor/
|
||||
|
||||
+# php-cs-fixer
|
||||
+.php-cs-fixer.php
|
||||
+.php-cs-fixer.cache
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Adding Preformatted License Header
|
||||
|
||||
You can create a preformatted license header to all PHP files by using the public `forLibrary()` method
|
||||
instead of `forProjects()`. This method accepts two required arguments (the library name and author) and
|
||||
two optional arguments (the email address and starting year of license).
|
||||
|
||||
* Scenario 1: Providing all arguments
|
||||
```diff
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Ruleset\Nexus73;
|
||||
|
||||
-return Factory::create(new Nexus73())->forProjects();
|
||||
+return Factory::create(new Nexus73())->forLibrary('My Library', 'John Doe', 'john@doe.com', 2020);
|
||||
```
|
||||
|
||||
This setting will configure a license header similar to below:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of My Library.
|
||||
*
|
||||
* (c) 2020 John Doe <john@doe.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig;
|
||||
```
|
||||
|
||||
* Scenario 2: Providing only the required arguments
|
||||
|
||||
If you opted not to provide any of the optional arguments (i.e., email address, starting license year),
|
||||
these will not be shown on the license header allowing flexibility on the copyright portion.
|
||||
|
||||
```diff
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Ruleset\Nexus73;
|
||||
|
||||
-return Factory::create(new Nexus73())->forProjects();
|
||||
+return Factory::create(new Nexus73())->forLibrary('My Library', 'John Doe');
|
||||
```
|
||||
|
||||
This will give the following license header:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of My Library.
|
||||
*
|
||||
* (c) John Doe
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig;
|
||||
```
|
||||
|
||||
### Overriding Rules in a Ruleset
|
||||
|
||||
If you feel that a specific rule in the ruleset is not appropriate for you, you can override it instead of creating a new ruleset:
|
||||
|
||||
```diff
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Ruleset\Nexus73;
|
||||
|
||||
-return Factory::create(new Nexus73())->forProjects();
|
||||
+return Factory::create(new Nexus73(), [
|
||||
+ 'binary_operator_spaces' => false,
|
||||
+])->forProjects();
|
||||
|
||||
```
|
||||
|
||||
### Specifying Options to `PhpCsFixer\Config`
|
||||
|
||||
The `Factory` class returns an instance of `PhpCsFixer\Config` and fully supports all of
|
||||
its properties setup. You can pass an array to the third parameter of `Factory::create()`
|
||||
containing your desired options.
|
||||
|
||||
**Options**
|
||||
|
||||
| Key | Allowed Types | Default |
|
||||
| -------------- | :--------------------------------------: | :----------------------------------: |
|
||||
| cacheFile | `string` | `.php-cs-fixer.cache` |
|
||||
| customFixers | `FixerInterface[], iterable, \Traversable` | `[]` |
|
||||
| finder | `iterable, string[], \Traversable` | default `PhpCsFixer\Finder` instance |
|
||||
| format | `string` | `txt` |
|
||||
| hideProgress | `bool` | `false` |
|
||||
| indent | `string` | `' '` // 4 spaces |
|
||||
| lineEnding | `string` | `"\n"` |
|
||||
| phpExecutable | `null, string` | `null` |
|
||||
| isRiskyAllowed | `bool` | `false` |
|
||||
| usingCache | `bool` | `true` |
|
||||
| customRules | `array` | `[]` |
|
||||
|
||||
```diff
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use Nexus\CsConfig\Ruleset\Nexus73;
|
||||
|
||||
-return Factory::create(new Nexus73())->forProjects();
|
||||
+return Factory::create(new Nexus73(), [], [
|
||||
+ 'usingCache' => false,
|
||||
+ 'hideProgress => true,
|
||||
+])->forProjects();
|
||||
```
|
||||
|
||||
## Customization of Ruleset
|
||||
|
||||
What is the purpose of a configuration factory if not able to create a custom ruleset for
|
||||
an organization-wide usage, right? Well, you are not constrained to use the default rulesets
|
||||
and putting a long array of overrides. That's pretty nasty.
|
||||
|
||||
The way to achieve this is dependent on you but the main idea is creating a new ruleset that
|
||||
extends `Nexus\CsConfig\Ruleset\AbstractRuleset`. Yup, it's that easy. Then you just need to
|
||||
provide details for its required four (4) protected properties.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace MyCompany\CodingStandards\Ruleset;
|
||||
|
||||
use Nexus\CsConfig\Ruleset\AbstractRuleset;
|
||||
|
||||
final class MyCompany extends AbstractRuleset
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'My Company';
|
||||
$this->rules = [
|
||||
'@PSR2' => true,
|
||||
...
|
||||
];
|
||||
$this->requiredPHPVersion = 70400;
|
||||
$this->autoActivateIsRiskyAllowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then, in creating your `.php-cs-fixer.dist.php`, use your own ruleset.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Nexus\CsConfig\Factory;
|
||||
use MyCompany\CodingStandards\Ruleset\MyCompany;
|
||||
|
||||
return Factory::create(new MyCompany())->forProjects();
|
||||
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
This project is inspired by and an enhancement of [`ergebnis/php-cs-fixer-config`](https://github.com/ergebnis/php-cs-fixer-config).
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are very much welcome. If you see an improvement or bugfix, open a [PR](https://github.com/NexusPHP/cs-config/pulls) now!
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "nexusphp/cs-config",
|
||||
"type": "library",
|
||||
"description": "A factory for custom rulesets for PHP CS Fixer.",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Paul E. Balandan, CPA",
|
||||
"email": "paulbalandan@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"ext-tokenizer": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.13"
|
||||
},
|
||||
"conflict": {
|
||||
"liaison/cs-config": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"nexusphp/tachycardia": "^1.3",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nexus\\CsConfig\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Nexus\\CsConfig\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"support": {
|
||||
"issues": "https://github.com/NexusPHP/cs-config/issues",
|
||||
"source": "https://github.com/NexusPHP/cs-config.git",
|
||||
"slack": "https://nexusphp.slack.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Cannot access offset 'header' on array\\<string, mixed\\>\\|bool\\.$#"
|
||||
count: 1
|
||||
path: tests/FactoryTest.php
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
includes:
|
||||
- phpstan-baseline.neon.dist
|
||||
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
|
||||
|
||||
parameters:
|
||||
tmpDir: build/phpstan
|
||||
level: 8
|
||||
paths:
|
||||
- src
|
||||
- tests
|
||||
bootstrapFiles:
|
||||
- vendor/autoload.php
|
||||
parallel:
|
||||
processTimeout: 300.0
|
||||
polluteScopeWithLoopInitialAssignments: false
|
||||
polluteScopeWithAlwaysIterableForeach: false
|
||||
checkAlwaysTrueCheckTypeFunctionCall: true
|
||||
checkAlwaysTrueInstanceof: true
|
||||
checkAlwaysTrueStrictComparison: true
|
||||
checkExplicitMixedMissingReturn: true
|
||||
checkFunctionNameCase: true
|
||||
checkInternalClassCaseSensitivity: true
|
||||
checkMissingIterableValueType: false
|
||||
reportMaybesInMethodSignatures: true
|
||||
reportStaticMethodSignatures: true
|
||||
checkTooWideReturnTypesInProtectedAndPublicMethods: true
|
||||
featureToggles:
|
||||
disableCheckMissingIterableValueType: false
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?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"
|
||||
cacheResultFile="build/phpunit/test-results"
|
||||
colors="true"
|
||||
columns="max"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
forceCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
verbose="true"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="NexusPHP CS Config Test Suite">
|
||||
<directory suffix="Test.php">tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage cacheDirectory="build/phpunit/code-coverage"
|
||||
ignoreDeprecatedCodeUnits="true"
|
||||
processUncoveredFiles="true"
|
||||
>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
|
||||
<report>
|
||||
<clover outputFile="build/phpunit/logs/clover.xml"/>
|
||||
<html outputDirectory="build/phpunit/logs/html"/>
|
||||
</report>
|
||||
</coverage>
|
||||
|
||||
<extensions>
|
||||
<extension class="Nexus\PHPUnit\Extension\Tachycardia" />
|
||||
</extensions>
|
||||
</phpunit>
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig;
|
||||
|
||||
use Nexus\CsConfig\Ruleset\RulesetInterface;
|
||||
use PhpCsFixer\Config;
|
||||
use PhpCsFixer\ConfigInterface;
|
||||
use PhpCsFixer\Finder;
|
||||
|
||||
/**
|
||||
* The Factory class is invoked on each project's `.php-cs-fixer.dist.php` to create
|
||||
* the specific ruleset for the project.
|
||||
*/
|
||||
final class Factory
|
||||
{
|
||||
/**
|
||||
* Current RulesetInterface instance.
|
||||
*/
|
||||
private RulesetInterface $ruleset;
|
||||
|
||||
/**
|
||||
* Array of resolved options.
|
||||
*
|
||||
* @phpstan-var array{
|
||||
* cacheFile: string,
|
||||
* customFixers: iterable<\PhpCsFixer\Fixer\FixerInterface>,
|
||||
* finder: \PhpCsFixer\Finder|iterable<\SplFileInfo>,
|
||||
* format: string,
|
||||
* hideProgress: bool,
|
||||
* indent: string,
|
||||
* lineEnding: string,
|
||||
* phpExecutable: null|string,
|
||||
* isRiskyAllowed: bool,
|
||||
* usingCache: bool,
|
||||
* rules: array<string, mixed>
|
||||
* }
|
||||
*/
|
||||
private array $options;
|
||||
|
||||
/**
|
||||
* @param array{
|
||||
* cacheFile: string,
|
||||
* customFixers: iterable<\PhpCsFixer\Fixer\FixerInterface>,
|
||||
* finder: \PhpCsFixer\Finder|iterable<\SplFileInfo>,
|
||||
* format: string,
|
||||
* hideProgress: bool,
|
||||
* indent: string,
|
||||
* lineEnding: string,
|
||||
* phpExecutable: null|string,
|
||||
* isRiskyAllowed: bool,
|
||||
* usingCache: bool,
|
||||
* rules: array<string, mixed>
|
||||
* } $options
|
||||
*/
|
||||
private function __construct(RulesetInterface $ruleset, array $options)
|
||||
{
|
||||
$this->ruleset = $ruleset;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the ruleset and options before the `PhpCsFixer\Config` object
|
||||
* is created.
|
||||
*
|
||||
* @param array<string, mixed> $overrides
|
||||
* @param array{
|
||||
* cacheFile?: string,
|
||||
* customFixers?: iterable<\PhpCsFixer\Fixer\FixerInterface>,
|
||||
* finder?: \PhpCsFixer\Finder|iterable<\SplFileInfo>,
|
||||
* format?: string,
|
||||
* hideProgress?: bool,
|
||||
* indent?: string,
|
||||
* lineEnding?: string,
|
||||
* phpExecutable?: null|string,
|
||||
* isRiskyAllowed?: bool,
|
||||
* usingCache?: bool,
|
||||
* customRules?: array<string, mixed>
|
||||
* } $options
|
||||
*/
|
||||
public static function create(RulesetInterface $ruleset, array $overrides = [], array $options = []): self
|
||||
{
|
||||
if (\PHP_VERSION_ID < $ruleset->getRequiredPHPVersion()) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'The "%s" ruleset requires a minimum PHP_VERSION_ID of "%d" but current PHP_VERSION_ID is "%d".',
|
||||
$ruleset->getName(),
|
||||
$ruleset->getRequiredPHPVersion(),
|
||||
\PHP_VERSION_ID,
|
||||
));
|
||||
}
|
||||
|
||||
// Meant to be used in vendor/ to get to the root directory
|
||||
$dir = \dirname(__DIR__, 4);
|
||||
$dir = realpath($dir) ?: $dir;
|
||||
|
||||
$defaultFinder = Finder::create()
|
||||
->files()
|
||||
->in([$dir])
|
||||
->exclude(['build'])
|
||||
;
|
||||
|
||||
// Resolve Config options
|
||||
$options['cacheFile'] ??= '.php-cs-fixer.cache';
|
||||
$options['customFixers'] ??= [];
|
||||
$options['finder'] ??= $defaultFinder;
|
||||
$options['format'] ??= 'txt';
|
||||
$options['hideProgress'] ??= false;
|
||||
$options['indent'] ??= ' ';
|
||||
$options['lineEnding'] ??= "\n";
|
||||
$options['phpExecutable'] ??= null;
|
||||
$options['isRiskyAllowed'] = $options['isRiskyAllowed'] ?? ($ruleset->willAutoActivateIsRiskyAllowed() ?: false);
|
||||
$options['usingCache'] ??= true;
|
||||
$options['rules'] = array_merge($ruleset->getRules(), $overrides, $options['customRules'] ?? []);
|
||||
|
||||
return new self($ruleset, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `PhpCsFixer\Config` object that is applicable for libraries,
|
||||
* i.e., has their own header docblock in place.
|
||||
*/
|
||||
public function forLibrary(string $library, string $author, string $email = '', ?int $startingYear = null): ConfigInterface
|
||||
{
|
||||
$year = (string) $startingYear;
|
||||
|
||||
if ('' !== $year) {
|
||||
$year .= ' ';
|
||||
}
|
||||
|
||||
if ('' !== $email) {
|
||||
$email = trim($email, '<>');
|
||||
$email = ' <'.$email.'>';
|
||||
}
|
||||
|
||||
$header = sprintf(
|
||||
<<<'HEADER'
|
||||
This file is part of %s.
|
||||
|
||||
(c) %s%s%s
|
||||
|
||||
For the full copyright and license information, please view
|
||||
the LICENSE file that was distributed with this source code.
|
||||
HEADER,
|
||||
$library,
|
||||
$year,
|
||||
$author,
|
||||
$email,
|
||||
);
|
||||
|
||||
return $this->invoke([
|
||||
'header_comment' => [
|
||||
'header' => trim($header),
|
||||
'comment_type' => 'PHPDoc',
|
||||
'location' => 'after_declare_strict',
|
||||
'separate' => 'both',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain invocation of `Config` with no additional arguments.
|
||||
*/
|
||||
public function forProjects(): ConfigInterface
|
||||
{
|
||||
return $this->invoke();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method of creating the Config instance.
|
||||
*
|
||||
* @param array<string, array<string>|bool> $overrides
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private function invoke(array $overrides = []): ConfigInterface
|
||||
{
|
||||
$rules = array_merge($this->options['rules'], $overrides);
|
||||
|
||||
return (new Config($this->ruleset->getName()))
|
||||
->registerCustomFixers($this->options['customFixers'])
|
||||
->setCacheFile($this->options['cacheFile'])
|
||||
->setFinder($this->options['finder'])
|
||||
->setFormat($this->options['format'])
|
||||
->setHideProgress($this->options['hideProgress'])
|
||||
->setIndent($this->options['indent'])
|
||||
->setLineEnding($this->options['lineEnding'])
|
||||
->setPhpExecutable($this->options['phpExecutable'])
|
||||
->setRiskyAllowed($this->options['isRiskyAllowed'])
|
||||
->setUsingCache($this->options['usingCache'])
|
||||
->setRules($rules)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Fixer;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\Utils;
|
||||
|
||||
abstract class AbstractCustomFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* Vendor namespace in fixer's name.
|
||||
*/
|
||||
protected static ?string $namespace;
|
||||
|
||||
/**
|
||||
* Returns the fixer name for easy use in fixer registration and usage.
|
||||
*/
|
||||
public static function name(): string
|
||||
{
|
||||
$nameParts = explode('\\', static::class);
|
||||
$namespace = static::$namespace ?? $nameParts[0];
|
||||
$name = substr(end($nameParts), 0, -\strlen('Fixer'));
|
||||
|
||||
return $namespace.'/'.Utils::camelCaseToUnderscore($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return self::name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Fixer\Comment;
|
||||
|
||||
use Nexus\CsConfig\Fixer\AbstractCustomFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* Removes code separator comments except when used as section boundary.
|
||||
*/
|
||||
final class NoCodeSeparatorCommentFixer extends AbstractCustomFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'There should not be any code separator comments.',
|
||||
[new CodeSample(
|
||||
<<<'EOF'
|
||||
<?php
|
||||
|
||||
$code = 'a';
|
||||
|
||||
//------------------------
|
||||
|
||||
$arr = [];
|
||||
|
||||
EOF,
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_COMMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Must run before NoEmptyCommentFixer, SpaceAfterCommentStartFixer
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
for ($index = 1, $count = $tokens->count(); $index < $count; ++$index) {
|
||||
/** @var Token $token */
|
||||
$token = $tokens[$index];
|
||||
|
||||
if (! $token->isGivenKind(T_COMMENT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->isCodeSeparatorComment($token->getContent())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isCommentBlockBoundary($tokens, $index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens->removeLeadingWhitespace($index);
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the recurring code separator comment is part of a comment
|
||||
* boundary that serves as a logical division between sections of code.
|
||||
*
|
||||
* ```
|
||||
* //================================== <-- this is used as a boundary
|
||||
* // SECTION
|
||||
* //================================== <-- this is used as a boundary
|
||||
*
|
||||
* //================================== <-- this is NOT a boundary
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
private function isCommentBlockBoundary(Tokens $tokens, int $index): bool
|
||||
{
|
||||
$prevIndex = $tokens->getPrevNonWhitespace($index);
|
||||
$nextIndex = $tokens->getNextNonWhitespace($index);
|
||||
|
||||
/** @var Token $prevToken */
|
||||
$prevToken = $tokens[$prevIndex];
|
||||
$prevTokenIsRegularComment = $prevToken->isGivenKind(T_COMMENT)
|
||||
&& ! $this->isCodeSeparatorComment($prevToken->getContent());
|
||||
|
||||
/** @var Token $nextToken */
|
||||
$nextToken = $tokens[$nextIndex];
|
||||
$nextTokenIsRegularComment = $nextToken->isGivenKind(T_COMMENT)
|
||||
&& ! $this->isCodeSeparatorComment($nextToken->getContent());
|
||||
|
||||
return $prevTokenIsRegularComment || $nextTokenIsRegularComment;
|
||||
}
|
||||
|
||||
private function isCodeSeparatorComment(string $comment): bool
|
||||
{
|
||||
return Preg::match('/^\/\/\s*[-|=]+$/', $comment) === 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Fixer\Comment;
|
||||
|
||||
use Nexus\CsConfig\Fixer\AbstractCustomFixer;
|
||||
use PhpCsFixer\Fixer\DeprecatedFixerInterface;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* Simple comments should have one space after the `//`.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
final class SpaceAfterCommentStartFixer extends AbstractCustomFixer implements DeprecatedFixerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'There should be a single whitespace after the start of a simple comment.',
|
||||
[
|
||||
new CodeSample("<?php\n //this is a comment\n"),
|
||||
new CodeSample("<?php\n // this is another comment\n"),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getSuccessorsNames(): array
|
||||
{
|
||||
return ['single_line_comment_spacing'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_COMMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Must run after NoEmptyCommentFixer
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
for ($index = 1, $count = $tokens->count(); $index < $count; ++$index) {
|
||||
/** @var Token $token */
|
||||
$token = $tokens[$index];
|
||||
|
||||
if (! $token->isGivenKind(T_COMMENT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$comment = $token->getContent();
|
||||
|
||||
if (substr($comment, 0, 2) !== '//') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('//' === $comment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Preg::match('/^\/\/(\s*)(.+)/', $comment, $matches);
|
||||
|
||||
if (' ' === $matches[1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Preg::match('/\-+/', $matches[2]) === 1 || Preg::match('/\=+/', $matches[2]) === 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([T_COMMENT, '// '.$matches[2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig;
|
||||
|
||||
use PhpCsFixer\Finder;
|
||||
use PhpCsFixer\Fixer\FixerInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
/**
|
||||
* Provides a generator of custom fixers for registration in `PhpCsFixer\Config`.
|
||||
*
|
||||
* @implements \IteratorAggregate<FixerInterface>
|
||||
*/
|
||||
final class FixerGenerator implements \IteratorAggregate
|
||||
{
|
||||
private string $path;
|
||||
private string $vendor;
|
||||
|
||||
private function __construct(string $path, string $vendor)
|
||||
{
|
||||
$this->path = $path;
|
||||
$this->vendor = $vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function create(string $path, string $vendor): self
|
||||
{
|
||||
if ('' === $path) {
|
||||
throw new \RuntimeException('Path to custom fixers cannot be empty.');
|
||||
}
|
||||
|
||||
if (! is_dir($path)) {
|
||||
throw new \RuntimeException(sprintf('Path "%s" is not a valid directory.', $path));
|
||||
}
|
||||
|
||||
if ('' === $vendor) {
|
||||
throw new \RuntimeException('Vendor namespace cannot be empty.');
|
||||
}
|
||||
|
||||
if (Preg::match('/^[A-Z][a-zA-Z0-9\\\\]+$/', $vendor) !== 1) {
|
||||
throw new \RuntimeException(sprintf('Vendor namespace "%s" is not valid.', $vendor));
|
||||
}
|
||||
|
||||
return new self($path, $vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable<FixerInterface>
|
||||
*/
|
||||
public function getIterator(): \Traversable
|
||||
{
|
||||
$finder = Finder::create()
|
||||
->files()
|
||||
->in($this->path)
|
||||
->notName('/Abstract(\S+)\.php$/')
|
||||
->notName('/(\S+)(?<!Fixer)\.php$/')
|
||||
->sortByName()
|
||||
;
|
||||
|
||||
$fixers = array_filter(array_map(
|
||||
function (SplFileInfo $file): object {
|
||||
$fixer = sprintf(
|
||||
'%s\\%s%s%s',
|
||||
trim($this->vendor, '\\'),
|
||||
strtr($file->getRelativePath(), \DIRECTORY_SEPARATOR, '\\'),
|
||||
$file->getRelativePath() !== '' ? '\\' : '',
|
||||
$file->getBasename('.'.$file->getExtension()),
|
||||
);
|
||||
|
||||
return new $fixer();
|
||||
},
|
||||
iterator_to_array($finder, false),
|
||||
), static fn (object $fixer): bool => $fixer instanceof FixerInterface);
|
||||
|
||||
yield from $fixers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Ruleset;
|
||||
|
||||
abstract class AbstractRuleset implements RulesetInterface
|
||||
{
|
||||
/**
|
||||
* Name of the ruleset.
|
||||
*/
|
||||
protected string $name;
|
||||
|
||||
/**
|
||||
* Rules for the ruleset.
|
||||
*/
|
||||
protected array $rules = [];
|
||||
|
||||
/**
|
||||
* Minimum PHP version.
|
||||
*/
|
||||
protected int $requiredPHPVersion = 0;
|
||||
|
||||
/**
|
||||
* Have this ruleset turn on `$isRiskyAllowed` flag?
|
||||
*/
|
||||
protected bool $autoActivateIsRiskyAllowed = false;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
final public function getName(): string
|
||||
{
|
||||
return $this->name ?: trim(strrchr(static::class, '\\') ?: static::class, '\\');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
final public function getRules(): array
|
||||
{
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
final public function getRequiredPHPVersion(): int
|
||||
{
|
||||
return $this->requiredPHPVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
final public function willAutoActivateIsRiskyAllowed(): bool
|
||||
{
|
||||
return $this->autoActivateIsRiskyAllowed;
|
||||
}
|
||||
}
|
||||
+637
@@ -0,0 +1,637 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Ruleset;
|
||||
|
||||
/**
|
||||
* Ruleset for `Nexus` group.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Nexus74 extends AbstractRuleset
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'Nexus for PHP 7.4';
|
||||
$this->rules = [
|
||||
'align_multiline_comment' => ['comment_type' => 'all_multiline'],
|
||||
'array_indentation' => true,
|
||||
'array_push' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'assign_null_coalescing_to_coalesce_equal' => true,
|
||||
'backtick_to_shell_exec' => true,
|
||||
'binary_operator_spaces' => [
|
||||
'default' => 'single_space',
|
||||
'operators' => [],
|
||||
],
|
||||
'blank_line_after_namespace' => true,
|
||||
'blank_line_after_opening_tag' => true,
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'case',
|
||||
'continue',
|
||||
'declare',
|
||||
'default',
|
||||
'do',
|
||||
'exit',
|
||||
'for',
|
||||
'foreach',
|
||||
'goto',
|
||||
'if',
|
||||
'return',
|
||||
'switch',
|
||||
'throw',
|
||||
'try',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'blank_line_between_import_groups' => true,
|
||||
'braces' => [
|
||||
'allow_single_line_anonymous_class_with_empty_body' => true,
|
||||
'allow_single_line_closure' => true,
|
||||
'position_after_anonymous_constructs' => 'same',
|
||||
'position_after_control_structures' => 'same',
|
||||
'position_after_functions_and_oop_constructs' => 'next',
|
||||
],
|
||||
'cast_spaces' => ['space' => 'single'],
|
||||
'class_attributes_separation' => [
|
||||
'elements' => [
|
||||
'const' => 'none',
|
||||
'property' => 'none',
|
||||
'method' => 'one',
|
||||
'trait_import' => 'none',
|
||||
],
|
||||
],
|
||||
'class_definition' => [
|
||||
'multi_line_extends_each_single_line' => true,
|
||||
'single_item_single_line' => true,
|
||||
'single_line' => true,
|
||||
'space_before_parenthesis' => true,
|
||||
'inline_constructor_arguments' => true,
|
||||
],
|
||||
'class_reference_name_casing' => true,
|
||||
'clean_namespace' => true,
|
||||
'combine_consecutive_issets' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'combine_nested_dirname' => true,
|
||||
'comment_to_phpdoc' => [
|
||||
'ignored_tags' => [
|
||||
'todo',
|
||||
'codeCoverageIgnore',
|
||||
'codeCoverageIgnoreStart',
|
||||
'codeCoverageIgnoreEnd',
|
||||
'phpstan-ignore-line',
|
||||
'phpstan-ignore-next-line',
|
||||
],
|
||||
],
|
||||
'compact_nullable_typehint' => true,
|
||||
'concat_space' => ['spacing' => 'none'],
|
||||
'constant_case' => ['case' => 'lower'],
|
||||
'control_structure_braces' => true,
|
||||
'control_structure_continuation_position' => ['position' => 'same_line'],
|
||||
'curly_braces_position' => [
|
||||
'control_structures_opening_brace' => 'same_line',
|
||||
'functions_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_functions_opening_brace' => 'same_line',
|
||||
'classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_classes_opening_brace' => 'same_line',
|
||||
'allow_single_line_empty_anonymous_classes' => true,
|
||||
'allow_single_line_anonymous_functions' => true,
|
||||
],
|
||||
'date_time_create_from_format_call' => true,
|
||||
'date_time_immutable' => true,
|
||||
'declare_equal_normalize' => ['space' => 'none'],
|
||||
'declare_parentheses' => true,
|
||||
'declare_strict_types' => true,
|
||||
'dir_constant' => true,
|
||||
'doctrine_annotation_array_assignment' => false,
|
||||
'doctrine_annotation_braces' => false,
|
||||
'doctrine_annotation_indentation' => false,
|
||||
'doctrine_annotation_spaces' => false,
|
||||
'echo_tag_syntax' => [
|
||||
'format' => 'short',
|
||||
'long_function' => 'echo',
|
||||
'shorten_simple_statements_only' => true,
|
||||
],
|
||||
'elseif' => true,
|
||||
'empty_loop_body' => ['style' => 'braces'],
|
||||
'empty_loop_condition' => ['style' => 'while'],
|
||||
'encoding' => true,
|
||||
'ereg_to_preg' => true,
|
||||
'error_suppression' => [
|
||||
'mute_deprecation_error' => true,
|
||||
'noise_remaining_usages' => false,
|
||||
'noise_remaining_usages_exclude' => [],
|
||||
],
|
||||
'escape_implicit_backslashes' => [
|
||||
'double_quoted' => true,
|
||||
'heredoc_syntax' => true,
|
||||
'single_quoted' => false,
|
||||
],
|
||||
'explicit_indirect_variable' => true,
|
||||
'explicit_string_variable' => true,
|
||||
'final_class' => false,
|
||||
'final_internal_class' => [
|
||||
'annotation_exclude' => ['@final', '@no-final'],
|
||||
'annotation_include' => ['@internal'],
|
||||
'consider_absent_docblock_as_internal_class' => false,
|
||||
],
|
||||
'final_public_method_for_abstract_class' => false,
|
||||
'fopen_flag_order' => true,
|
||||
'fopen_flags' => ['b_mode' => true],
|
||||
'full_opening_tag' => true,
|
||||
'fully_qualified_strict_types' => true,
|
||||
'function_declaration' => [
|
||||
'closure_function_spacing' => 'one',
|
||||
'closure_fn_spacing' => 'one',
|
||||
'trailing_comma_single_line' => false,
|
||||
],
|
||||
'function_to_constant' => [
|
||||
'functions' => [
|
||||
'get_called_class',
|
||||
'get_class',
|
||||
'get_class_this',
|
||||
'php_sapi_name',
|
||||
'phpversion',
|
||||
'pi',
|
||||
],
|
||||
],
|
||||
'function_typehint_space' => true,
|
||||
'general_phpdoc_annotation_remove' => [
|
||||
'annotations' => [
|
||||
'package',
|
||||
'subpackage',
|
||||
],
|
||||
'case_sensitive' => false,
|
||||
],
|
||||
'general_phpdoc_tag_rename' => [
|
||||
'case_sensitive' => false,
|
||||
'fix_annotation' => true,
|
||||
'fix_inline' => true,
|
||||
'replacements' => ['inheritDocs' => 'inheritDoc'],
|
||||
],
|
||||
'get_class_to_class_keyword' => false,
|
||||
'global_namespace_import' => [
|
||||
'import_classes' => false,
|
||||
'import_constants' => false,
|
||||
'import_functions' => false,
|
||||
],
|
||||
'group_import' => false,
|
||||
'header_comment' => false,
|
||||
'heredoc_indentation' => ['indentation' => 'start_plus_one'],
|
||||
'heredoc_to_nowdoc' => true,
|
||||
'implode_call' => true,
|
||||
'include' => true,
|
||||
'increment_style' => ['style' => 'pre'],
|
||||
'indentation_type' => true,
|
||||
'integer_literal_case' => true,
|
||||
'is_null' => true,
|
||||
'lambda_not_used_import' => true,
|
||||
'line_ending' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'list_syntax' => ['syntax' => 'short'],
|
||||
'logical_operators' => true,
|
||||
'lowercase_cast' => true,
|
||||
'lowercase_keywords' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'magic_constant_casing' => true,
|
||||
'magic_method_casing' => true,
|
||||
'mb_str_functions' => false,
|
||||
'method_argument_space' => [
|
||||
'after_heredoc' => true,
|
||||
'keep_multiple_spaces_after_comma' => false,
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
],
|
||||
'method_chaining_indentation' => true,
|
||||
'modernize_strpos' => false,
|
||||
'modernize_types_casting' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
|
||||
'native_constant_invocation' => [
|
||||
'fix_built_in' => false,
|
||||
'include' => [
|
||||
'DIRECTORY_SEPARATOR',
|
||||
'PHP_INT_SIZE',
|
||||
'PHP_SAPI',
|
||||
'PHP_VERSION_ID',
|
||||
],
|
||||
'exclude' => [],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_casing' => true,
|
||||
'native_function_invocation' => [
|
||||
'exclude' => [],
|
||||
'include' => ['@compiler_optimized'],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_type_declaration_casing' => true,
|
||||
'new_with_braces' => [
|
||||
'named_class' => true,
|
||||
'anonymous_class' => true,
|
||||
],
|
||||
'no_alias_functions' => ['sets' => ['@all']],
|
||||
'no_alias_language_construct_call' => true,
|
||||
'no_alternative_syntax' => ['fix_non_monolithic_code' => false],
|
||||
'no_binary_string' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_blank_lines_after_phpdoc' => true,
|
||||
'no_blank_lines_before_namespace' => false,
|
||||
'no_break_comment' => ['comment_text' => 'no break'],
|
||||
'no_closing_tag' => true,
|
||||
'no_empty_comment' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_empty_statement' => true,
|
||||
'no_extra_blank_lines' => [
|
||||
'tokens' => [
|
||||
'extra',
|
||||
'break',
|
||||
'continue',
|
||||
'curly_brace_block',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'return',
|
||||
'throw',
|
||||
'use',
|
||||
'switch',
|
||||
'case',
|
||||
'default',
|
||||
],
|
||||
],
|
||||
'no_homoglyph_names' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'no_mixed_echo_print' => ['use' => 'echo'],
|
||||
'no_multiline_whitespace_around_double_arrow' => true,
|
||||
'no_multiple_statements_per_line' => true,
|
||||
'no_null_property_initialization' => true,
|
||||
'no_php4_constructor' => true,
|
||||
'no_short_bool_cast' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_space_around_double_colon' => true,
|
||||
'no_spaces_after_function_name' => true,
|
||||
'no_spaces_around_offset' => ['positions' => ['inside', 'outside']],
|
||||
'no_spaces_inside_parenthesis' => true,
|
||||
'no_superfluous_elseif' => true,
|
||||
'no_superfluous_phpdoc_tags' => [
|
||||
'allow_mixed' => true,
|
||||
'allow_unused_params' => true,
|
||||
'remove_inheritdoc' => false,
|
||||
],
|
||||
'no_trailing_comma_in_singleline' => [
|
||||
'elements' => ['arguments', 'array', 'array_destructuring', 'group_import'],
|
||||
],
|
||||
'no_trailing_whitespace' => true,
|
||||
'no_trailing_whitespace_in_comment' => true,
|
||||
'no_trailing_whitespace_in_string' => true,
|
||||
'no_unneeded_control_parentheses' => [
|
||||
'statements' => [
|
||||
'break',
|
||||
'clone',
|
||||
'continue',
|
||||
'echo_print',
|
||||
'return',
|
||||
'switch_case',
|
||||
'yield',
|
||||
],
|
||||
],
|
||||
'no_unneeded_curly_braces' => ['namespaces' => true],
|
||||
'no_unneeded_final_method' => ['private_methods' => true],
|
||||
'no_unneeded_import_alias' => true,
|
||||
'no_unreachable_default_argument_value' => true,
|
||||
'no_unset_cast' => true,
|
||||
'no_unset_on_property' => false,
|
||||
'no_unused_imports' => true,
|
||||
'no_useless_concat_operator' => ['juggle_simple_strings' => true],
|
||||
'no_useless_else' => true,
|
||||
'no_useless_nullsafe_operator' => false,
|
||||
'no_useless_return' => true,
|
||||
'no_useless_sprintf' => true,
|
||||
'no_whitespace_before_comma_in_array' => ['after_heredoc' => false],
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'non_printable_character' => ['use_escape_sequences_in_strings' => true],
|
||||
'normalize_index_brace' => true,
|
||||
'not_operator_with_space' => false,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => true],
|
||||
'object_operator_without_whitespace' => true,
|
||||
'octal_notation' => false, // requires 8.1+
|
||||
'operator_linebreak' => ['only_booleans' => true, 'position' => 'beginning'],
|
||||
'ordered_class_elements' => [
|
||||
'order' => [
|
||||
'use_trait',
|
||||
'constant_public',
|
||||
'constant_protected',
|
||||
'constant_private',
|
||||
'property_public',
|
||||
'property_protected',
|
||||
'property_private',
|
||||
'construct',
|
||||
'destruct',
|
||||
'magic',
|
||||
'phpunit',
|
||||
'method_public_static',
|
||||
'method_protected_static',
|
||||
'method_private_static',
|
||||
'method_public',
|
||||
'method_protected',
|
||||
'method_private',
|
||||
],
|
||||
'sort_algorithm' => 'none',
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => ['class', 'function', 'const'],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'ordered_interfaces' => false,
|
||||
'ordered_traits' => true,
|
||||
'php_unit_construct' => [
|
||||
'assertions' => [
|
||||
'assertEquals',
|
||||
'assertSame',
|
||||
'assertNotEquals',
|
||||
'assertNotSame',
|
||||
],
|
||||
],
|
||||
'php_unit_dedicate_assert' => ['target' => 'newest'],
|
||||
'php_unit_dedicate_assert_internal_type' => ['target' => 'newest'],
|
||||
'php_unit_expectation' => ['target' => 'newest'],
|
||||
'php_unit_fqcn_annotation' => true,
|
||||
'php_unit_internal_class' => ['types' => ['normal', 'final']],
|
||||
'php_unit_method_casing' => ['case' => 'camel_case'],
|
||||
'php_unit_mock' => ['target' => 'newest'],
|
||||
'php_unit_mock_short_will_return' => true,
|
||||
'php_unit_namespaced' => ['target' => 'newest'],
|
||||
'php_unit_no_expectation_annotation' => [
|
||||
'target' => 'newest',
|
||||
'use_class_const' => true,
|
||||
],
|
||||
'php_unit_set_up_tear_down_visibility' => true,
|
||||
'php_unit_size_class' => false,
|
||||
'php_unit_strict' => [
|
||||
'assertions' => [
|
||||
'assertAttributeEquals',
|
||||
'assertAttributeNotEquals',
|
||||
'assertEquals',
|
||||
'assertNotEquals',
|
||||
],
|
||||
],
|
||||
'php_unit_test_annotation' => ['style' => 'prefix'],
|
||||
'php_unit_test_case_static_method_calls' => [
|
||||
'call_type' => 'self',
|
||||
'methods' => [],
|
||||
],
|
||||
'php_unit_test_class_requires_covers' => false,
|
||||
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
|
||||
'phpdoc_align' => [
|
||||
'align' => 'vertical',
|
||||
'tags' => [
|
||||
'method',
|
||||
'param',
|
||||
'property',
|
||||
'return',
|
||||
'throws',
|
||||
'type',
|
||||
'var',
|
||||
],
|
||||
],
|
||||
'phpdoc_annotation_without_dot' => true,
|
||||
'phpdoc_indent' => true,
|
||||
'phpdoc_inline_tag_normalizer' => [
|
||||
'tags' => [
|
||||
'example',
|
||||
'id',
|
||||
'internal',
|
||||
'inheritdoc',
|
||||
'inheritdocs',
|
||||
'link',
|
||||
'source',
|
||||
'toc',
|
||||
'tutorial',
|
||||
],
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'const' => 'multi',
|
||||
'method' => 'multi',
|
||||
'property' => 'multi',
|
||||
],
|
||||
'phpdoc_no_access' => true,
|
||||
'phpdoc_no_alias_tag' => [
|
||||
'replacements' => [
|
||||
'property-read' => 'property',
|
||||
'property-write' => 'property',
|
||||
'type' => 'var',
|
||||
'link' => 'see',
|
||||
],
|
||||
],
|
||||
'phpdoc_no_empty_return' => false,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_no_useless_inheritdoc' => true,
|
||||
'phpdoc_order' => ['order' => ['param', 'return', 'throws']],
|
||||
'phpdoc_order_by_value' => [
|
||||
'annotations' => [
|
||||
'author',
|
||||
'covers',
|
||||
'coversNothing',
|
||||
'dataProvider',
|
||||
'depends',
|
||||
'group',
|
||||
'internal',
|
||||
'method',
|
||||
'property',
|
||||
'property-read',
|
||||
'property-write',
|
||||
'requires',
|
||||
'throws',
|
||||
'uses',
|
||||
],
|
||||
],
|
||||
'phpdoc_return_self_reference' => [
|
||||
'replacements' => [
|
||||
'this' => '$this',
|
||||
'@this' => '$this',
|
||||
'$self' => 'self',
|
||||
'@self' => 'self',
|
||||
'$static' => 'static',
|
||||
'@static' => 'static',
|
||||
],
|
||||
],
|
||||
'phpdoc_scalar' => [
|
||||
'types' => [
|
||||
'boolean',
|
||||
'callback',
|
||||
'double',
|
||||
'integer',
|
||||
'real',
|
||||
'str',
|
||||
],
|
||||
],
|
||||
'phpdoc_separation' => [
|
||||
'groups' => [
|
||||
['deprecated', 'link', 'see', 'since'],
|
||||
['author', 'copyright', 'license'],
|
||||
['category', 'package', 'subpackage'],
|
||||
['property', 'property-read', 'property-write'],
|
||||
],
|
||||
],
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_summary' => true,
|
||||
'phpdoc_tag_casing' => ['tags' => ['inheritDoc']],
|
||||
'phpdoc_tag_type' => ['tags' => ['inheritDoc' => 'inline']],
|
||||
'phpdoc_to_comment' => ['ignored_tags' => [
|
||||
'phpstan-var',
|
||||
'phpstan-return',
|
||||
]],
|
||||
'phpdoc_to_param_type' => false,
|
||||
'phpdoc_to_property_type' => ['scalar_types' => true],
|
||||
'phpdoc_to_return_type' => false,
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||
'phpdoc_types' => ['groups' => ['simple', 'alias', 'meta']],
|
||||
'phpdoc_types_order' => [
|
||||
'null_adjustment' => 'always_first',
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'phpdoc_var_annotation_correct_order' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'pow_to_exponentiation' => true,
|
||||
'protected_to_private' => true,
|
||||
'psr_autoloading' => ['dir' => null],
|
||||
'random_api_migration' => [
|
||||
'replacements' => [
|
||||
'getrandmax' => 'mt_getrandmax',
|
||||
'rand' => 'mt_rand',
|
||||
'srand' => 'mt_srand',
|
||||
],
|
||||
],
|
||||
'regular_callable_call' => true,
|
||||
'return_assignment' => true,
|
||||
'return_type_declaration' => ['space_before' => 'none'],
|
||||
'self_accessor' => true,
|
||||
'self_static_accessor' => true,
|
||||
'semicolon_after_instruction' => true,
|
||||
'set_type_to_cast' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'simple_to_complex_string_variable' => true,
|
||||
'simplified_if_return' => true,
|
||||
'simplified_null_return' => false,
|
||||
'single_blank_line_at_eof' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'single_class_element_per_statement' => ['elements' => ['const', 'property']],
|
||||
'single_import_per_statement' => ['group_to_single_imports' => true],
|
||||
'single_line_after_imports' => true,
|
||||
'single_line_comment_spacing' => true,
|
||||
'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']],
|
||||
'single_line_throw' => false,
|
||||
'single_quote' => ['strings_containing_single_quote_chars' => false],
|
||||
'single_space_after_construct' => [
|
||||
'constructs' => [
|
||||
'abstract',
|
||||
'as',
|
||||
'attribute',
|
||||
'break',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'clone',
|
||||
'comment',
|
||||
'const',
|
||||
'const_import',
|
||||
'continue',
|
||||
'do',
|
||||
'echo',
|
||||
'else',
|
||||
'elseif',
|
||||
'extends',
|
||||
'final',
|
||||
'finally',
|
||||
'for',
|
||||
'foreach',
|
||||
'function',
|
||||
'function_import',
|
||||
'global',
|
||||
'goto',
|
||||
'if',
|
||||
'implements',
|
||||
'include',
|
||||
'include_once',
|
||||
'instanceof',
|
||||
'insteadof',
|
||||
'interface',
|
||||
'match',
|
||||
'named_argument',
|
||||
'new',
|
||||
'open_tag_with_echo',
|
||||
'php_doc',
|
||||
'php_open',
|
||||
'print',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'require',
|
||||
'require_once',
|
||||
'return',
|
||||
'static',
|
||||
'throw',
|
||||
'trait',
|
||||
'try',
|
||||
'use',
|
||||
'use_lambda',
|
||||
'use_trait',
|
||||
'var',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'single_trait_insert_per_statement' => true,
|
||||
'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
|
||||
'standardize_increment' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'statement_indentation' => true,
|
||||
'static_lambda' => true,
|
||||
'strict_comparison' => true,
|
||||
'strict_param' => true,
|
||||
'string_length_to_empty' => true,
|
||||
'string_line_ending' => true,
|
||||
'switch_case_semicolon_to_colon' => true,
|
||||
'switch_case_space' => true,
|
||||
'switch_continue_to_break' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'ternary_to_elvis_operator' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'trailing_comma_in_multiline' => [
|
||||
'after_heredoc' => true,
|
||||
'elements' => ['arrays', 'arguments'],
|
||||
],
|
||||
'trim_array_spaces' => true,
|
||||
'types_spaces' => ['space' => 'none', 'space_multiple_catch' => null],
|
||||
'unary_operator_spaces' => true,
|
||||
'use_arrow_functions' => true,
|
||||
'visibility_required' => ['elements' => ['const', 'method', 'property']],
|
||||
'void_return' => false,
|
||||
'whitespace_after_comma_in_array' => ['ensure_single_space' => true],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => true,
|
||||
'equal' => true,
|
||||
'identical' => true,
|
||||
'less_and_greater' => null,
|
||||
],
|
||||
];
|
||||
$this->requiredPHPVersion = 70400;
|
||||
$this->autoActivateIsRiskyAllowed = true;
|
||||
}
|
||||
}
|
||||
+637
@@ -0,0 +1,637 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Ruleset;
|
||||
|
||||
/**
|
||||
* Ruleset for `Nexus` group.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Nexus80 extends AbstractRuleset
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'Nexus for PHP 8.0';
|
||||
$this->rules = [
|
||||
'align_multiline_comment' => ['comment_type' => 'all_multiline'],
|
||||
'array_indentation' => true,
|
||||
'array_push' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'assign_null_coalescing_to_coalesce_equal' => true,
|
||||
'backtick_to_shell_exec' => true,
|
||||
'binary_operator_spaces' => [
|
||||
'default' => 'single_space',
|
||||
'operators' => [],
|
||||
],
|
||||
'blank_line_after_namespace' => true,
|
||||
'blank_line_after_opening_tag' => true,
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'case',
|
||||
'continue',
|
||||
'declare',
|
||||
'default',
|
||||
'do',
|
||||
'exit',
|
||||
'for',
|
||||
'foreach',
|
||||
'goto',
|
||||
'if',
|
||||
'return',
|
||||
'switch',
|
||||
'throw',
|
||||
'try',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'blank_line_between_import_groups' => true,
|
||||
'braces' => [
|
||||
'allow_single_line_anonymous_class_with_empty_body' => true,
|
||||
'allow_single_line_closure' => true,
|
||||
'position_after_anonymous_constructs' => 'same',
|
||||
'position_after_control_structures' => 'same',
|
||||
'position_after_functions_and_oop_constructs' => 'next',
|
||||
],
|
||||
'cast_spaces' => ['space' => 'single'],
|
||||
'class_attributes_separation' => [
|
||||
'elements' => [
|
||||
'const' => 'none',
|
||||
'property' => 'none',
|
||||
'method' => 'one',
|
||||
'trait_import' => 'none',
|
||||
],
|
||||
],
|
||||
'class_definition' => [
|
||||
'multi_line_extends_each_single_line' => true,
|
||||
'single_item_single_line' => true,
|
||||
'single_line' => true,
|
||||
'space_before_parenthesis' => true,
|
||||
'inline_constructor_arguments' => true,
|
||||
],
|
||||
'class_reference_name_casing' => true,
|
||||
'clean_namespace' => true,
|
||||
'combine_consecutive_issets' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'combine_nested_dirname' => true,
|
||||
'comment_to_phpdoc' => [
|
||||
'ignored_tags' => [
|
||||
'todo',
|
||||
'codeCoverageIgnore',
|
||||
'codeCoverageIgnoreStart',
|
||||
'codeCoverageIgnoreEnd',
|
||||
'phpstan-ignore-line',
|
||||
'phpstan-ignore-next-line',
|
||||
],
|
||||
],
|
||||
'compact_nullable_typehint' => true,
|
||||
'concat_space' => ['spacing' => 'none'],
|
||||
'constant_case' => ['case' => 'lower'],
|
||||
'control_structure_braces' => true,
|
||||
'control_structure_continuation_position' => ['position' => 'same_line'],
|
||||
'curly_braces_position' => [
|
||||
'control_structures_opening_brace' => 'same_line',
|
||||
'functions_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_functions_opening_brace' => 'same_line',
|
||||
'classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_classes_opening_brace' => 'same_line',
|
||||
'allow_single_line_empty_anonymous_classes' => true,
|
||||
'allow_single_line_anonymous_functions' => true,
|
||||
],
|
||||
'date_time_create_from_format_call' => true,
|
||||
'date_time_immutable' => true,
|
||||
'declare_equal_normalize' => ['space' => 'none'],
|
||||
'declare_parentheses' => true,
|
||||
'declare_strict_types' => true,
|
||||
'dir_constant' => true,
|
||||
'doctrine_annotation_array_assignment' => false,
|
||||
'doctrine_annotation_braces' => false,
|
||||
'doctrine_annotation_indentation' => false,
|
||||
'doctrine_annotation_spaces' => false,
|
||||
'echo_tag_syntax' => [
|
||||
'format' => 'short',
|
||||
'long_function' => 'echo',
|
||||
'shorten_simple_statements_only' => true,
|
||||
],
|
||||
'elseif' => true,
|
||||
'empty_loop_body' => ['style' => 'braces'],
|
||||
'empty_loop_condition' => ['style' => 'while'],
|
||||
'encoding' => true,
|
||||
'ereg_to_preg' => true,
|
||||
'error_suppression' => [
|
||||
'mute_deprecation_error' => true,
|
||||
'noise_remaining_usages' => false,
|
||||
'noise_remaining_usages_exclude' => [],
|
||||
],
|
||||
'escape_implicit_backslashes' => [
|
||||
'double_quoted' => true,
|
||||
'heredoc_syntax' => true,
|
||||
'single_quoted' => false,
|
||||
],
|
||||
'explicit_indirect_variable' => true,
|
||||
'explicit_string_variable' => true,
|
||||
'final_class' => false,
|
||||
'final_internal_class' => [
|
||||
'annotation_exclude' => ['@final', '@no-final'],
|
||||
'annotation_include' => ['@internal'],
|
||||
'consider_absent_docblock_as_internal_class' => true,
|
||||
],
|
||||
'final_public_method_for_abstract_class' => true,
|
||||
'fopen_flag_order' => true,
|
||||
'fopen_flags' => ['b_mode' => true],
|
||||
'full_opening_tag' => true,
|
||||
'fully_qualified_strict_types' => true,
|
||||
'function_declaration' => [
|
||||
'closure_function_spacing' => 'one',
|
||||
'closure_fn_spacing' => 'one',
|
||||
'trailing_comma_single_line' => false,
|
||||
],
|
||||
'function_to_constant' => [
|
||||
'functions' => [
|
||||
'get_called_class',
|
||||
'get_class',
|
||||
'get_class_this',
|
||||
'php_sapi_name',
|
||||
'phpversion',
|
||||
'pi',
|
||||
],
|
||||
],
|
||||
'function_typehint_space' => true,
|
||||
'general_phpdoc_annotation_remove' => [
|
||||
'annotations' => [
|
||||
'package',
|
||||
'subpackage',
|
||||
],
|
||||
'case_sensitive' => false,
|
||||
],
|
||||
'general_phpdoc_tag_rename' => [
|
||||
'case_sensitive' => false,
|
||||
'fix_annotation' => true,
|
||||
'fix_inline' => true,
|
||||
'replacements' => ['inheritDocs' => 'inheritDoc'],
|
||||
],
|
||||
'get_class_to_class_keyword' => true,
|
||||
'global_namespace_import' => [
|
||||
'import_classes' => false,
|
||||
'import_constants' => false,
|
||||
'import_functions' => false,
|
||||
],
|
||||
'group_import' => false,
|
||||
'header_comment' => false,
|
||||
'heredoc_indentation' => ['indentation' => 'start_plus_one'],
|
||||
'heredoc_to_nowdoc' => true,
|
||||
'implode_call' => true,
|
||||
'include' => true,
|
||||
'increment_style' => ['style' => 'pre'],
|
||||
'indentation_type' => true,
|
||||
'integer_literal_case' => true,
|
||||
'is_null' => true,
|
||||
'lambda_not_used_import' => true,
|
||||
'line_ending' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'list_syntax' => ['syntax' => 'short'],
|
||||
'logical_operators' => true,
|
||||
'lowercase_cast' => true,
|
||||
'lowercase_keywords' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'magic_constant_casing' => true,
|
||||
'magic_method_casing' => true,
|
||||
'mb_str_functions' => false,
|
||||
'method_argument_space' => [
|
||||
'after_heredoc' => true,
|
||||
'keep_multiple_spaces_after_comma' => false,
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
],
|
||||
'method_chaining_indentation' => true,
|
||||
'modernize_strpos' => true,
|
||||
'modernize_types_casting' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
|
||||
'native_constant_invocation' => [
|
||||
'fix_built_in' => false,
|
||||
'include' => [
|
||||
'DIRECTORY_SEPARATOR',
|
||||
'PHP_INT_SIZE',
|
||||
'PHP_SAPI',
|
||||
'PHP_VERSION_ID',
|
||||
],
|
||||
'exclude' => [],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_casing' => true,
|
||||
'native_function_invocation' => [
|
||||
'exclude' => [],
|
||||
'include' => ['@compiler_optimized'],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_type_declaration_casing' => true,
|
||||
'new_with_braces' => [
|
||||
'named_class' => true,
|
||||
'anonymous_class' => true,
|
||||
],
|
||||
'no_alias_functions' => ['sets' => ['@all']],
|
||||
'no_alias_language_construct_call' => true,
|
||||
'no_alternative_syntax' => ['fix_non_monolithic_code' => false],
|
||||
'no_binary_string' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_blank_lines_after_phpdoc' => true,
|
||||
'no_blank_lines_before_namespace' => false,
|
||||
'no_break_comment' => ['comment_text' => 'no break'],
|
||||
'no_closing_tag' => true,
|
||||
'no_empty_comment' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_empty_statement' => true,
|
||||
'no_extra_blank_lines' => [
|
||||
'tokens' => [
|
||||
'extra',
|
||||
'break',
|
||||
'continue',
|
||||
'curly_brace_block',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'return',
|
||||
'throw',
|
||||
'use',
|
||||
'switch',
|
||||
'case',
|
||||
'default',
|
||||
],
|
||||
],
|
||||
'no_homoglyph_names' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'no_mixed_echo_print' => ['use' => 'echo'],
|
||||
'no_multiline_whitespace_around_double_arrow' => true,
|
||||
'no_multiple_statements_per_line' => true,
|
||||
'no_null_property_initialization' => true,
|
||||
'no_php4_constructor' => true,
|
||||
'no_short_bool_cast' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_space_around_double_colon' => true,
|
||||
'no_spaces_after_function_name' => true,
|
||||
'no_spaces_around_offset' => ['positions' => ['inside', 'outside']],
|
||||
'no_spaces_inside_parenthesis' => true,
|
||||
'no_superfluous_elseif' => true,
|
||||
'no_superfluous_phpdoc_tags' => [
|
||||
'allow_mixed' => true,
|
||||
'allow_unused_params' => true,
|
||||
'remove_inheritdoc' => false,
|
||||
],
|
||||
'no_trailing_comma_in_singleline' => [
|
||||
'elements' => ['arguments', 'array', 'array_destructuring', 'group_import'],
|
||||
],
|
||||
'no_trailing_whitespace' => true,
|
||||
'no_trailing_whitespace_in_comment' => true,
|
||||
'no_trailing_whitespace_in_string' => true,
|
||||
'no_unneeded_control_parentheses' => [
|
||||
'statements' => [
|
||||
'break',
|
||||
'clone',
|
||||
'continue',
|
||||
'echo_print',
|
||||
'return',
|
||||
'switch_case',
|
||||
'yield',
|
||||
],
|
||||
],
|
||||
'no_unneeded_curly_braces' => ['namespaces' => true],
|
||||
'no_unneeded_final_method' => ['private_methods' => true],
|
||||
'no_unneeded_import_alias' => true,
|
||||
'no_unreachable_default_argument_value' => true,
|
||||
'no_unset_cast' => true,
|
||||
'no_unset_on_property' => false,
|
||||
'no_unused_imports' => true,
|
||||
'no_useless_concat_operator' => ['juggle_simple_strings' => true],
|
||||
'no_useless_else' => true,
|
||||
'no_useless_nullsafe_operator' => true,
|
||||
'no_useless_return' => true,
|
||||
'no_useless_sprintf' => true,
|
||||
'no_whitespace_before_comma_in_array' => ['after_heredoc' => false],
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'non_printable_character' => ['use_escape_sequences_in_strings' => true],
|
||||
'normalize_index_brace' => true,
|
||||
'not_operator_with_space' => false,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => true],
|
||||
'object_operator_without_whitespace' => true,
|
||||
'octal_notation' => false, // requires 8.1+
|
||||
'operator_linebreak' => ['only_booleans' => true, 'position' => 'beginning'],
|
||||
'ordered_class_elements' => [
|
||||
'order' => [
|
||||
'use_trait',
|
||||
'constant_public',
|
||||
'constant_protected',
|
||||
'constant_private',
|
||||
'property_public',
|
||||
'property_protected',
|
||||
'property_private',
|
||||
'construct',
|
||||
'destruct',
|
||||
'magic',
|
||||
'phpunit',
|
||||
'method_public_static',
|
||||
'method_protected_static',
|
||||
'method_private_static',
|
||||
'method_public',
|
||||
'method_protected',
|
||||
'method_private',
|
||||
],
|
||||
'sort_algorithm' => 'none',
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => ['class', 'function', 'const'],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'ordered_interfaces' => false,
|
||||
'ordered_traits' => true,
|
||||
'php_unit_construct' => [
|
||||
'assertions' => [
|
||||
'assertEquals',
|
||||
'assertSame',
|
||||
'assertNotEquals',
|
||||
'assertNotSame',
|
||||
],
|
||||
],
|
||||
'php_unit_dedicate_assert' => ['target' => 'newest'],
|
||||
'php_unit_dedicate_assert_internal_type' => ['target' => 'newest'],
|
||||
'php_unit_expectation' => ['target' => 'newest'],
|
||||
'php_unit_fqcn_annotation' => true,
|
||||
'php_unit_internal_class' => ['types' => ['normal', 'final']],
|
||||
'php_unit_method_casing' => ['case' => 'camel_case'],
|
||||
'php_unit_mock' => ['target' => 'newest'],
|
||||
'php_unit_mock_short_will_return' => true,
|
||||
'php_unit_namespaced' => ['target' => 'newest'],
|
||||
'php_unit_no_expectation_annotation' => [
|
||||
'target' => 'newest',
|
||||
'use_class_const' => true,
|
||||
],
|
||||
'php_unit_set_up_tear_down_visibility' => true,
|
||||
'php_unit_size_class' => false,
|
||||
'php_unit_strict' => [
|
||||
'assertions' => [
|
||||
'assertAttributeEquals',
|
||||
'assertAttributeNotEquals',
|
||||
'assertEquals',
|
||||
'assertNotEquals',
|
||||
],
|
||||
],
|
||||
'php_unit_test_annotation' => ['style' => 'prefix'],
|
||||
'php_unit_test_case_static_method_calls' => [
|
||||
'call_type' => 'self',
|
||||
'methods' => [],
|
||||
],
|
||||
'php_unit_test_class_requires_covers' => false,
|
||||
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
|
||||
'phpdoc_align' => [
|
||||
'align' => 'vertical',
|
||||
'tags' => [
|
||||
'method',
|
||||
'param',
|
||||
'property',
|
||||
'return',
|
||||
'throws',
|
||||
'type',
|
||||
'var',
|
||||
],
|
||||
],
|
||||
'phpdoc_annotation_without_dot' => true,
|
||||
'phpdoc_indent' => true,
|
||||
'phpdoc_inline_tag_normalizer' => [
|
||||
'tags' => [
|
||||
'example',
|
||||
'id',
|
||||
'internal',
|
||||
'inheritdoc',
|
||||
'inheritdocs',
|
||||
'link',
|
||||
'source',
|
||||
'toc',
|
||||
'tutorial',
|
||||
],
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'const' => 'multi',
|
||||
'method' => 'multi',
|
||||
'property' => 'multi',
|
||||
],
|
||||
'phpdoc_no_access' => true,
|
||||
'phpdoc_no_alias_tag' => [
|
||||
'replacements' => [
|
||||
'property-read' => 'property',
|
||||
'property-write' => 'property',
|
||||
'type' => 'var',
|
||||
'link' => 'see',
|
||||
],
|
||||
],
|
||||
'phpdoc_no_empty_return' => false,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_no_useless_inheritdoc' => true,
|
||||
'phpdoc_order' => ['order' => ['param', 'return', 'throws']],
|
||||
'phpdoc_order_by_value' => [
|
||||
'annotations' => [
|
||||
'author',
|
||||
'covers',
|
||||
'coversNothing',
|
||||
'dataProvider',
|
||||
'depends',
|
||||
'group',
|
||||
'internal',
|
||||
'method',
|
||||
'property',
|
||||
'property-read',
|
||||
'property-write',
|
||||
'requires',
|
||||
'throws',
|
||||
'uses',
|
||||
],
|
||||
],
|
||||
'phpdoc_return_self_reference' => [
|
||||
'replacements' => [
|
||||
'this' => '$this',
|
||||
'@this' => '$this',
|
||||
'$self' => 'self',
|
||||
'@self' => 'self',
|
||||
'$static' => 'static',
|
||||
'@static' => 'static',
|
||||
],
|
||||
],
|
||||
'phpdoc_scalar' => [
|
||||
'types' => [
|
||||
'boolean',
|
||||
'callback',
|
||||
'double',
|
||||
'integer',
|
||||
'real',
|
||||
'str',
|
||||
],
|
||||
],
|
||||
'phpdoc_separation' => [
|
||||
'groups' => [
|
||||
['deprecated', 'link', 'see', 'since'],
|
||||
['author', 'copyright', 'license'],
|
||||
['category', 'package', 'subpackage'],
|
||||
['property', 'property-read', 'property-write'],
|
||||
],
|
||||
],
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_summary' => true,
|
||||
'phpdoc_tag_casing' => ['tags' => ['inheritDoc']],
|
||||
'phpdoc_tag_type' => ['tags' => ['inheritDoc' => 'inline']],
|
||||
'phpdoc_to_comment' => ['ignored_tags' => [
|
||||
'phpstan-var',
|
||||
'phpstan-return',
|
||||
]],
|
||||
'phpdoc_to_param_type' => ['scalar_types' => true],
|
||||
'phpdoc_to_property_type' => ['scalar_types' => true],
|
||||
'phpdoc_to_return_type' => ['scalar_types' => true],
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||
'phpdoc_types' => ['groups' => ['simple', 'alias', 'meta']],
|
||||
'phpdoc_types_order' => [
|
||||
'null_adjustment' => 'always_first',
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'phpdoc_var_annotation_correct_order' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'pow_to_exponentiation' => true,
|
||||
'protected_to_private' => true,
|
||||
'psr_autoloading' => ['dir' => null],
|
||||
'random_api_migration' => [
|
||||
'replacements' => [
|
||||
'getrandmax' => 'mt_getrandmax',
|
||||
'rand' => 'mt_rand',
|
||||
'srand' => 'mt_srand',
|
||||
],
|
||||
],
|
||||
'regular_callable_call' => true,
|
||||
'return_assignment' => true,
|
||||
'return_type_declaration' => ['space_before' => 'none'],
|
||||
'self_accessor' => true,
|
||||
'self_static_accessor' => true,
|
||||
'semicolon_after_instruction' => true,
|
||||
'set_type_to_cast' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'simple_to_complex_string_variable' => true,
|
||||
'simplified_if_return' => true,
|
||||
'simplified_null_return' => false,
|
||||
'single_blank_line_at_eof' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'single_class_element_per_statement' => ['elements' => ['const', 'property']],
|
||||
'single_import_per_statement' => ['group_to_single_imports' => true],
|
||||
'single_line_after_imports' => true,
|
||||
'single_line_comment_spacing' => true,
|
||||
'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']],
|
||||
'single_line_throw' => false,
|
||||
'single_quote' => ['strings_containing_single_quote_chars' => false],
|
||||
'single_space_after_construct' => [
|
||||
'constructs' => [
|
||||
'abstract',
|
||||
'as',
|
||||
'attribute',
|
||||
'break',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'clone',
|
||||
'comment',
|
||||
'const',
|
||||
'const_import',
|
||||
'continue',
|
||||
'do',
|
||||
'echo',
|
||||
'else',
|
||||
'elseif',
|
||||
'extends',
|
||||
'final',
|
||||
'finally',
|
||||
'for',
|
||||
'foreach',
|
||||
'function',
|
||||
'function_import',
|
||||
'global',
|
||||
'goto',
|
||||
'if',
|
||||
'implements',
|
||||
'include',
|
||||
'include_once',
|
||||
'instanceof',
|
||||
'insteadof',
|
||||
'interface',
|
||||
'match',
|
||||
'named_argument',
|
||||
'new',
|
||||
'open_tag_with_echo',
|
||||
'php_doc',
|
||||
'php_open',
|
||||
'print',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'require',
|
||||
'require_once',
|
||||
'return',
|
||||
'static',
|
||||
'throw',
|
||||
'trait',
|
||||
'try',
|
||||
'use',
|
||||
'use_lambda',
|
||||
'use_trait',
|
||||
'var',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'single_trait_insert_per_statement' => true,
|
||||
'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
|
||||
'standardize_increment' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'statement_indentation' => true,
|
||||
'static_lambda' => true,
|
||||
'strict_comparison' => true,
|
||||
'strict_param' => true,
|
||||
'string_length_to_empty' => true,
|
||||
'string_line_ending' => true,
|
||||
'switch_case_semicolon_to_colon' => true,
|
||||
'switch_case_space' => true,
|
||||
'switch_continue_to_break' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'ternary_to_elvis_operator' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'trailing_comma_in_multiline' => [
|
||||
'after_heredoc' => true,
|
||||
'elements' => ['arrays', 'arguments', 'parameters'],
|
||||
],
|
||||
'trim_array_spaces' => true,
|
||||
'types_spaces' => ['space' => 'none', 'space_multiple_catch' => null],
|
||||
'unary_operator_spaces' => true,
|
||||
'use_arrow_functions' => true,
|
||||
'visibility_required' => ['elements' => ['const', 'method', 'property']],
|
||||
'void_return' => true,
|
||||
'whitespace_after_comma_in_array' => ['ensure_single_space' => true],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => true,
|
||||
'equal' => true,
|
||||
'identical' => true,
|
||||
'less_and_greater' => null,
|
||||
],
|
||||
];
|
||||
$this->requiredPHPVersion = 80000;
|
||||
$this->autoActivateIsRiskyAllowed = true;
|
||||
}
|
||||
}
|
||||
+637
@@ -0,0 +1,637 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Ruleset;
|
||||
|
||||
/**
|
||||
* Ruleset for `Nexus` group.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Nexus81 extends AbstractRuleset
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'Nexus for PHP 8.1';
|
||||
$this->rules = [
|
||||
'align_multiline_comment' => ['comment_type' => 'all_multiline'],
|
||||
'array_indentation' => true,
|
||||
'array_push' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'assign_null_coalescing_to_coalesce_equal' => true,
|
||||
'backtick_to_shell_exec' => true,
|
||||
'binary_operator_spaces' => [
|
||||
'default' => 'single_space',
|
||||
'operators' => [],
|
||||
],
|
||||
'blank_line_after_namespace' => true,
|
||||
'blank_line_after_opening_tag' => true,
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'case',
|
||||
'continue',
|
||||
'declare',
|
||||
'default',
|
||||
'do',
|
||||
'exit',
|
||||
'for',
|
||||
'foreach',
|
||||
'goto',
|
||||
'if',
|
||||
'return',
|
||||
'switch',
|
||||
'throw',
|
||||
'try',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'blank_line_between_import_groups' => true,
|
||||
'braces' => [
|
||||
'allow_single_line_anonymous_class_with_empty_body' => true,
|
||||
'allow_single_line_closure' => true,
|
||||
'position_after_anonymous_constructs' => 'same',
|
||||
'position_after_control_structures' => 'same',
|
||||
'position_after_functions_and_oop_constructs' => 'next',
|
||||
],
|
||||
'cast_spaces' => ['space' => 'single'],
|
||||
'class_attributes_separation' => [
|
||||
'elements' => [
|
||||
'const' => 'none',
|
||||
'property' => 'none',
|
||||
'method' => 'one',
|
||||
'trait_import' => 'none',
|
||||
],
|
||||
],
|
||||
'class_definition' => [
|
||||
'multi_line_extends_each_single_line' => true,
|
||||
'single_item_single_line' => true,
|
||||
'single_line' => true,
|
||||
'space_before_parenthesis' => true,
|
||||
'inline_constructor_arguments' => true,
|
||||
],
|
||||
'class_reference_name_casing' => true,
|
||||
'clean_namespace' => true,
|
||||
'combine_consecutive_issets' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'combine_nested_dirname' => true,
|
||||
'comment_to_phpdoc' => [
|
||||
'ignored_tags' => [
|
||||
'todo',
|
||||
'codeCoverageIgnore',
|
||||
'codeCoverageIgnoreStart',
|
||||
'codeCoverageIgnoreEnd',
|
||||
'phpstan-ignore-line',
|
||||
'phpstan-ignore-next-line',
|
||||
],
|
||||
],
|
||||
'compact_nullable_typehint' => true,
|
||||
'concat_space' => ['spacing' => 'none'],
|
||||
'constant_case' => ['case' => 'lower'],
|
||||
'control_structure_braces' => true,
|
||||
'control_structure_continuation_position' => ['position' => 'same_line'],
|
||||
'curly_braces_position' => [
|
||||
'control_structures_opening_brace' => 'same_line',
|
||||
'functions_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_functions_opening_brace' => 'same_line',
|
||||
'classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||
'anonymous_classes_opening_brace' => 'same_line',
|
||||
'allow_single_line_empty_anonymous_classes' => true,
|
||||
'allow_single_line_anonymous_functions' => true,
|
||||
],
|
||||
'date_time_create_from_format_call' => true,
|
||||
'date_time_immutable' => true,
|
||||
'declare_equal_normalize' => ['space' => 'none'],
|
||||
'declare_parentheses' => true,
|
||||
'declare_strict_types' => true,
|
||||
'dir_constant' => true,
|
||||
'doctrine_annotation_array_assignment' => false,
|
||||
'doctrine_annotation_braces' => false,
|
||||
'doctrine_annotation_indentation' => false,
|
||||
'doctrine_annotation_spaces' => false,
|
||||
'echo_tag_syntax' => [
|
||||
'format' => 'short',
|
||||
'long_function' => 'echo',
|
||||
'shorten_simple_statements_only' => true,
|
||||
],
|
||||
'elseif' => true,
|
||||
'empty_loop_body' => ['style' => 'braces'],
|
||||
'empty_loop_condition' => ['style' => 'while'],
|
||||
'encoding' => true,
|
||||
'ereg_to_preg' => true,
|
||||
'error_suppression' => [
|
||||
'mute_deprecation_error' => true,
|
||||
'noise_remaining_usages' => false,
|
||||
'noise_remaining_usages_exclude' => [],
|
||||
],
|
||||
'escape_implicit_backslashes' => [
|
||||
'double_quoted' => true,
|
||||
'heredoc_syntax' => true,
|
||||
'single_quoted' => false,
|
||||
],
|
||||
'explicit_indirect_variable' => true,
|
||||
'explicit_string_variable' => true,
|
||||
'final_class' => false,
|
||||
'final_internal_class' => [
|
||||
'annotation_exclude' => ['@final', '@no-final'],
|
||||
'annotation_include' => ['@internal'],
|
||||
'consider_absent_docblock_as_internal_class' => true,
|
||||
],
|
||||
'final_public_method_for_abstract_class' => true,
|
||||
'fopen_flag_order' => true,
|
||||
'fopen_flags' => ['b_mode' => true],
|
||||
'full_opening_tag' => true,
|
||||
'fully_qualified_strict_types' => true,
|
||||
'function_declaration' => [
|
||||
'closure_function_spacing' => 'one',
|
||||
'closure_fn_spacing' => 'one',
|
||||
'trailing_comma_single_line' => false,
|
||||
],
|
||||
'function_to_constant' => [
|
||||
'functions' => [
|
||||
'get_called_class',
|
||||
'get_class',
|
||||
'get_class_this',
|
||||
'php_sapi_name',
|
||||
'phpversion',
|
||||
'pi',
|
||||
],
|
||||
],
|
||||
'function_typehint_space' => true,
|
||||
'general_phpdoc_annotation_remove' => [
|
||||
'annotations' => [
|
||||
'package',
|
||||
'subpackage',
|
||||
],
|
||||
'case_sensitive' => false,
|
||||
],
|
||||
'general_phpdoc_tag_rename' => [
|
||||
'case_sensitive' => false,
|
||||
'fix_annotation' => true,
|
||||
'fix_inline' => true,
|
||||
'replacements' => ['inheritDocs' => 'inheritDoc'],
|
||||
],
|
||||
'get_class_to_class_keyword' => true,
|
||||
'global_namespace_import' => [
|
||||
'import_classes' => false,
|
||||
'import_constants' => false,
|
||||
'import_functions' => false,
|
||||
],
|
||||
'group_import' => false,
|
||||
'header_comment' => false,
|
||||
'heredoc_indentation' => ['indentation' => 'start_plus_one'],
|
||||
'heredoc_to_nowdoc' => true,
|
||||
'implode_call' => true,
|
||||
'include' => true,
|
||||
'increment_style' => ['style' => 'pre'],
|
||||
'indentation_type' => true,
|
||||
'integer_literal_case' => true,
|
||||
'is_null' => true,
|
||||
'lambda_not_used_import' => true,
|
||||
'line_ending' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'list_syntax' => ['syntax' => 'short'],
|
||||
'logical_operators' => true,
|
||||
'lowercase_cast' => true,
|
||||
'lowercase_keywords' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'magic_constant_casing' => true,
|
||||
'magic_method_casing' => true,
|
||||
'mb_str_functions' => false,
|
||||
'method_argument_space' => [
|
||||
'after_heredoc' => true,
|
||||
'keep_multiple_spaces_after_comma' => false,
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
],
|
||||
'method_chaining_indentation' => true,
|
||||
'modernize_strpos' => true,
|
||||
'modernize_types_casting' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
|
||||
'native_constant_invocation' => [
|
||||
'fix_built_in' => false,
|
||||
'include' => [
|
||||
'DIRECTORY_SEPARATOR',
|
||||
'PHP_INT_SIZE',
|
||||
'PHP_SAPI',
|
||||
'PHP_VERSION_ID',
|
||||
],
|
||||
'exclude' => [],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_casing' => true,
|
||||
'native_function_invocation' => [
|
||||
'exclude' => [],
|
||||
'include' => ['@compiler_optimized'],
|
||||
'scope' => 'namespaced',
|
||||
'strict' => true,
|
||||
],
|
||||
'native_function_type_declaration_casing' => true,
|
||||
'new_with_braces' => [
|
||||
'named_class' => true,
|
||||
'anonymous_class' => true,
|
||||
],
|
||||
'no_alias_functions' => ['sets' => ['@all']],
|
||||
'no_alias_language_construct_call' => true,
|
||||
'no_alternative_syntax' => ['fix_non_monolithic_code' => false],
|
||||
'no_binary_string' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_blank_lines_after_phpdoc' => true,
|
||||
'no_blank_lines_before_namespace' => false,
|
||||
'no_break_comment' => ['comment_text' => 'no break'],
|
||||
'no_closing_tag' => true,
|
||||
'no_empty_comment' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_empty_statement' => true,
|
||||
'no_extra_blank_lines' => [
|
||||
'tokens' => [
|
||||
'extra',
|
||||
'break',
|
||||
'continue',
|
||||
'curly_brace_block',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'return',
|
||||
'throw',
|
||||
'use',
|
||||
'switch',
|
||||
'case',
|
||||
'default',
|
||||
],
|
||||
],
|
||||
'no_homoglyph_names' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'no_mixed_echo_print' => ['use' => 'echo'],
|
||||
'no_multiline_whitespace_around_double_arrow' => true,
|
||||
'no_multiple_statements_per_line' => true,
|
||||
'no_null_property_initialization' => true,
|
||||
'no_php4_constructor' => true,
|
||||
'no_short_bool_cast' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_space_around_double_colon' => true,
|
||||
'no_spaces_after_function_name' => true,
|
||||
'no_spaces_around_offset' => ['positions' => ['inside', 'outside']],
|
||||
'no_spaces_inside_parenthesis' => true,
|
||||
'no_superfluous_elseif' => true,
|
||||
'no_superfluous_phpdoc_tags' => [
|
||||
'allow_mixed' => true,
|
||||
'allow_unused_params' => true,
|
||||
'remove_inheritdoc' => false,
|
||||
],
|
||||
'no_trailing_comma_in_singleline' => [
|
||||
'elements' => ['arguments', 'array', 'array_destructuring', 'group_import'],
|
||||
],
|
||||
'no_trailing_whitespace' => true,
|
||||
'no_trailing_whitespace_in_comment' => true,
|
||||
'no_trailing_whitespace_in_string' => true,
|
||||
'no_unneeded_control_parentheses' => [
|
||||
'statements' => [
|
||||
'break',
|
||||
'clone',
|
||||
'continue',
|
||||
'echo_print',
|
||||
'return',
|
||||
'switch_case',
|
||||
'yield',
|
||||
],
|
||||
],
|
||||
'no_unneeded_curly_braces' => ['namespaces' => true],
|
||||
'no_unneeded_final_method' => ['private_methods' => true],
|
||||
'no_unneeded_import_alias' => true,
|
||||
'no_unreachable_default_argument_value' => true,
|
||||
'no_unset_cast' => true,
|
||||
'no_unset_on_property' => false,
|
||||
'no_unused_imports' => true,
|
||||
'no_useless_concat_operator' => ['juggle_simple_strings' => true],
|
||||
'no_useless_else' => true,
|
||||
'no_useless_nullsafe_operator' => true,
|
||||
'no_useless_return' => true,
|
||||
'no_useless_sprintf' => true,
|
||||
'no_whitespace_before_comma_in_array' => ['after_heredoc' => false],
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'non_printable_character' => ['use_escape_sequences_in_strings' => true],
|
||||
'normalize_index_brace' => true,
|
||||
'not_operator_with_space' => false,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => true],
|
||||
'object_operator_without_whitespace' => true,
|
||||
'octal_notation' => true,
|
||||
'operator_linebreak' => ['only_booleans' => true, 'position' => 'beginning'],
|
||||
'ordered_class_elements' => [
|
||||
'order' => [
|
||||
'use_trait',
|
||||
'constant_public',
|
||||
'constant_protected',
|
||||
'constant_private',
|
||||
'property_public',
|
||||
'property_protected',
|
||||
'property_private',
|
||||
'construct',
|
||||
'destruct',
|
||||
'magic',
|
||||
'phpunit',
|
||||
'method_public_static',
|
||||
'method_protected_static',
|
||||
'method_private_static',
|
||||
'method_public',
|
||||
'method_protected',
|
||||
'method_private',
|
||||
],
|
||||
'sort_algorithm' => 'none',
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => ['class', 'function', 'const'],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'ordered_interfaces' => false,
|
||||
'ordered_traits' => true,
|
||||
'php_unit_construct' => [
|
||||
'assertions' => [
|
||||
'assertEquals',
|
||||
'assertSame',
|
||||
'assertNotEquals',
|
||||
'assertNotSame',
|
||||
],
|
||||
],
|
||||
'php_unit_dedicate_assert' => ['target' => 'newest'],
|
||||
'php_unit_dedicate_assert_internal_type' => ['target' => 'newest'],
|
||||
'php_unit_expectation' => ['target' => 'newest'],
|
||||
'php_unit_fqcn_annotation' => true,
|
||||
'php_unit_internal_class' => ['types' => ['normal', 'final']],
|
||||
'php_unit_method_casing' => ['case' => 'camel_case'],
|
||||
'php_unit_mock' => ['target' => 'newest'],
|
||||
'php_unit_mock_short_will_return' => true,
|
||||
'php_unit_namespaced' => ['target' => 'newest'],
|
||||
'php_unit_no_expectation_annotation' => [
|
||||
'target' => 'newest',
|
||||
'use_class_const' => true,
|
||||
],
|
||||
'php_unit_set_up_tear_down_visibility' => true,
|
||||
'php_unit_size_class' => false,
|
||||
'php_unit_strict' => [
|
||||
'assertions' => [
|
||||
'assertAttributeEquals',
|
||||
'assertAttributeNotEquals',
|
||||
'assertEquals',
|
||||
'assertNotEquals',
|
||||
],
|
||||
],
|
||||
'php_unit_test_annotation' => ['style' => 'prefix'],
|
||||
'php_unit_test_case_static_method_calls' => [
|
||||
'call_type' => 'self',
|
||||
'methods' => [],
|
||||
],
|
||||
'php_unit_test_class_requires_covers' => false,
|
||||
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
|
||||
'phpdoc_align' => [
|
||||
'align' => 'vertical',
|
||||
'tags' => [
|
||||
'method',
|
||||
'param',
|
||||
'property',
|
||||
'return',
|
||||
'throws',
|
||||
'type',
|
||||
'var',
|
||||
],
|
||||
],
|
||||
'phpdoc_annotation_without_dot' => true,
|
||||
'phpdoc_indent' => true,
|
||||
'phpdoc_inline_tag_normalizer' => [
|
||||
'tags' => [
|
||||
'example',
|
||||
'id',
|
||||
'internal',
|
||||
'inheritdoc',
|
||||
'inheritdocs',
|
||||
'link',
|
||||
'source',
|
||||
'toc',
|
||||
'tutorial',
|
||||
],
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'const' => 'multi',
|
||||
'method' => 'multi',
|
||||
'property' => 'multi',
|
||||
],
|
||||
'phpdoc_no_access' => true,
|
||||
'phpdoc_no_alias_tag' => [
|
||||
'replacements' => [
|
||||
'property-read' => 'property',
|
||||
'property-write' => 'property',
|
||||
'type' => 'var',
|
||||
'link' => 'see',
|
||||
],
|
||||
],
|
||||
'phpdoc_no_empty_return' => false,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_no_useless_inheritdoc' => true,
|
||||
'phpdoc_order' => ['order' => ['param', 'return', 'throws']],
|
||||
'phpdoc_order_by_value' => [
|
||||
'annotations' => [
|
||||
'author',
|
||||
'covers',
|
||||
'coversNothing',
|
||||
'dataProvider',
|
||||
'depends',
|
||||
'group',
|
||||
'internal',
|
||||
'method',
|
||||
'property',
|
||||
'property-read',
|
||||
'property-write',
|
||||
'requires',
|
||||
'throws',
|
||||
'uses',
|
||||
],
|
||||
],
|
||||
'phpdoc_return_self_reference' => [
|
||||
'replacements' => [
|
||||
'this' => '$this',
|
||||
'@this' => '$this',
|
||||
'$self' => 'self',
|
||||
'@self' => 'self',
|
||||
'$static' => 'static',
|
||||
'@static' => 'static',
|
||||
],
|
||||
],
|
||||
'phpdoc_scalar' => [
|
||||
'types' => [
|
||||
'boolean',
|
||||
'callback',
|
||||
'double',
|
||||
'integer',
|
||||
'real',
|
||||
'str',
|
||||
],
|
||||
],
|
||||
'phpdoc_separation' => [
|
||||
'groups' => [
|
||||
['deprecated', 'link', 'see', 'since'],
|
||||
['author', 'copyright', 'license'],
|
||||
['category', 'package', 'subpackage'],
|
||||
['property', 'property-read', 'property-write'],
|
||||
],
|
||||
],
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_summary' => true,
|
||||
'phpdoc_tag_casing' => ['tags' => ['inheritDoc']],
|
||||
'phpdoc_tag_type' => ['tags' => ['inheritDoc' => 'inline']],
|
||||
'phpdoc_to_comment' => ['ignored_tags' => [
|
||||
'phpstan-var',
|
||||
'phpstan-return',
|
||||
]],
|
||||
'phpdoc_to_param_type' => ['scalar_types' => true],
|
||||
'phpdoc_to_property_type' => ['scalar_types' => true],
|
||||
'phpdoc_to_return_type' => ['scalar_types' => true],
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||
'phpdoc_types' => ['groups' => ['simple', 'alias', 'meta']],
|
||||
'phpdoc_types_order' => [
|
||||
'null_adjustment' => 'always_first',
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'phpdoc_var_annotation_correct_order' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'pow_to_exponentiation' => true,
|
||||
'protected_to_private' => true,
|
||||
'psr_autoloading' => ['dir' => null],
|
||||
'random_api_migration' => [
|
||||
'replacements' => [
|
||||
'getrandmax' => 'mt_getrandmax',
|
||||
'rand' => 'mt_rand',
|
||||
'srand' => 'mt_srand',
|
||||
],
|
||||
],
|
||||
'regular_callable_call' => true,
|
||||
'return_assignment' => true,
|
||||
'return_type_declaration' => ['space_before' => 'none'],
|
||||
'self_accessor' => true,
|
||||
'self_static_accessor' => true,
|
||||
'semicolon_after_instruction' => true,
|
||||
'set_type_to_cast' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'simple_to_complex_string_variable' => true,
|
||||
'simplified_if_return' => true,
|
||||
'simplified_null_return' => false,
|
||||
'single_blank_line_at_eof' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'single_class_element_per_statement' => ['elements' => ['const', 'property']],
|
||||
'single_import_per_statement' => ['group_to_single_imports' => true],
|
||||
'single_line_after_imports' => true,
|
||||
'single_line_comment_spacing' => true,
|
||||
'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']],
|
||||
'single_line_throw' => false,
|
||||
'single_quote' => ['strings_containing_single_quote_chars' => false],
|
||||
'single_space_after_construct' => [
|
||||
'constructs' => [
|
||||
'abstract',
|
||||
'as',
|
||||
'attribute',
|
||||
'break',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'clone',
|
||||
'comment',
|
||||
'const',
|
||||
'const_import',
|
||||
'continue',
|
||||
'do',
|
||||
'echo',
|
||||
'else',
|
||||
'elseif',
|
||||
'extends',
|
||||
'final',
|
||||
'finally',
|
||||
'for',
|
||||
'foreach',
|
||||
'function',
|
||||
'function_import',
|
||||
'global',
|
||||
'goto',
|
||||
'if',
|
||||
'implements',
|
||||
'include',
|
||||
'include_once',
|
||||
'instanceof',
|
||||
'insteadof',
|
||||
'interface',
|
||||
'match',
|
||||
'named_argument',
|
||||
'new',
|
||||
'open_tag_with_echo',
|
||||
'php_doc',
|
||||
'php_open',
|
||||
'print',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'require',
|
||||
'require_once',
|
||||
'return',
|
||||
'static',
|
||||
'throw',
|
||||
'trait',
|
||||
'try',
|
||||
'use',
|
||||
'use_lambda',
|
||||
'use_trait',
|
||||
'var',
|
||||
'while',
|
||||
'yield',
|
||||
'yield_from',
|
||||
],
|
||||
],
|
||||
'single_trait_insert_per_statement' => true,
|
||||
'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
|
||||
'standardize_increment' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'statement_indentation' => true,
|
||||
'static_lambda' => true,
|
||||
'strict_comparison' => true,
|
||||
'strict_param' => true,
|
||||
'string_length_to_empty' => true,
|
||||
'string_line_ending' => true,
|
||||
'switch_case_semicolon_to_colon' => true,
|
||||
'switch_case_space' => true,
|
||||
'switch_continue_to_break' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'ternary_to_elvis_operator' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'trailing_comma_in_multiline' => [
|
||||
'after_heredoc' => true,
|
||||
'elements' => ['arrays', 'arguments', 'parameters'],
|
||||
],
|
||||
'trim_array_spaces' => true,
|
||||
'types_spaces' => ['space' => 'none', 'space_multiple_catch' => null],
|
||||
'unary_operator_spaces' => true,
|
||||
'use_arrow_functions' => true,
|
||||
'visibility_required' => ['elements' => ['const', 'method', 'property']],
|
||||
'void_return' => true,
|
||||
'whitespace_after_comma_in_array' => ['ensure_single_space' => true],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => true,
|
||||
'equal' => true,
|
||||
'identical' => true,
|
||||
'less_and_greater' => null,
|
||||
],
|
||||
];
|
||||
$this->requiredPHPVersion = 80000;
|
||||
$this->autoActivateIsRiskyAllowed = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Ruleset;
|
||||
|
||||
interface RulesetInterface
|
||||
{
|
||||
/**
|
||||
* Name of this ruleset.
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* Defined rules for this ruleset.
|
||||
*/
|
||||
public function getRules(): array;
|
||||
|
||||
/**
|
||||
* Returns the minimum `PHP_VERSION_ID`
|
||||
* that is required by this ruleset.
|
||||
*/
|
||||
public function getRequiredPHPVersion(): int;
|
||||
|
||||
/**
|
||||
* Does this ruleset have risky rules?
|
||||
*
|
||||
* If yes and `PhpCsFixer\Config` has the `$isRiskyAllowed`
|
||||
* flag set to `false`, those risky rules won't be run.
|
||||
*
|
||||
* Set this flag to `true` to automatically setup
|
||||
* the `$isRiskyAllowed` flag.
|
||||
*/
|
||||
public function willAutoActivateIsRiskyAllowed(): bool;
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Test;
|
||||
|
||||
use Nexus\CsConfig\Fixer\AbstractCustomFixer;
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
|
||||
use PhpCsFixer\Fixer\DeprecatedFixerInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerOptionInterface;
|
||||
use PhpCsFixer\FixerDefinition\CodeSampleInterface;
|
||||
use PhpCsFixer\FixerDefinition\FileSpecificCodeSampleInterface;
|
||||
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSampleInterface;
|
||||
use PhpCsFixer\FixerNameValidator;
|
||||
use PhpCsFixer\Linter\CachingLinter;
|
||||
use PhpCsFixer\Linter\LinterInterface;
|
||||
use PhpCsFixer\Linter\ProcessLinter;
|
||||
use PhpCsFixer\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Used for testing the fixers.
|
||||
*
|
||||
* Most of the tests here are directly from `PhpCsFixer\Tests\Test\AbstractFixerTestCase`
|
||||
* with some modifications and additions, since the test case is not shipped to production.
|
||||
*
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
* @author John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*/
|
||||
abstract class AbstractCustomFixerTestCase extends TestCase
|
||||
{
|
||||
protected AbstractCustomFixer $fixer;
|
||||
protected LinterInterface $linter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->fixer = $this->createFixer();
|
||||
$this->linter = $this->getLinter();
|
||||
}
|
||||
|
||||
private static function assertTokens(Tokens $expectedTokens, Tokens $inputTokens): void
|
||||
{
|
||||
self::assertSame($expectedTokens->count(), $inputTokens->count(), 'Both Tokens collections should have the same size.');
|
||||
|
||||
/** @var Token $expectedToken */
|
||||
foreach ($expectedTokens as $index => $expectedToken) {
|
||||
/** @var Token $inputToken */
|
||||
$inputToken = $inputTokens[$index];
|
||||
|
||||
self::assertTrue(
|
||||
$expectedToken->equals($inputToken),
|
||||
sprintf("Token at index %d must be:\n%s,\ngot:\n%s.", $index, $expectedToken->toJson(), $inputToken->toJson()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static function assertValidDescription(string $fixerName, string $descriptionType, string $description): void
|
||||
{
|
||||
self::assertMatchesRegularExpression('/^[A-Z`][^"]+\.$/', $description, sprintf('[%s] The %s must start with capital letter or a ` and end with dot.', $fixerName, $descriptionType));
|
||||
self::assertStringNotContainsString('phpdocs', $description, sprintf('[%s] `PHPDoc` must not be in the plural in %s.', $fixerName, $descriptionType));
|
||||
self::assertCorrectCasing($description, 'PHPDoc', sprintf('[%s] `PHPDoc` must be in correct casing in %s.', $fixerName, $descriptionType));
|
||||
self::assertCorrectCasing($description, 'PHPUnit', sprintf('[%s] `PHPUnit` must be in correct casing in %s.', $fixerName, $descriptionType));
|
||||
self::assertFalse(strpos($descriptionType, '``'), sprintf('[%s] The %s must not contain sequential backticks.', $fixerName, $descriptionType));
|
||||
}
|
||||
|
||||
private static function assertCorrectCasing(string $needle, string $haystack, string $message): void
|
||||
{
|
||||
self::assertSame(substr_count(strtolower($haystack), strtolower($needle)), substr_count($haystack, $needle), $message);
|
||||
}
|
||||
|
||||
final public function testIsRisky(): void
|
||||
{
|
||||
$riskyDescription = $this->fixer->getDefinition()->getRiskyDescription();
|
||||
|
||||
if ($this->fixer->isRisky()) {
|
||||
self::assertIsString($riskyDescription);
|
||||
self::assertValidDescription($this->fixer->getName(), 'risky description', (string) $riskyDescription);
|
||||
} else {
|
||||
self::assertNull($riskyDescription, sprintf('[%s] Fixer is not risky so no description of it is expected.', $this->fixer->getName()));
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionMethod($this->fixer, 'isRisky');
|
||||
|
||||
self::assertSame(
|
||||
! $this->fixer->isRisky(),
|
||||
$reflection->getDeclaringClass()->getName() === AbstractFixer::class,
|
||||
sprintf(
|
||||
'[%s] Fixer is %s so the method "AbstractFixer::isRisky()" must be %s.',
|
||||
$this->fixer->getName(),
|
||||
$this->fixer->isRisky() ? 'risky' : 'not risky',
|
||||
$this->fixer->isRisky() ? 'overridden' : 'used',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final public function testNameIsValid(): void
|
||||
{
|
||||
$nameValidator = new FixerNameValidator();
|
||||
$customFixerName = $this->fixer->getName();
|
||||
|
||||
self::assertTrue(
|
||||
$nameValidator->isValid($customFixerName, true),
|
||||
sprintf('Fixer name "%s" is not valid.', $customFixerName),
|
||||
);
|
||||
}
|
||||
|
||||
final public function testFixerIsFinal(): void
|
||||
{
|
||||
self::assertTrue(
|
||||
(new \ReflectionClass($this->fixer))->isFinal(),
|
||||
sprintf('Fixer "%s" must be declared "final".', $this->fixer->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
final public function testDeprecatedFixersHaveCorrectSummary(): void
|
||||
{
|
||||
self::assertStringNotContainsString(
|
||||
'DEPRECATED',
|
||||
$this->fixer->getDefinition()->getSummary(),
|
||||
'Fixer cannot contain word "DEPRECATED" in summary',
|
||||
);
|
||||
|
||||
$comment = (new \ReflectionClass($this->fixer))->getDocComment();
|
||||
self::assertIsString($comment, sprintf('[%s] Fixer is missing a class-level PHPDoc.', $this->fixer->getName()));
|
||||
$comment = (string) $comment;
|
||||
|
||||
if ($this->fixer instanceof DeprecatedFixerInterface) {
|
||||
self::assertStringContainsString('@deprecated', $comment);
|
||||
} else {
|
||||
self::assertStringNotContainsString('@deprecated', $comment);
|
||||
}
|
||||
}
|
||||
|
||||
final public function testFixerConfigurationDefinitions(): void
|
||||
{
|
||||
if (! $this->fixer instanceof ConfigurableFixerInterface) {
|
||||
$this->addToAssertionCount(1); // not applied to the fixer without configuration
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$configurationDefinition = $this->fixer->getConfigurationDefinition();
|
||||
|
||||
self::assertInstanceOf(FixerConfigurationResolverInterface::class, $configurationDefinition);
|
||||
|
||||
foreach ($configurationDefinition->getOptions() as $option) {
|
||||
self::assertInstanceOf(FixerOptionInterface::class, $option);
|
||||
self::assertNotEmpty($option->getDescription());
|
||||
|
||||
self::assertTrue(
|
||||
$option->hasDefault(),
|
||||
sprintf(
|
||||
'Option `%s` of fixer `%s` should have a default value.',
|
||||
$option->getName(),
|
||||
$this->fixer->getName(),
|
||||
),
|
||||
);
|
||||
|
||||
self::assertStringNotContainsString(
|
||||
'DEPRECATED',
|
||||
$option->getDescription(),
|
||||
'Option description cannot contain word "DEPRECATED"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final public function testFixerDefinitions(): void
|
||||
{
|
||||
$fixerName = $this->fixer->getName();
|
||||
$definition = $this->fixer->getDefinition();
|
||||
$fixerIsConfigurable = $this->fixer instanceof ConfigurableFixerInterface;
|
||||
|
||||
self::assertValidDescription($fixerName, 'summary', $definition->getSummary());
|
||||
|
||||
$samples = $definition->getCodeSamples();
|
||||
self::assertNotEmpty($samples, sprintf('[%s] Code samples are required.', $fixerName));
|
||||
|
||||
$configSamplesProvided = [];
|
||||
$dummyFileInfo = new \SplFileInfo(__FILE__);
|
||||
|
||||
foreach ($samples as $counter => $sample) {
|
||||
self::assertIsInt($counter);
|
||||
|
||||
++$counter;
|
||||
self::assertInstanceOf(CodeSampleInterface::class, $sample, sprintf('[%s] Sample #%d must be an instance of "%s".', $fixerName, $counter, CodeSampleInterface::class));
|
||||
|
||||
$code = $sample->getCode();
|
||||
self::assertNotEmpty($code, sprintf('[%s] Code provided by sample #%d must not be empty.', $fixerName, $counter));
|
||||
self::assertSame("\n", substr($code, -1), sprintf('[%s] Sample #%d must end with linebreak', $fixerName, $counter));
|
||||
|
||||
$config = $sample->getConfiguration();
|
||||
|
||||
if (null !== $config) {
|
||||
self::assertTrue($fixerIsConfigurable, sprintf('[%s] Sample #%d has configuration, but the fixer is not configurable.', $fixerName, $counter));
|
||||
self::assertIsArray($config, sprintf('[%s] Sample #%d configuration must be an array or null.', $fixerName, $counter));
|
||||
|
||||
$configSamplesProvided[$counter] = $config;
|
||||
} elseif ($fixerIsConfigurable) {
|
||||
if (! $sample instanceof VersionSpecificCodeSampleInterface) {
|
||||
self::assertArrayNotHasKey('default', $configSamplesProvided, sprintf('[%s] Multiple non-versioned samples with default configuration.', $fixerName));
|
||||
}
|
||||
|
||||
$configSamplesProvided['default'] = true;
|
||||
}
|
||||
|
||||
if ($sample instanceof VersionSpecificCodeSampleInterface && ! $sample->isSuitableFor(\PHP_VERSION_ID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fixerIsConfigurable) {
|
||||
// always re-configure as the fixer might have been configured with diff. configuration from previous sample
|
||||
$this->fixer->configure(null === $config ? [] : $config);
|
||||
}
|
||||
|
||||
Tokens::clearCache();
|
||||
$tokens = Tokens::fromCode($code);
|
||||
|
||||
$this->fixer->fix(
|
||||
$sample instanceof FileSpecificCodeSampleInterface ? $sample->getSplFileInfo() : $dummyFileInfo,
|
||||
$tokens,
|
||||
);
|
||||
|
||||
self::assertTrue($tokens->isChanged(), sprintf('[%s] Sample #%d is not changed during fixing.', $fixerName, $counter));
|
||||
|
||||
$duplicatedCodeSample = array_search(
|
||||
$sample,
|
||||
\array_slice($samples, 0, $counter - 1),
|
||||
false,
|
||||
);
|
||||
|
||||
self::assertFalse(
|
||||
$duplicatedCodeSample,
|
||||
sprintf('[%s] Sample #%d duplicates #%d.', $fixerName, $counter, ++$duplicatedCodeSample),
|
||||
);
|
||||
}
|
||||
|
||||
if ($fixerIsConfigurable) {
|
||||
if (isset($configSamplesProvided['default'])) {
|
||||
reset($configSamplesProvided);
|
||||
self::assertSame('default', key($configSamplesProvided), sprintf('[%s] First sample must be for the default configuration.', $fixerName));
|
||||
}
|
||||
|
||||
if (\count($configSamplesProvided) < 2) {
|
||||
self::fail(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options.', $fixerName));
|
||||
}
|
||||
|
||||
$options = $this->fixer->getConfigurationDefinition()->getOptions();
|
||||
|
||||
foreach ($options as $option) {
|
||||
self::assertMatchesRegularExpression('/^[a-z_]+[a-z]$/', $option->getName(), sprintf('[%s] Option %s is not snake_case.', $fixerName, $option->getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a fixer fixes a given string to match the expected result.
|
||||
*
|
||||
* It is used both if you want to test if something is fixed or if it is not touched by the fixer.
|
||||
*
|
||||
* It also makes sure that the expected output does not change when run through the fixer. That means that you
|
||||
* do not need two test cases like [$expected] and [$expected, $input] (where $expected is the same in both cases)
|
||||
* as the latter covers both of them.
|
||||
*
|
||||
* This method throws an exception if $expected and $input are equal to prevent test cases that accidentally do
|
||||
* not test anything.
|
||||
*
|
||||
* @param string $expected The expected fixer output
|
||||
* @param null|string $input The fixer input, or null if it should intentionally be equal to the output
|
||||
*/
|
||||
protected function doTest(string $expected, ?string $input = null): void
|
||||
{
|
||||
if ($expected === $input) {
|
||||
throw new \LogicException('Input parameter must not be equal to expected parameter.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$file = new \SplFileInfo(__FILE__);
|
||||
|
||||
if (null !== $input) {
|
||||
self::assertNull($this->lintSource($input));
|
||||
|
||||
Tokens::clearCache();
|
||||
$tokens = Tokens::fromCode($input);
|
||||
|
||||
self::assertTrue($this->fixer->isCandidate($tokens), 'Fixer must be a candidate for input code.');
|
||||
self::assertFalse($tokens->isChanged(), 'Fixer must not touch Tokens on candidate check.');
|
||||
$this->fixer->fix($file, $tokens);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$tokens->generateCode(),
|
||||
'Code build on input code must match expected code.',
|
||||
);
|
||||
self::assertTrue($tokens->isChanged(), 'Tokens collection built on input code must be marked as changed after fixing.');
|
||||
|
||||
$tokens->clearEmptyTokens();
|
||||
|
||||
/** @var Token[] $tokensArray */
|
||||
$tokensArray = $tokens->toArray();
|
||||
|
||||
self::assertSame(
|
||||
\count($tokens),
|
||||
\count(array_unique(array_map(static fn (Token $token): string => spl_object_hash($token), $tokensArray))),
|
||||
'Token items inside Tokens collection must be unique.',
|
||||
);
|
||||
|
||||
unset($tokensArray);
|
||||
Tokens::clearCache();
|
||||
$expectedTokens = Tokens::fromCode($expected);
|
||||
self::assertTokens($expectedTokens, $tokens);
|
||||
}
|
||||
|
||||
self::assertNull($this->lintSource($expected));
|
||||
|
||||
Tokens::clearCache();
|
||||
$tokens = Tokens::fromCode($expected);
|
||||
$this->fixer->fix($file, $tokens);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$tokens->generateCode(),
|
||||
'Code build on expected code must not change.',
|
||||
);
|
||||
self::assertFalse($tokens->isChanged(), 'Tokens collection built on expected code must not be marked as changed after fixing.');
|
||||
}
|
||||
|
||||
protected function createFixer(): AbstractCustomFixer
|
||||
{
|
||||
/** @phpstan-var class-string<AbstractCustomFixer> $customFixer */
|
||||
$customFixer = Preg::replace('/^(Nexus\\\\CsConfig)\\\\Tests(\\\\.+)Test$/', '$1$2', static::class);
|
||||
|
||||
return new $customFixer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function lintSource(string $source): ?string
|
||||
{
|
||||
try {
|
||||
$this->linter->lintSource($source)->check();
|
||||
|
||||
return null;
|
||||
} catch (\Throwable $e) {
|
||||
return sprintf('Linting "%s" failed with message: %s.', $source, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function getLinter(): LinterInterface
|
||||
{
|
||||
static $linter = null;
|
||||
|
||||
if (null === $linter) {
|
||||
$linter = new CachingLinter(new ProcessLinter());
|
||||
}
|
||||
|
||||
return $linter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Test;
|
||||
|
||||
use Nexus\CsConfig\Ruleset\RulesetInterface;
|
||||
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
|
||||
use PhpCsFixer\Fixer\FixerInterface;
|
||||
use PhpCsFixer\FixerConfiguration\DeprecatedFixerOptionInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerOptionInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Used for testing the rulesets.
|
||||
*/
|
||||
abstract class AbstractRulesetTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var array<string, FixerInterface>
|
||||
*/
|
||||
private static array $builtInFixers = [];
|
||||
|
||||
/**
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private static array $configuredFixers = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool|string|string[]>|bool>
|
||||
*/
|
||||
private static array $enabledFixers = [];
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$fixerProvider = FixerProvider::create(static::createRuleset());
|
||||
self::$builtInFixers = $fixerProvider->builtin();
|
||||
self::$configuredFixers = $fixerProvider->configured();
|
||||
self::$enabledFixers = $fixerProvider->enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
FixerProvider::reset();
|
||||
self::$builtInFixers = [];
|
||||
self::$configuredFixers = [];
|
||||
self::$enabledFixers = [];
|
||||
}
|
||||
|
||||
protected static function createRuleset(): RulesetInterface
|
||||
{
|
||||
/** @phpstan-var class-string<RulesetInterface> $className */
|
||||
$className = Preg::replace('/^(Nexus\\\\CsConfig)\\\\Tests(\\\\.+)Test$/', '$1$2', static::class);
|
||||
|
||||
return new $className();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// TESTS
|
||||
// =========================================================================
|
||||
|
||||
final public function testAllConfiguredFixersAreNotUsingPresets(): void
|
||||
{
|
||||
$fixersThatArePresets = array_filter(
|
||||
self::$enabledFixers,
|
||||
static fn (string $fixer): bool => substr($fixer, 0, 1) === '@',
|
||||
ARRAY_FILTER_USE_KEY,
|
||||
);
|
||||
|
||||
self::assertEmpty($fixersThatArePresets, sprintf(
|
||||
'[%s] Ruleset should not be using rule sets (presets) as fixers. Found: "%s".',
|
||||
static::createRuleset()->getName(),
|
||||
implode('", "', array_keys($fixersThatArePresets)),
|
||||
));
|
||||
}
|
||||
|
||||
final public function testAllBuiltInFixersNotDeprecatedAreConfiguredInThisRuleset(): void
|
||||
{
|
||||
$fixersNotConfigured = array_diff(array_keys(self::$builtInFixers), self::$configuredFixers);
|
||||
|
||||
sort($fixersNotConfigured);
|
||||
$c = \count($fixersNotConfigured);
|
||||
|
||||
self::assertEmpty($fixersNotConfigured, sprintf(
|
||||
'[%s] Non-deprecated built-in %s "%s" %s not configured in the ruleset.',
|
||||
static::createRuleset()->getName(),
|
||||
$c > 1 ? 'fixers' : 'fixer',
|
||||
implode('", "', $fixersNotConfigured),
|
||||
$c > 1 ? 'are' : 'is',
|
||||
));
|
||||
}
|
||||
|
||||
final public function testAllConfiguredFixersInThisRulesetAreBuiltInAndNotDeprecated(): void
|
||||
{
|
||||
$fixersNotBuiltIn = array_diff(self::$configuredFixers, array_keys(self::$builtInFixers));
|
||||
|
||||
sort($fixersNotBuiltIn);
|
||||
$c = \count($fixersNotBuiltIn);
|
||||
|
||||
self::assertEmpty($fixersNotBuiltIn, sprintf(
|
||||
'[%s] Ruleset used %s "%s" which %s unknown and/or deprecated in PhpCsFixer.',
|
||||
static::createRuleset()->getName(),
|
||||
$c > 1 ? 'fixers' : 'fixer',
|
||||
implode('", "', $fixersNotBuiltIn),
|
||||
$c > 1 ? 'are' : 'is',
|
||||
));
|
||||
}
|
||||
|
||||
final public function testAllConfiguredFixersInThisRulesetAreSortedByName(): void
|
||||
{
|
||||
$fixers = self::$configuredFixers;
|
||||
$sorted = $fixers;
|
||||
sort($sorted);
|
||||
|
||||
self::assertSame($sorted, $fixers, sprintf(
|
||||
'[%s] Fixers are not sorted by name.',
|
||||
static::createRuleset()->getName(),
|
||||
));
|
||||
}
|
||||
|
||||
final public function testHeaderCommentFixerIsDisabledByDefault(): void
|
||||
{
|
||||
self::assertArrayHasKey('header_comment', self::$enabledFixers);
|
||||
self::assertFalse(self::$enabledFixers['header_comment']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function provideConfigurableFixersCases(): iterable
|
||||
{
|
||||
$fixers = FixerProvider::create(static::createRuleset())->builtin();
|
||||
ksort($fixers);
|
||||
|
||||
foreach ($fixers as $name => $fixer) {
|
||||
if ($fixer instanceof ConfigurableFixerInterface) {
|
||||
$options = $fixer->getConfigurationDefinition()->getOptions();
|
||||
|
||||
$goodOptions = array_map(
|
||||
static fn (FixerOptionInterface $option): string => $option->getName(),
|
||||
array_filter(
|
||||
$options,
|
||||
static fn (FixerOptionInterface $option): bool => ! $option instanceof DeprecatedFixerOptionInterface,
|
||||
),
|
||||
);
|
||||
|
||||
$deprecatedOptions = array_map(
|
||||
static fn (FixerOptionInterface $option): string => $option->getName(),
|
||||
array_filter(
|
||||
$options,
|
||||
static fn (FixerOptionInterface $option): bool => $option instanceof DeprecatedFixerOptionInterface,
|
||||
),
|
||||
);
|
||||
|
||||
yield $name => [$name, $goodOptions, $deprecatedOptions];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideConfigurableFixersCases
|
||||
*/
|
||||
final public function testEnabledConfigurableFixerUsesAllAvailableOptionsNotDeprecated(string $name, array $goodOptions, array $deprecatedOptions): void
|
||||
{
|
||||
/** @var null|array<string, bool|string|string[]>|bool $ruleConfiguration */
|
||||
$ruleConfiguration = self::$enabledFixers[$name] ?? null;
|
||||
|
||||
if (null === $ruleConfiguration) {
|
||||
self::markTestSkipped(sprintf('`%s` is not yet defined in this ruleset.', $name)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if (false === $ruleConfiguration) {
|
||||
// fixer is turned off
|
||||
$this->addToAssertionCount(1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ruleConfiguration = \is_array($ruleConfiguration) ? $ruleConfiguration : [];
|
||||
$ruleConfiguration = array_keys($ruleConfiguration);
|
||||
|
||||
$missingOptions = array_diff($goodOptions, $ruleConfiguration);
|
||||
$usedDeprecatedOptions = array_intersect($deprecatedOptions, $ruleConfiguration);
|
||||
$extraUsedOptions = array_diff($ruleConfiguration, $goodOptions);
|
||||
|
||||
self::assertEmpty($missingOptions, sprintf(
|
||||
'Enabled configurable fixer "%s" does not use its available array %s "%s". Missing %s: "%s".',
|
||||
$name,
|
||||
\count($goodOptions) > 1 ? 'options' : 'option',
|
||||
implode('", "', $goodOptions),
|
||||
\count($missingOptions) > 1 ? 'options' : 'option',
|
||||
implode('", "', $missingOptions),
|
||||
));
|
||||
self::assertEmpty($usedDeprecatedOptions, sprintf(
|
||||
'Enabled configurable fixer "%s" uses deprecated %s: "%s".',
|
||||
$name,
|
||||
\count($usedDeprecatedOptions) > 1 ? 'options' : 'option',
|
||||
implode('", "', $usedDeprecatedOptions),
|
||||
));
|
||||
self::assertEmpty($extraUsedOptions, sprintf(
|
||||
'%s "%s" for enabled configurable fixer "%s" %s not defined by PhpCsFixer.',
|
||||
\count($extraUsedOptions) > 1 ? 'Options' : 'Option',
|
||||
implode('", "', $extraUsedOptions),
|
||||
$name,
|
||||
\count($extraUsedOptions) > 1 ? 'are' : 'is',
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Nexus CS Config.
|
||||
*
|
||||
* (c) 2020 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nexus\CsConfig\Test;
|
||||
|
||||
use Nexus\CsConfig\Ruleset\RulesetInterface;
|
||||
use PhpCsFixer\Fixer\DeprecatedFixerInterface;
|
||||
use PhpCsFixer\Fixer\FixerInterface;
|
||||
use PhpCsFixer\FixerFactory;
|
||||
use PhpCsFixer\RuleSet\RuleSet;
|
||||
|
||||
final class FixerProvider
|
||||
{
|
||||
/**
|
||||
* Built-in fixers from php-cs-fixer.
|
||||
*
|
||||
* @var array<string, FixerInterface>
|
||||
*/
|
||||
private static array $builtIn = [];
|
||||
|
||||
/**
|
||||
* Configured fixers from a ruleset.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $configured = [];
|
||||
|
||||
/**
|
||||
* Enabled fixers from a ruleset.
|
||||
*
|
||||
* @var array<string, array<string, bool|string|string[]>|bool>
|
||||
*/
|
||||
private array $enabled = [];
|
||||
|
||||
/**
|
||||
* @param array<int, string> $configured
|
||||
* @param array<string, array<string, bool|string|string[]>|bool> $enabled
|
||||
*/
|
||||
private function __construct(array $configured, array $enabled)
|
||||
{
|
||||
$this->configured = $configured;
|
||||
$this->enabled = $enabled;
|
||||
}
|
||||
|
||||
public static function create(RulesetInterface $ruleset): self
|
||||
{
|
||||
if ([] === self::$builtIn) {
|
||||
$fixers = array_filter(
|
||||
(new FixerFactory())->registerBuiltInFixers()->getFixers(),
|
||||
static fn (FixerInterface $fixer): bool => ! $fixer instanceof DeprecatedFixerInterface,
|
||||
);
|
||||
|
||||
foreach ($fixers as $fixer) {
|
||||
// workaround for using `array_combine` with PHPStan on PHP < 80000
|
||||
self::$builtIn[$fixer->getName()] = $fixer;
|
||||
}
|
||||
}
|
||||
|
||||
$rules = $ruleset->getRules();
|
||||
|
||||
$configured = array_map(static function ($ruleConfiguration): bool {
|
||||
// force enable all rules
|
||||
return true;
|
||||
}, $rules);
|
||||
|
||||
return new self(array_keys((new RuleSet($configured))->getRules()), $rules);
|
||||
}
|
||||
|
||||
public static function reset(): void
|
||||
{
|
||||
self::$builtIn = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names and instances of built-in fixers.
|
||||
*
|
||||
* @return array<string, FixerInterface>
|
||||
*/
|
||||
public function builtin(): array
|
||||
{
|
||||
return self::$builtIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the configured fixers.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function configured(): array
|
||||
{
|
||||
return $this->configured;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enabled rules from a ruleset and
|
||||
* their configuration.
|
||||
*
|
||||
* @return array<string, array<string, bool|string|string[]>|bool>
|
||||
*/
|
||||
public function enabled(): array
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user