diff --git a/.gitignore b/.gitignore index 93c920b..d87973a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /.composer /.idea +/playground /vendor composer.lock diff --git a/composer.json b/composer.json index 4cab17a..fee1314 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,11 @@ "Blumilk\\Codestyle\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "Blumilk\\Codestyle\\Tests\\": "tests/codestyle/" + } + }, "scripts": { "cs": "./vendor/bin/php-cs-fixer fix --dry-run --diff --config codestyle.php", "csf": "./vendor/bin/php-cs-fixer fix --diff --config codestyle.php", diff --git a/src/Config.php b/src/Config.php index a61f32d..ba91ea8 100644 --- a/src/Config.php +++ b/src/Config.php @@ -8,7 +8,9 @@ use Blumilk\Codestyle\Configuration\Defaults\LaravelPaths; use Blumilk\Codestyle\Configuration\Paths; use Blumilk\Codestyle\Configuration\Rules; +use Blumilk\Codestyle\Configuration\Utils\Rule; use Blumilk\Codestyle\Fixers\DoubleQuoteFixer; +use Blumilk\Codestyle\Fixers\NoCommentFixer; use Blumilk\Codestyle\Fixers\NoLaravelMigrationsGeneratedCommentFixer; use JetBrains\PhpStorm\ArrayShape; use PhpCsFixer\Config as PhpCsFixerConfig; @@ -42,8 +44,8 @@ public function config(): PhpCsFixerConfig } $finder = Finder::create()->directories()->append($files); - $config = new PhpCsFixerConfig("Blumilk codestyle standard"); + return $config->setFinder($finder) ->setUsingCache(false) ->registerCustomFixers(new PhpCsFixerCustomFixers()) @@ -61,6 +63,13 @@ public function options(): array ]; } + public function purgeMode(): static + { + $this->rules->add(new Rule(NoCommentFixer::class)); + + return $this; + } + protected function getAllFiles(array &$paths, string $path): void { if (is_file($path) || !is_dir($path)) { @@ -83,6 +92,7 @@ protected function getCustomFixers(): array return [ new DoubleQuoteFixer(), new NoLaravelMigrationsGeneratedCommentFixer(), + new NoCommentFixer(), ]; } } diff --git a/src/Configuration/Utils/Rule.php b/src/Configuration/Utils/Rule.php index 7af0b53..b09cb51 100644 --- a/src/Configuration/Utils/Rule.php +++ b/src/Configuration/Utils/Rule.php @@ -6,6 +6,9 @@ class Rule { + /** + * @param class-string $fixer + */ public function __construct( protected string $fixer, protected ?array $options = null, diff --git a/src/Fixers/NoCommentFixer.php b/src/Fixers/NoCommentFixer.php new file mode 100644 index 0000000..f0a6362 --- /dev/null +++ b/src/Fixers/NoCommentFixer.php @@ -0,0 +1,80 @@ +string("id")->primary(); + $table->text("payload"); + }); + } +}; +EOF; + + return new FixerDefinition( + "There can be no comments.", + [ + new CodeSample($codeSample), + ], + ); + } + + public function getName(): string + { + return "Blumilk/no_comments"; + } + + public function getPriority(): int + { + $fixer = new NoExtraBlankLinesFixer(); + return $fixer->getPriority() + 1; + } + + public function supports(SplFileInfo $file): bool + { + return true; + } + + public function isCandidate(Tokens $tokens): bool + { + return $tokens->isAnyTokenKindsFound([T_COMMENT, T_DOC_COMMENT]); + } + + public function isRisky(): bool + { + return true; + } + + public function fix(SplFileInfo $file, Tokens $tokens): void + { + for ($index = $tokens->count() - 1; $index > 0; $index--) { + if (!$tokens[$index]->isGivenKind([T_COMMENT])) { + continue; + } + + TokenRemover::removeWithLinesIfPossible($tokens, $index); + } + } +} diff --git a/tests/codestyle/CodestyleTest.php b/tests/codestyle/CodestyleTestCase.php similarity index 50% rename from tests/codestyle/CodestyleTest.php rename to tests/codestyle/CodestyleTestCase.php index 5551b0e..bdfb905 100644 --- a/tests/codestyle/CodestyleTest.php +++ b/tests/codestyle/CodestyleTestCase.php @@ -2,12 +2,15 @@ declare(strict_types=1); +namespace Blumilk\Codestyle\Tests; + +use Exception; use PhpCsFixer\Console\Application; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\BufferedOutput; -class CodestyleTest extends TestCase +abstract class CodestyleTestCase extends TestCase { protected function setUp(): void { @@ -19,75 +22,6 @@ protected function tearDown(): void $this->clearTempDirectory(); } - /** - * @dataProvider providePhp80Fixtures - * @requires PHP >= 8.0 - * @throws Exception - */ - public function testPhp80Fixtures(string $name): void - { - $this->testFixture($name); - } - - /** - * @dataProvider providePhp81Fixtures - * @requires PHP >= 8.1 - * @throws Exception - */ - public function testPhp81Fixtures(string $name): void - { - $this->testFixture($name); - } - - /** - * @dataProvider providePhp82Fixtures - * @requires PHP >= 8.2 - * @throws Exception - */ - public function testPhp82Fixtures(string $name): void - { - $this->testFixture($name); - } - - public static function providePhp80Fixtures(): array - { - return [ - ["noExtraBlankLines"], - ["nullableTypeForDefaultNull"], - ["operatorSpacing"], - ["singleQuotes"], - ["strictTypes"], - ["trailingCommas"], - ["unionTypes"], - ["references"], - ["classAttributesSeparation"], - ["uselessParenthesis"], - ["laravelMigrations"], - ["phpdocs"], - ["yodaStyle"], - ["objectOperators"], - ["anonymousFunctions"], - ["namespaces"], - ["emptyLines"], - ["importsOrder"], - ]; - } - - public static function providePhp81Fixtures(): array - { - return [ - ["enums"], - ["readonlies"], - ]; - } - - public static function providePhp82Fixtures(): array - { - return [ - ["php82"], - ]; - } - /** * @dataProvider providePhp80Fixtures * @throws Exception @@ -124,7 +58,8 @@ protected function runFixer(bool $fix = false): bool $application->setAutoExit(false); $output = new BufferedOutput(); - $result = $application->run(new StringInput("fix {$dryRun} --diff --config ./tests/codestyle/config.php"), $output); + $config = $this->getConfigPath(); + $result = $application->run(new StringInput("fix {$dryRun} --diff --config $config"), $output); return $result === 0; } @@ -136,4 +71,9 @@ protected function clearTempDirectory(): void unlink($file); } } + + protected function getConfigPath(): string + { + return "./tests/codestyle/config/config.php"; + } } diff --git a/tests/codestyle/CommonRulesetTest.php b/tests/codestyle/CommonRulesetTest.php new file mode 100644 index 0000000..57defe5 --- /dev/null +++ b/tests/codestyle/CommonRulesetTest.php @@ -0,0 +1,76 @@ += 8.0 + * @throws Exception + */ + public function testPhp80Fixtures(string $name): void + { + $this->testFixture($name); + } + + /** + * @dataProvider providePhp81Fixtures + * @requires PHP >= 8.1 + * @throws Exception + */ + public function testPhp81Fixtures(string $name): void + { + $this->testFixture($name); + } + + /** + * @dataProvider providePhp82Fixtures + * @requires PHP >= 8.2 + * @throws Exception + */ + public function testPhp82Fixtures(string $name): void + { + $this->testFixture($name); + } + + public static function providePhp80Fixtures(): array + { + return [ + ["noExtraBlankLines"], + ["nullableTypeForDefaultNull"], + ["operatorSpacing"], + ["singleQuotes"], + ["strictTypes"], + ["trailingCommas"], + ["unionTypes"], + ["references"], + ["classAttributesSeparation"], + ["uselessParenthesis"], + ["laravelMigrations"], + ["phpdocs"], + ["yodaStyle"], + ["objectOperators"], + ["anonymousFunctions"], + ["namespaces"], + ["emptyLines"], + ["importsOrder"], + ]; + } + + public static function providePhp81Fixtures(): array + { + return [ + ["enums"], + ["readonlies"], + ]; + } + + public static function providePhp82Fixtures(): array + { + return [ + ["php82"], + ]; + } +} diff --git a/tests/codestyle/PurgeTest.php b/tests/codestyle/PurgeTest.php new file mode 100644 index 0000000..5fb80d8 --- /dev/null +++ b/tests/codestyle/PurgeTest.php @@ -0,0 +1,20 @@ +testFixture("noComments"); + } + + protected function getConfigPath(): string + { + return "./tests/codestyle/config/config.purge.php"; + } +} diff --git a/tests/codestyle/config.php b/tests/codestyle/config/config.php similarity index 100% rename from tests/codestyle/config.php rename to tests/codestyle/config/config.php diff --git a/tests/codestyle/config/config.purge.php b/tests/codestyle/config/config.purge.php new file mode 100644 index 0000000..09d643f --- /dev/null +++ b/tests/codestyle/config/config.purge.php @@ -0,0 +1,12 @@ +purgeMode()->config(); diff --git a/tests/codestyle/fixtures/noComments/actual.php b/tests/codestyle/fixtures/noComments/actual.php new file mode 100644 index 0000000..fbda349 --- /dev/null +++ b/tests/codestyle/fixtures/noComments/actual.php @@ -0,0 +1,147 @@ + env("DB_CONNECTION", "mysql"), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + "connections" => [ + "sqlite" => [ + "driver" => "sqlite", + "url" => env("DATABASE_URL"), + "database" => env("DB_DATABASE", database_path("database.sqlite")), + "prefix" => "", + "foreign_key_constraints" => env("DB_FOREIGN_KEYS", true), + ], + + "mysql" => [ + "driver" => "mysql", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "127.0.0.1"), + "port" => env("DB_PORT", "3306"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "unix_socket" => env("DB_SOCKET", ""), + "charset" => "utf8mb4", + "collation" => "utf8mb4_unicode_ci", + "prefix" => "", + "prefix_indexes" => true, + "strict" => true, + "engine" => null, + "options" => extension_loaded("pdo_mysql") ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env("MYSQL_ATTR_SSL_CA"), + ]) : [], + ], + + "pgsql" => [ + "driver" => "pgsql", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "127.0.0.1"), + "port" => env("DB_PORT", "5432"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "charset" => "utf8", + "prefix" => "", + "prefix_indexes" => true, + "search_path" => "public", + "sslmode" => "prefer", + ], + + "sqlsrv" => [ + "driver" => "sqlsrv", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "localhost"), + "port" => env("DB_PORT", "1433"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "charset" => "utf8", + "prefix" => "", + "prefix_indexes" => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + "migrations" => "migrations", + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + "redis" => [ + "client" => env("REDIS_CLIENT", "phpredis"), + + "options" => [ + "cluster" => env("REDIS_CLUSTER", "redis"), + "prefix" => env("REDIS_PREFIX", Str::slug(env("APP_NAME", "laravel"), "_") . "_database_"), + ], + + "default" => [ + "url" => env("REDIS_URL"), + "host" => env("REDIS_HOST", "127.0.0.1"), + "username" => env("REDIS_USERNAME"), + "password" => env("REDIS_PASSWORD"), + "port" => env("REDIS_PORT", "6379"), + "database" => env("REDIS_DB", "0"), + ], + + "cache" => [ + "url" => env("REDIS_URL"), + "host" => env("REDIS_HOST", "127.0.0.1"), + "username" => env("REDIS_USERNAME"), + "password" => env("REDIS_PASSWORD"), + "port" => env("REDIS_PORT", "6379"), + "database" => env("REDIS_CACHE_DB", "1"), + ], + ], +]; diff --git a/tests/codestyle/fixtures/noComments/expected.php b/tests/codestyle/fixtures/noComments/expected.php new file mode 100644 index 0000000..c92379a --- /dev/null +++ b/tests/codestyle/fixtures/noComments/expected.php @@ -0,0 +1,96 @@ + env("DB_CONNECTION", "mysql"), + + "connections" => [ + "sqlite" => [ + "driver" => "sqlite", + "url" => env("DATABASE_URL"), + "database" => env("DB_DATABASE", database_path("database.sqlite")), + "prefix" => "", + "foreign_key_constraints" => env("DB_FOREIGN_KEYS", true), + ], + + "mysql" => [ + "driver" => "mysql", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "127.0.0.1"), + "port" => env("DB_PORT", "3306"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "unix_socket" => env("DB_SOCKET", ""), + "charset" => "utf8mb4", + "collation" => "utf8mb4_unicode_ci", + "prefix" => "", + "prefix_indexes" => true, + "strict" => true, + "engine" => null, + "options" => extension_loaded("pdo_mysql") ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env("MYSQL_ATTR_SSL_CA"), + ]) : [], + ], + + "pgsql" => [ + "driver" => "pgsql", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "127.0.0.1"), + "port" => env("DB_PORT", "5432"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "charset" => "utf8", + "prefix" => "", + "prefix_indexes" => true, + "search_path" => "public", + "sslmode" => "prefer", + ], + + "sqlsrv" => [ + "driver" => "sqlsrv", + "url" => env("DATABASE_URL"), + "host" => env("DB_HOST", "localhost"), + "port" => env("DB_PORT", "1433"), + "database" => env("DB_DATABASE", "forge"), + "username" => env("DB_USERNAME", "forge"), + "password" => env("DB_PASSWORD", ""), + "charset" => "utf8", + "prefix" => "", + "prefix_indexes" => true, + ], + ], + + "migrations" => "migrations", + + "redis" => [ + "client" => env("REDIS_CLIENT", "phpredis"), + + "options" => [ + "cluster" => env("REDIS_CLUSTER", "redis"), + "prefix" => env("REDIS_PREFIX", Str::slug(env("APP_NAME", "laravel"), "_") . "_database_"), + ], + + "default" => [ + "url" => env("REDIS_URL"), + "host" => env("REDIS_HOST", "127.0.0.1"), + "username" => env("REDIS_USERNAME"), + "password" => env("REDIS_PASSWORD"), + "port" => env("REDIS_PORT", "6379"), + "database" => env("REDIS_DB", "0"), + ], + + "cache" => [ + "url" => env("REDIS_URL"), + "host" => env("REDIS_HOST", "127.0.0.1"), + "username" => env("REDIS_USERNAME"), + "password" => env("REDIS_PASSWORD"), + "port" => env("REDIS_PORT", "6379"), + "database" => env("REDIS_CACHE_DB", "1"), + ], + ], +];