Completed
Push — master ( 662a49...9d1eac )
by Дмитрий
9s
created

PrintCFGCommand::execute()   C

Complexity

Conditions 12
Paths 36

Size

Total Lines 102
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 0
Metric Value
cc 12
eloc 54
nc 36
nop 2
dl 0
loc 102
ccs 0
cts 65
cp 0
crap 156
rs 5.034
c 0
b 0
f 0

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
namespace PHPSA\Command;
4
5
use FilesystemIterator;
6
use PhpParser\ParserFactory;
7
use PHPSA\Application;
8
use PHPSA\Compiler;
9
use PHPSA\Context;
10
use PHPSA\ControlFlow\BlockTraverser;
11
use PHPSA\ControlFlow\Visitor;
12
use PHPSA\Definition\FileParser;
13
use RecursiveDirectoryIterator;
14
use RecursiveIteratorIterator;
15
use SplFileInfo;
16
use Symfony\Component\Console\Command\Command;
17
use Symfony\Component\Console\Input\InputArgument;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Webiny\Component\EventManager\EventManager;
21
22
/**
23
 * Command to dump the analyzer documentation as markdown
24
 */
25
class PrintCFGCommand extends Command
26
{
27
    /**
28
     * {@inheritdoc}
29
     */
30 884
    protected function configure()
31
    {
32 884
        $this
33 884
            ->setName('print-cfg')
34 884
            ->setDescription('Dumps Control Flow Graph')
35 884
            ->addArgument('path', InputArgument::OPTIONAL, 'Path to check file or directory', '.');
36
        ;
37 884
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    protected function execute(InputInterface $input, OutputInterface $output)
43
    {
44
        $output->writeln('');
45
46
        if (extension_loaded('xdebug')) {
47
            /**
48
             * This will disable only showing stack traces on error conditions.
49
             */
50
            if (function_exists('xdebug_disable')) {
51
                xdebug_disable();
52
            }
53
54
            $output->writeln('<error>It is highly recommended to disable the XDebug extension before invoking this command.</error>');
55
        }
56
57
        $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7, new \PhpParser\Lexer\Emulative([
58
            'usedAttributes' => [
59
                'comments',
60
                'startLine',
61
                'endLine',
62
                'startTokenPos',
63
                'endTokenPos'
64
            ]
65
        ]));
66
67
        /** @var Application $application */
68
        $application = $this->getApplication();
69
        $application->compiler = new Compiler();
70
71
        $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...
72
        $context = new Context($output, $application, $em);
73
74
        $fileParser = new FileParser(
75
            $parser,
76
            $application->compiler
77
        );
78
79
        $path = $input->getArgument('path');
80
        if (is_dir($path)) {
81
            $directoryIterator = new RecursiveIteratorIterator(
82
                new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
83
            );
84
            $output->writeln('Scanning directory <info>' . $path . '</info>');
85
86
            $count = 0;
87
88
            /** @var SplFileInfo $file */
89
            foreach ($directoryIterator as $file) {
90
                if ($file->getExtension() !== 'php') {
91
                    continue;
92
                }
93
94
                $context->debug($file->getPathname());
95
                $count++;
96
            }
97
98
            $output->writeln("Found <info>{$count} files</info>");
99
100
            if ($count > 100) {
101
                $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>');
102
            }
103
104
            $output->writeln('');
105
106
            /** @var SplFileInfo $file */
107
            foreach ($directoryIterator as $file) {
108
                if ($file->getExtension() !== 'php') {
109
                    continue;
110
                }
111
112
                $fileParser->parserFile($file->getPathname(), $context);
113
            }
114
        } elseif (is_file($path)) {
115
            $fileParser->parserFile($path, $context);
116
        }
117
118
119
        /**
120
         * Step 2 Recursive check ...
121
         */
122
        $application->compiler->compile($context);
123
124
        $traverser = new BlockTraverser();
125
        //$traverser->addVisitor(new Visitor\DebugTextVisitor());
126
        $traverser->addVisitor(new Visitor\UnreachableVisitor());
127
128
        $printer = new \PHPSA\ControlFlow\Printer\DebugText();
129
130
        $functions = $application->compiler->getFunctions();
131
        foreach ($functions as $function) {
132
            $output->writeln('Function: ' . $function->getName());
133
134
            $cfg = $function->getCFG();
135
            if ($cfg) {
136
                $traverser->traverse($cfg);
137
                $printer->printGraph($cfg->getRoot());
138
            }
139
        }
140
141
        $output->writeln('');
142
        $output->writeln('Memory usage: ' . $this->getMemoryUsage(false) . ' (peak: ' . $this->getMemoryUsage(true) . ') MB');
143
    }
144
145
    /**
146
     * @param boolean $type
147
     * @return float
148
     */
149
    protected function getMemoryUsage($type)
150
    {
151
        return round(memory_get_usage($type) / 1024 / 1024, 2);
152
    }
153
}
154