Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/code_analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ jobs:

-
name: 'Check Commented Code'
run: bin/swiss-knife check-commented-code src tests --ansi
run: bin/swiss-knife check-commented-code src tests

-
name: 'Check Active Classes'
run: vendor/bin/class-leak check bin src --ansi
run: vendor/bin/class-leak check bin src --skip-type="\Entropy\Console\Contract\CommandInterface"

-
name: 'Unusued check'
Expand Down
8 changes: 3 additions & 5 deletions bin/swiss-knife.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

declare(strict_types=1);

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Entropy\Console\ConsoleApplication;
use Rector\SwissKnife\DependencyInjection\ContainerFactory;

$scoperAutoloadFilepath = __DIR__ . '/../vendor/scoper-autoload.php';
Expand Down Expand Up @@ -32,7 +30,7 @@
$containerFactory = new ContainerFactory();
$container = $containerFactory->create();

$application = $container->make(Application::class);
$consoleApplication = $container->make(ConsoleApplication::class);

$exitCode = $application->run(new ArgvInput(), new ConsoleOutput());
$exitCode = $consoleApplication->run($argv);
exit($exitCode);
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^12.5",
"symfony/config": "^6.4",
"rector/jack": "^0.5.1",
"rector/rector": "^2.3",
"shipmonk/composer-dependency-analyser": "^1.8",
"symfony/config": "^6.4",
"symfony/dependency-injection": "^6.4",
"symplify/phpstan-extensions": "^12.0",
"tomasvotruba/class-leak": "^2.1",
Expand Down
11 changes: 8 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ parameters:
identifier: argument.type
path: src/Testing/MockWire.php

# optional command, depends on present of classes
# magic contract
-
identifier: argument.unresolvableType
path: src/Command/GenerateSymfonyConfigBuildersCommand.php
identifier: public.method.unused
message: '#Public method "Rector\\SwissKnife\\(.*?)Command\:\:run\(\)" is never used#'

# depends on symfony extenison class presence
-
message: '#Parameter \#1 \$objectOrClass of class ReflectionClass constructor contains unresolvable type#'
path: src/Command/GenerateSymfonyConfigBuildersCommand.php
12 changes: 7 additions & 5 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
use Rector\Config\RectorConfig;

return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPaths([__DIR__ . '/bin', __DIR__ . '/src', __DIR__ . '/tests'])
->withPhpSets()
->withRootFiles()
->withPreparedSets(
codeQuality: true,
deadCode: true,
codeQuality: true,
codingStyle: true,
typeDeclarations: true,
typeDeclarationDocblocks: true,
privatization: true,
earlyReturn: true,
codingStyle: true,
naming: true,
instanceOf: true,
naming: true
earlyReturn: true,
rectorPreset: true,
)
->withImportNames(removeUnusedImports: true)
->withSkip(['*/scoper.php', '*/Source/*', '*/Fixture/*']);
43 changes: 20 additions & 23 deletions src/Command/AliceYamlFixturesToPhpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,32 @@

namespace Rector\SwissKnife\Command;

use Entropy\Console\Contract\CommandInterface;
use Entropy\Console\Enum\ExitCode;
use Nette\Utils\FileSystem;
use PhpParser\BuilderHelpers;
use PhpParser\Node\Stmt\Return_;
use PhpParser\PrettyPrinter\Standard;
use Rector\SwissKnife\Finder\FilesFinder;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Yaml\Yaml;

/**
* @see https://github.com/nelmio/alice/blob/v2.3.0/doc/complete-reference.md#php
*/
final class AliceYamlFixturesToPhpCommand extends Command
final readonly class AliceYamlFixturesToPhpCommand implements CommandInterface
{
public function __construct(
private readonly SymfonyStyle $symfonyStyle,
private SymfonyStyle $symfonyStyle,
) {
parent::__construct();
}

protected function configure(): void
{
$this->setName('alice-yaml-fixtures-to-php');

$this->addArgument(
'sources',
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'One or more paths to check'
);

$this->setDescription('Converts Alice YAML fixtures to PHP format, so Rector and PHPStan can understand it');
}

protected function execute(InputInterface $input, OutputInterface $output): int
/**
* @param string[] $sources One or more paths to check
* @return ExitCode::*
*/
public function run(array $sources): int
{
$sources = (array) $input->getArgument('sources');
$yamlFileInfos = FilesFinder::findYamlFiles($sources);

$standard = new Standard();
Expand Down Expand Up @@ -75,7 +62,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
sprintf('Successfully converted %d Alice YAML fixtures to PHP', count($yamlFileInfos))
);

return self::SUCCESS;
return ExitCode::SUCCESS;
}

public function getName(): string
{
return 'alice-yaml-fixtures-to-php';
}

public function getDescription(): string
{
return 'Converts Alice YAML fixtures to PHP format, so Rector and PHPStan can understand it';
}

/**
Expand Down
69 changes: 26 additions & 43 deletions src/Command/CheckCommentedCodeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,36 @@

namespace Rector\SwissKnife\Command;

use Entropy\Console\Contract\CommandInterface;
use Entropy\Console\Enum\ExitCode;
use Rector\SwissKnife\Comments\CommentedCodeAnalyzer;
use Rector\SwissKnife\Finder\PhpFilesFinder;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

final class CheckCommentedCodeCommand extends Command
final readonly class CheckCommentedCodeCommand implements CommandInterface
{
private const int DEFAULT_LINE_LIMIT = 5;

public function __construct(
private readonly CommentedCodeAnalyzer $commentedCodeAnalyzer,
private readonly SymfonyStyle $symfonyStyle,
private CommentedCodeAnalyzer $commentedCodeAnalyzer,
private SymfonyStyle $symfonyStyle,
) {
parent::__construct();
}

protected function configure(): void
/**
* @param string[] $sources One or more paths to check
* @param string[] $skipFiles File paths to skip
* @param int $lineLimit Maximum number of comment lines in a row allowed
*
* @return ExitCode::*
*/
public function run(array $sources, array $skipFiles = [], int $lineLimit = self::DEFAULT_LINE_LIMIT): int
{
$this->setName('check-commented-code');

$this->addArgument(
'sources',
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'One or more paths to check'
);
$this->addOption(
'skip-file',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Skip file path'
);
$this->setDescription('Checks code for commented snippets');

$this->addOption(
'line-limit',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_OPTIONAL,
'Amount of allowed comment lines in a row',
self::DEFAULT_LINE_LIMIT
);
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$sources = (array) $input->getArgument('sources');
$skipFiles = (array) $input->getOption('skip-file');

$phpFileInfos = PhpFilesFinder::find($sources, $skipFiles);

$message = sprintf('Analysing %d *.php files', count($phpFileInfos));
$this->symfonyStyle->note($message);

$lineLimit = (int) $input->getOption('line-limit');

$commentedLinesByFilePaths = [];
foreach ($phpFileInfos as $phpFileInfo) {
$commentedLines = $this->commentedCodeAnalyzer->process($phpFileInfo->getRealPath(), $lineLimit);
Expand All @@ -75,7 +47,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if ($commentedLinesByFilePaths === []) {
$this->symfonyStyle->success('No commented code found');
return self::SUCCESS;
return ExitCode::SUCCESS;
}

foreach ($commentedLinesByFilePaths as $filePath => $commentedLines) {
Expand All @@ -86,6 +58,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

$this->symfonyStyle->error('Errors found');
return self::FAILURE;

return ExitCode::ERROR;
}

public function getName(): string
{
return 'check-commented-code';
}

public function getDescription(): string
{
return 'Checks code for commented snippets';
}
}
45 changes: 23 additions & 22 deletions src/Command/CheckConflictsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,28 @@

namespace Rector\SwissKnife\Command;

use Entropy\Console\Contract\CommandInterface;
use Entropy\Console\Enum\ExitCode;
use Rector\SwissKnife\Finder\FilesFinder;
use Rector\SwissKnife\Git\ConflictResolver;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

final class CheckConflictsCommand extends Command
final readonly class CheckConflictsCommand implements CommandInterface
{
public function __construct(
private readonly ConflictResolver $conflictResolver,
private readonly SymfonyStyle $symfonyStyle,
private ConflictResolver $conflictResolver,
private SymfonyStyle $symfonyStyle,
) {
parent::__construct();
}

protected function configure(): void
/**
* @param string[] $sources One or more path to project
* @return ExitCode::*
*/
public function run(array $sources): int
{
$this->setName('check-conflicts');

$this->setDescription('Check files for missed git conflicts');
$this->addArgument('sources', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Path to project');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var string[] $sources */
$sources = (array) $input->getArgument('sources');

$fileInfos = FilesFinder::find($sources);

$filePaths = [];
foreach ($fileInfos as $fileInfo) {
$filePaths[] = $fileInfo->getRealPath();
Expand All @@ -45,14 +36,24 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$message = sprintf('No conflicts found in %d files', count($fileInfos));
$this->symfonyStyle->success($message);

return self::SUCCESS;
return ExitCode::SUCCESS;
}

foreach ($conflictsCountByFilePath as $file => $conflictCount) {
$message = sprintf('File "%s" contains %d unresolved conflicts', $file, $conflictCount);
$this->symfonyStyle->error($message);
}

return self::FAILURE;
return ExitCode::ERROR;
}

public function getName(): string
{
return 'check-conflicts';
}

public function getDescription(): string
{
return 'Check files for missed git conflicts';
}
}
28 changes: 16 additions & 12 deletions src/Command/DumpEditorconfigCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,41 @@

namespace Rector\SwissKnife\Command;

use Entropy\Console\Contract\CommandInterface;
use Entropy\Console\Enum\ExitCode;
use Nette\Utils\FileSystem;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

final class DumpEditorconfigCommand extends Command
final readonly class DumpEditorconfigCommand implements CommandInterface
{
public function __construct(
private readonly SymfonyStyle $symfonyStyle,
private SymfonyStyle $symfonyStyle,
) {
parent::__construct();
}

protected function configure(): void
public function getName(): string
{
$this->setName('dump-editorconfig');
$this->setDescription('Dump .editorconfig file to project root');
return 'dump-editorconfig';
}

protected function execute(InputInterface $input, OutputInterface $output): int
public function getDescription(): string
{
return 'Dump .editorconfig file to project root';
}

public function run(): int
{
$projectEditorconfigFilePath = getcwd() . '/.editorconfig';
if (file_exists($projectEditorconfigFilePath)) {
$this->symfonyStyle->error('.editorconfig file already exists');
return self::FAILURE;

return ExitCode::ERROR;
}

FileSystem::copy(__DIR__ . '/../../templates/.editorconfig', $projectEditorconfigFilePath);

$this->symfonyStyle->success('.editorconfig file was created');

return self::SUCCESS;
return ExitCode::SUCCESS;
}
}
Loading