Completed
Pull Request — master (#293)
by Дмитрий
02:50
created

PrintCFGCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
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\Definition\FileParser;
11
use RecursiveDirectoryIterator;
12
use RecursiveIteratorIterator;
13
use SplFileInfo;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Webiny\Component\EventManager\EventManager;
19
20
/**
21
 * Command to dump the analyzer documentation as markdown
22
 */
23
class PrintCFGCommand extends Command
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28
    protected function configure()
29
    {
30
        $this
31
            ->setName('print-cfg')
32
            ->setDescription('Dumps Control Flow Graph')
33
            ->addArgument('path', InputArgument::OPTIONAL, 'Path to check file or directory', '.');
34
        ;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40
    protected function execute(InputInterface $input, OutputInterface $output)
41
    {
42
        $output->writeln('');
43
44
        if (extension_loaded('xdebug')) {
45
            /**
46
             * This will disable only showing stack traces on error conditions.
47
             */
48
            if (function_exists('xdebug_disable')) {
49
                xdebug_disable();
50
            }
51
52
            $output->writeln('<error>It is highly recommended to disable the XDebug extension before invoking this command.</error>');
53
        }
54
55
        $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7, new \PhpParser\Lexer\Emulative([
56
            'usedAttributes' => [
57
                'comments',
58
                'startLine',
59
                'endLine',
60
                'startTokenPos',
61
                'endTokenPos'
62
            ]
63
        ]));
64
65
        /** @var Application $application */
66
        $application = $this->getApplication();
67
        $application->compiler = new Compiler();
68
69
        $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...
70
        $context = new Context($output, $application, $em);
71
72
        $fileParser = new FileParser(
73
            $parser,
74
            $application->compiler
75
        );
76
77
        $path = $input->getArgument('path');
78
        if (is_dir($path)) {
79
            $directoryIterator = new RecursiveIteratorIterator(
80
                new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
81
            );
82
            $output->writeln('Scanning directory <info>' . $path . '</info>');
83
84
            $count = 0;
85
86
            /** @var SplFileInfo $file */
87
            foreach ($directoryIterator as $file) {
88
                if ($file->getExtension() !== 'php') {
89
                    continue;
90
                }
91
92
                $context->debug($file->getPathname());
93
                $count++;
94
            }
95
96
            $output->writeln("Found <info>{$count} files</info>");
97
98
            if ($count > 100) {
99
                $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>');
100
            }
101
102
            $output->writeln('');
103
104
            /** @var SplFileInfo $file */
105
            foreach ($directoryIterator as $file) {
106
                if ($file->getExtension() !== 'php') {
107
                    continue;
108
                }
109
110
                $fileParser->parserFile($file->getPathname(), $context);
111
            }
112
        } elseif (is_file($path)) {
113
            $fileParser->parserFile($path, $context);
114
        }
115
116
117
        /**
118
         * Step 2 Recursive check ...
119
         */
120
        $application->compiler->compile($context);
121
        $printer = new \PHPSA\ControlFlow\Printer\DebugText();
122
123
        $functions = $application->compiler->getFunctions();
0 ignored issues
show
Bug introduced by
The method getFunctions() does not exist on PHPSA\Compiler. Did you maybe mean getFunction()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
124
        foreach ($functions as $function) {
125
            $cfg = $function->getCFG();
126
            if ($cfg) {
127
                $printer->printGraph($cfg->getRootNode());
128
            }
129
        }
130
131
        $output->writeln('');
132
        $output->writeln('Memory usage: ' . $this->getMemoryUsage(false) . ' (peak: ' . $this->getMemoryUsage(true) . ') MB');
133
    }
134
135
    /**
136
     * @param boolean $type
137
     * @return float
138
     */
139
    protected function getMemoryUsage($type)
140
    {
141
        return round(memory_get_usage($type) / 1024 / 1024, 2);
142
    }
143
}
144