first commit

This commit is contained in:
DESKTOP-DH6BVPV\chiefsoft
2022-11-15 21:53:02 -05:00
commit 29452e5b6e
1991 changed files with 265605 additions and 0 deletions
+203
View File
@@ -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]]);
}
}
}
+91
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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',
));
}
}
+114
View File
@@ -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;
}
}