Completed
Push — master ( 81db43...f030be )
by Aleh
12s
created

IndexGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 15
rs 9.4285
cc 1
eloc 13
nc 1
nop 6
1
<?php
2
3
namespace Padawan\Framework\Generator;
4
5
use Padawan\Domain\Project\Node\ClassData;
6
use Padawan\Domain\Project\Node\InterfaceData;
7
use Padawan\Domain\Event\IndexGenerationEvent;
8
use Padawan\Framework\Domain\Project\InMemoryIndex;
9
use Padawan\Domain\Project;
10
use Padawan\Domain\Project\File;
11
use Padawan\Domain\Project\Index;
12
use Padawan\Domain\Scope\FileScope;
13
use Padawan\Framework\Utils\PathResolver;
14
use Padawan\Framework\Utils\Composer;
15
use Padawan\Framework\Utils\ClassUtils;
16
use Psr\Log\LoggerInterface;
17
use Padawan\Parser\Walker\IndexGeneratingWalker;
18
use Symfony\Component\EventDispatcher\EventDispatcher;
19
use Padawan\Domain\Generator\IndexGenerator as IndexGeneratorInterface;
20
21
class IndexGenerator implements IndexGeneratorInterface
22
{
23
    const BEFORE_GENERATION = 'index.before_generation';
24
    const AFTER_GENERATION = 'index.after_generation';
25
26
    public function __construct(
27
        PathResolver $path,
28
        ClassUtils $class,
29
        LoggerInterface $logger,
30
        EventDispatcher $dispatcher,
31
        FilesFinder $filesFinder,
32
        IndexGeneratingWalker $walker
33
    ) {
34
        $this->path             = $path;
35
        $this->classUtils       = $class;
0 ignored issues
show
Bug introduced by
The property classUtils does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
36
        $this->logger           = $logger;
37
        $this->walker           = $walker;
38
        $this->dispatcher       = $dispatcher;
39
        $this->filesFinder      = $filesFinder;
40
    }
41
42
    public function generateIndex(Project $project)
43
    {
44
        $event = new IndexGenerationEvent($project);
45
        $this->dispatcher->dispatch(self::BEFORE_GENERATION, $event);
46
47
        $index = $project->getIndex();
48
49
        $this->generateProjectIndex($project);
50
51
        $this->dispatcher->dispatch(self::AFTER_GENERATION, $event);
52
53
        return $index;
54
    }
55
56
    public function generateProjectIndex(Project $project, $rewrite = true)
57
    {
58
        // You know what this mean
59
        gc_disable();
60
        $index = $project->getIndex();
61
        $globalTime = 0;
62
        $done = 0;
63
        $files = $this->filesFinder->findProjectFiles($project);
64
        $all = count($files);
65
        foreach ($files as $file) {
66
            $start = microtime(1);
67
            $this->processFile($index, $file, $rewrite);
68
            $end = microtime(1) - $start;
69
70
            $this->getLogger()->debug("Indexing: [$end]s");
71
            $this->getLogger()->debug("Memory: " . memory_get_usage());
72
            $globalTime += $end;
73
            ++$done;
74
            $process = floor($done / $all * 100);
75
            $this->getLogger()->info("Progress: $process%");
76
        }
77
        $this->getLogger()->info("[ $globalTime ]");
78
        gc_enable();
79
    }
80
81
    public function processFile(
82
        Index $index,
83
        $filePath,
84
        $rewrite = true
85
    ) {
86
        $this->getLogger()
87
            ->info("processing $filePath");
88
        $file = $index->findFileByPath($filePath);
89
        if (empty($file)) {
90
            $file = new File($filePath);
91
        }
92
        $filePath = $this->path->getAbsolutePath($file->path());
93
        $content = $this->path->read($filePath);
94
        $hash = sha1($content);
95
        if ($rewrite || $file->isChanged($hash)) {
96
            $scope = $this->createScopeForFile($file, $content, $index, $rewrite);
97
            $this->processFileScope(
98
                $file,
99
                $index,
100
                $scope,
101
                $hash
102
            );
103
        }
104
    }
105
    public function createScopeForFile(File $file, $content, Index $index, $rewrite = true)
106
    {
107
        $startParser = microtime(1);
108
        $walker = $this->walker;
109
        $parser = $this->getClassUtils()->getParser();
110
        $parser->addWalker($walker);
111
        $parser->setIndex($index);
112
        $scope = $parser->parseContent($file->path(), $content, null);
113
        $end = microtime(1) - $startParser;
114
        $this->getLogger()->info("Parsing: [$end]s");
115
        return $scope;
116
    }
117
    public function processFileScope(File $file, Index $index, FileScope $scope = null, $hash = null)
118
    {
119
        if (empty($scope)) {
120
            return;
121
        }
122
        if (empty($hash)) {
123
            throw new \Exception("Contents hash could not be empty");
124
        }
125
        $this->getLogger()->debug(sprintf("Processing %s classes", count($scope->getClasses())));
126
        $this->getLogger()->debug(sprintf("Processing %s interfaces", count($scope->getInterfaces())));
127
        $this->getLogger()->debug(sprintf("Processing %s functions", count($scope->getFunctions())));
128
        foreach ($scope->getClasses() as $classData) {
129
            $this->getLogger()->debug('Processing node ' . $classData->fqcn->toString());
130
        }
131
        foreach ($scope->getInterfaces() as $interfaceData) {
132
            $this->getLogger()->debug('Processing node ' . $interfaceData->fqcn->toString());
133
        }
134
        foreach ($scope->getFunctions() as $functionData) {
135
            $this->getLogger()->debug('Processing node ' . $functionData->name);
136
        }
137
        $file->updateScope($scope, $hash);
138
        $index->addFile($file);
139
    }
140
141
    /** @return LoggerInterface */
142
    public function getLogger()
143
    {
144
        return $this->logger;
145
    }
146
147
    public function getWalker()
148
    {
149
        return $this->walker;
150
    }
151
152
    /** @return ClassUtils */
153
    public function getClassUtils()
154
    {
155
        return $this->classUtils;
156
    }
157
158
    public function getNamespaceUtils()
159
    {
160
        return $this->namespaceUtils;
0 ignored issues
show
Bug introduced by
The property namespaceUtils does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
161
    }
162
163
    /**
164
     *
165
     *
166
     * @var PathResolver
167
     */
168
    protected $path;
169
170
    /**
171
     * Object with Composer-specific functions
172
     *
173
     * @var Composer
174
     */
175
    protected $composer;
176
177
    /**
178
     * Object for work with class-information
179
     *
180
     * @var ClassUtils
181
     */
182
    protected $class;
183
184
    /**
185
     *
186
     * @var LoggerInterface
187
     */
188
    protected $logger;
189
190
    /**
191
     *
192
     * @var IndexGeneratingWalker
193
     */
194
    protected $walker;
195
196
    /** @var EventDispatcher */
197
    protected $dispatcher;
198
199
    /** @var FilesFinder */
200
    protected $filesFinder;
201
}
202