Completed
Push — master ( b7cb0e...ffcfdb )
by Дмитрий
02:53
created

CheckCommand::execute()   D

Complexity

Conditions 10
Paths 16

Size

Total Lines 126
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 11
Bugs 1 Features 4
Metric Value
cc 10
eloc 68
c 11
b 1
f 4
nc 16
nop 2
dl 0
loc 126
ccs 0
cts 85
cp 0
crap 110
rs 4.8196

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Patsura Dmitry https://github.com/ovr <[email protected]>
4
 */
5
6
namespace PHPSA\Command;
7
8
use PhpParser\ParserFactory;
9
use PHPSA\Analyzer\EventListener\ExpressionListener;
10
use PHPSA\Analyzer\EventListener\StatementListener;
11
use PHPSA\Application;
12
use PHPSA\Compiler;
13
use PHPSA\Context;
14
use PHPSA\Definition\FileParser;
15
use RecursiveDirectoryIterator;
16
use RecursiveIteratorIterator;
17
use SplFileInfo;
18
use FilesystemIterator;
19
use PhpParser\Node;
20
use PhpParser\Parser;
21
use Symfony\Component\Console\Command\Command;
22
use Symfony\Component\Console\Input\InputArgument;
23
use Symfony\Component\Console\Input\InputInterface;
24
use Symfony\Component\Console\Input\InputOption;
25
use Symfony\Component\Console\Output\OutputInterface;
26
use Webiny\Component\EventManager\EventManager;
27
use PHPSA\Analyzer\Pass as AnalyzerPass;
28
29
/**
30
 * Class CheckCommand
31
 * @package PHPSA\Command
32
 *
33
 * @method Application getApplication();
34
 */
35
class CheckCommand extends Command
36
{
37 379
    protected function configure()
38
    {
39 379
        $this
40 379
            ->setName('check')
41 379
            ->setDescription('SPA')
42 379
            ->addOption('blame', null, InputOption::VALUE_OPTIONAL, 'Git blame author for bad code ;)', false)
43 379
            ->addArgument('path', InputArgument::OPTIONAL, 'Path to check file or directory', '.')
44 379
            ->addOption(
45 379
                'report-json',
46 379
                null,
47 379
                InputOption::VALUE_REQUIRED,
48
                'Path to save detailed report in JSON format. Example: /tmp/report.json'
49 379
            );
50 379
    }
51
52
    protected function execute(InputInterface $input, OutputInterface $output)
53
    {
54
        $output->writeln('');
55
56
        if (extension_loaded('xdebug')) {
57
            $output->writeln('<error>It is highly recommended to disable the XDebug extension before invoking this command.</error>');
58
        }
59
60
        $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7, new \PhpParser\Lexer\Emulative(
61
            array(
62
                'usedAttributes' => array(
63
                    'comments',
64
                    'startLine',
65
                    'endLine',
66
                    'startTokenPos',
67
                    'endTokenPos'
68
                )
69
            )
70
        ));
71
72
        /** @var Application $application */
73
        $application = $this->getApplication();
74
        $application->compiler = new Compiler();
75
76
        $em = EventManager::getInstance();
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $em. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
77
        $em->listen(Compiler\Event\ExpressionBeforeCompile::EVENT_NAME)
78
            ->handler(
79
                new ExpressionListener(
80
                    [
81
                        Node\Expr\FuncCall::class => [
82
                            new AnalyzerPass\Expression\FunctionCall\AliasCheck(),
83
                            new AnalyzerPass\Expression\FunctionCall\DebugCode(),
84
                            new AnalyzerPass\Expression\FunctionCall\RandomApiMigration(),
85
                            new AnalyzerPass\Expression\FunctionCall\UseCast(),
86
                            new AnalyzerPass\Expression\FunctionCall\DeprecatedIniOptions(),
87
                        ],
88
                        Node\Expr\Array_::class => [
89
                            new AnalyzerPass\Expression\ArrayShortDefinition()
90
                        ]
91
                    ]
92
                )
93
            )
94
            ->method('beforeCompile');
95
        
96
        $em->listen(Compiler\Event\StatementBeforeCompile::EVENT_NAME)
97
            ->handler(
98
                new StatementListener(
99
                    [
100
                        Node\Stmt\ClassMethod::class => [
101
                            new AnalyzerPass\Statement\MethodCannotReturn()
102
                        ]
103
                    ]
104
                )
105
            )
106
            ->method('beforeCompile');
107
108
        $context = new Context($output, $application, $em);
109
110
        /**
111
         * Store option's in application's configuration
112
         */
113
        $application->getConfiguration()->setValue('blame', $input->getOption('blame'));
114
115
        $fileParser = new FileParser(
116
            $parser,
117
            $this->getCompiler()
118
        );
119
120
        $path = $input->getArgument('path');
121
        if (is_dir($path)) {
122
            $directoryIterator = new RecursiveIteratorIterator(
123
                new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
124
            );
125
            $output->writeln('Scanning directory <info>' . $path . '</info>');
126
127
            $count = 0;
128
129
            /** @var SplFileInfo $file */
130
            foreach ($directoryIterator as $file) {
131
                if ($file->getExtension() != 'php') {
132
                    continue;
133
                }
134
135
                $context->debug($file->getPathname());
136
                $count++;
137
            }
138
139
            $output->writeln("Found <info>{$count} files</info>");
140
141
            if ($count > 100) {
142
                $output->writeln('<comment>Caution: You are trying to scan a lot of files; this might be slow. For bigger libraries, consider setting up a dedicated platform or using ci.lowl.io.</comment>');
143
            }
144
145
            $output->writeln('');
146
147
            /** @var SplFileInfo $file */
148
            foreach ($directoryIterator as $file) {
149
                if ($file->getExtension() != 'php') {
150
                    continue;
151
                }
152
153
                $fileParser->parserFile($file->getPathname(), $context);
154
            }
155
        } elseif (is_file($path)) {
156
            $fileParser->parserFile($path, $context);
157
        }
158
159
160
        /**
161
         * Step 2 Recursive check ...
162
         */
163
        $application->compiler->compile($context);
164
165
        $jsonReport = $input->getOption('report-json');
166
        if ($jsonReport) {
167
            file_put_contents(
168
                $jsonReport,
169
                json_encode(
170
                    $this->getApplication()->getIssuesCollector()->getIssues()
171
                )
172
            );
173
        }
174
175
        $output->writeln('');
176
        $output->writeln('Memory usage: ' . $this->getMemoryUsage(false) . ' (peak: ' . $this->getMemoryUsage(true) . ') MB');
177
    }
178
179
    /**
180
     * @param boolean $type
181
     * @return float
182
     */
183
    protected function getMemoryUsage($type)
184
    {
185
        return round(memory_get_usage($type) / 1024 / 1024, 2);
186
    }
187
188
    /**
189
     * @return Compiler
190
     */
191
    protected function getCompiler()
192
    {
193
        return $this->getApplication()->compiler;
194
    }
195
}
196