diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7751119 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +.idea/ \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..f1fa49b --- /dev/null +++ b/composer.json @@ -0,0 +1,18 @@ +{ + "name": "lubiana/code-quality", + "autoload": { + "psr-4": { + "Lubiana\\CodeQuality\\": "src/" + } + }, + "require-dev": { + "slevomat/coding-standard": "^8.5.2", + "symplify/easy-coding-standard": "^11.1.10", + "rector/rector": "^0.14.5" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..2ab8fac --- /dev/null +++ b/composer.lock @@ -0,0 +1,428 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "c93722fb34d77a79c19b807c9cbc8230", + "packages": [], + "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.7.2", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, + "time": "2022-02-04T12:51:07+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "8dd908dd6156e974b9a0f8bb4cd5ad0707830f04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8dd908dd6156e974b9a0f8bb4cd5ad0707830f04", + "reference": "8dd908dd6156e974b9a0f8bb4cd5ad0707830f04", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.8.0" + }, + "time": "2022-09-04T18:59:06+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.8.8", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "08310ce271984587e2a4cda94e1ac66510a6ea07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/08310ce271984587e2a4cda94e1ac66510a6ea07", + "reference": "08310ce271984587e2a4cda94e1ac66510a6ea07", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.8.8" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-10-06T12:51:57+00:00" + }, + { + "name": "rector/rector", + "version": "0.14.5", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/f7fd87b2435835f481e6a94ee28e09af412bd3cc", + "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.8.6" + }, + "conflict": { + "rector/rector-cakephp": "*", + "rector/rector-doctrine": "*", + "rector/rector-laravel": "*", + "rector/rector-php-parser": "*", + "rector/rector-phpoffice": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.14-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/0.14.5" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-09-29T11:05:42+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "8.5.2", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "f32937dc41b587f3500efed1dbca2f82aa519373" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/f32937dc41b587f3500efed1dbca2f82aa519373", + "reference": "f32937dc41b587f3500efed1dbca2f82aa519373", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": ">=1.7.0 <1.9.0", + "squizlabs/php_codesniffer": "^3.7.1" + }, + "require-dev": { + "phing/phing": "2.17.4", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.4.10|1.8.6", + "phpstan/phpstan-deprecation-rules": "1.0.0", + "phpstan/phpstan-phpunit": "1.0.0|1.1.1", + "phpstan/phpstan-strict-rules": "1.4.4", + "phpunit/phpunit": "7.5.20|8.5.21|9.5.25" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.5.2" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2022-09-27T16:45:37+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.1", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2022-06-18T07:21:10+00:00" + }, + { + "name": "symplify/easy-coding-standard", + "version": "11.1.10", + "source": { + "type": "git", + "url": "https://github.com/symplify/easy-coding-standard.git", + "reference": "dc1c9c50059de9b0f51029a9446537f80bbf0c4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/dc1c9c50059de9b0f51029a9446537f80bbf0c4e", + "reference": "dc1c9c50059de9b0f51029a9446537f80bbf0c4e", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "conflict": { + "friendsofphp/php-cs-fixer": "<3.0", + "squizlabs/php_codesniffer": "<3.6" + }, + "bin": [ + "bin/ecs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.3-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Prefixed scoped version of ECS package", + "support": { + "source": "https://github.com/symplify/easy-coding-standard/tree/11.1.10" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-09-29T10:40:41+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/config/ecs.php b/config/ecs.php new file mode 100644 index 0000000..76f1333 --- /dev/null +++ b/config/ecs.php @@ -0,0 +1,113 @@ +skip([ + BlankLineAfterOpeningTagFixer::class, + NewWithBracesFixer::class, + OrderedImportsFixer::class, + ]); + + $c->sets([ + SetList::ARRAY, + SetList::CLEAN_CODE, + SetList::COMMENTS, + SetList::COMMON, + SetList::CONTROL_STRUCTURES, + SetList::DOCBLOCK, + SetList::NAMESPACES, + SetList::PSR_12, + SetList::SPACES, + SetList::STRICT, + SetList::SYMPLIFY, + ]); + + // force visibility declaration on class constants + $c->ruleWithConfiguration(ClassConstantVisibilitySniff::class, [ + 'fixable' => true, + ]); + + // sort all use statements + $c->rules([ + AlphabeticallySortedUsesSniff::class, + DisallowGroupUseSniff::class, + MultipleUsesPerLineSniff::class, + NamespaceSpacingSniff::class, + ]); + + // import all namespaces, and event php core functions and classes + $c->ruleWithConfiguration( + ReferenceUsedNamesOnlySniff::class, + [ + 'allowFallbackGlobalConstants' => false, + 'allowFallbackGlobalFunctions' => false, + 'allowFullyQualifiedGlobalClasses' => false, + 'allowFullyQualifiedGlobalConstants' => false, + 'allowFullyQualifiedGlobalFunctions' => false, + 'allowFullyQualifiedNameForCollidingClasses' => true, + 'allowFullyQualifiedNameForCollidingConstants' => true, + 'allowFullyQualifiedNameForCollidingFunctions' => true, + 'searchAnnotations' => true, + ] + ); + + // define newlines between use statements + $c->ruleWithConfiguration(UseSpacingSniff::class, [ + 'linesCountAfterLastUse' => 1, + 'linesCountBeforeFirstUse' => 1, + 'linesCountBetweenUseTypes' => 1, + ]); + + // strict types declaration should be on same line as opening tag + $c->ruleWithConfiguration( + DeclareStrictTypesSniff::class, + [ + 'declareOnFirstLine' => true, + 'spacesCountAroundEqualsSign' => 0, + ] + ); + + // disallow ?Foo typehint in favor of Foo|null + $c->ruleWithConfiguration(UnionTypeHintFormatSniff::class, [ + 'nullPosition' => 'last', + 'shortNullable' => 'no', + 'withSpaces' => 'no', + ]); + + // Remove useless parentheses in new statements + $c->rule(BracesFixer::class); + $c->rule(NewWithoutParenthesesSniff::class); + + // do not inline short multilinestatements + $c->ruleWithConfiguration(LineLengthFixer::class, [ + LineLengthFixer::INLINE_SHORT_LINES => false, + ]); + + $c->ruleWithConfiguration( + NoExtraBlankLinesFixer::class, + [ + 'tokens' => ['square_brace_block', 'return', 'extra'], + ] + ); + + $c->rule(NoWhitespaceInBlankLineFixer::class); +}; diff --git a/config/rector.php b/config/rector.php new file mode 100644 index 0000000..f49f121 --- /dev/null +++ b/config/rector.php @@ -0,0 +1,90 @@ +sets([LevelSetList::UP_TO_PHP_81]); + $c->rules([ + AddArrayParamDocTypeRector::class, + AddArrayReturnDocTypeRector::class, + AddArrowFunctionReturnTypeRector::class, + AddClosureReturnTypeRector::class, + AddMethodCallBasedStrictParamTypeRector::class, + AddReturnTypeDeclarationBasedOnParentClassMethodRector::class, + BooleanNotIdenticalToNotIdenticalRector::class, + ChangeAndIfToEarlyReturnRector::class, + ChangeNestedForeachIfsToEarlyContinueRector::class, + ChangeNestedIfsToEarlyReturnRector::class, + ChangeOrIfContinueToMultiContinueRector::class, + ChangeOrIfReturnToEarlyReturnRector::class, + CountArrayToEmptyArrayComparisonRector::class, + ExplicitBoolCompareRector::class, + InlineArrayReturnAssignRector::class, + InlineIsAInstanceOfRector::class, + NewlineAfterStatementRector::class, + NewlineBeforeNewAssignSetRector::class, + NullableCompareToNullRector::class, + ParamTypeByMethodCallTypeRector::class, + ParamTypeByParentCallTypeRector::class, + ParamTypeFromStrictTypedPropertyRector::class, + PreparedValueToEarlyReturnRector::class, + ReplaceMultipleBooleanNotRector::class, + ReturnBinaryAndToEarlyReturnRector::class, + ReturnBinaryOrToEarlyReturnRector::class, + ReturnEarlyIfVariableRector::class, + ReturnTypeDeclarationRector::class, + ReturnTypeFromReturnNewRector::class, + ReturnTypeFromStrictBoolReturnExprRector::class, + ReturnTypeFromStrictNativeCallRector::class, + ReturnTypeFromStrictNewArrayRector::class, + ReturnTypeFromStrictTypedPropertyRector::class, + SimplifyConditionsRector::class, + SimplifyEmptyArrayCheckRector::class, + StaticArrowFunctionRector::class, + StaticClosureRector::class, + ThrowWithPreviousExceptionRector::class, + TypedPropertyFromStrictConstructorRector::class, + TypedPropertyFromStrictGetterMethodReturnTypeRector::class, + ]); +}; diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..45c8c6b --- /dev/null +++ b/ecs.php @@ -0,0 +1,15 @@ +paths([ + __DIR__ . '/src', + __DIR__ . '/config', + __DIR__ . '/rector.php', + __DIR__ . '/ecs.php', + ]); + + $c->sets([SetList::ECS]); +}; diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..7970267 --- /dev/null +++ b/rector.php @@ -0,0 +1,15 @@ +paths([ + __DIR__ . '/src', + __DIR__ . '/config', + __DIR__ . '/rector.php', + __DIR__ . '/ecs.php', + ]); + + $c->sets([SetList::RECTOR]); +}; diff --git a/src/SetList.php b/src/SetList.php new file mode 100644 index 0000000..53a1d6c --- /dev/null +++ b/src/SetList.php @@ -0,0 +1,10 @@ +