Passed
Pull Request — master (#40)
by Alexander
09:55 queued 07:23
created

ParserClassifier::getAvailableClasses()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 5
nop 0
dl 0
loc 18
ccs 10
cts 10
cp 1
crap 4
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Classifier;
6
7
use PhpParser\NodeTraverser;
8
use PhpParser\NodeVisitor\NameResolver;
9
use PhpParser\Parser;
10
use PhpParser\ParserFactory;
11
12
/**
13
 * `ParserClassifier` finds classes using [`nikic/PHP-Parser`](https://github.com/nikic/PHP-Parser).
14
 * This may require performance tuning, so you may need
15
 * follow {@see https://github.com/nikic/PHP-Parser/blob/master/doc/component/Performance.markdown} instructions.
16
 */
17
final class ParserClassifier extends AbstractClassifier
18
{
19
    private Parser $parser;
20
    private NodeTraverser $nodeTraverser;
21
22 14
    public function __construct(string $directory, string ...$directories)
23
    {
24 14
        parent::__construct($directory, ...$directories);
25 14
        $this->parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
26
27 14
        $traverser = new NodeTraverser();
28 14
        $traverser->addVisitor(new NameResolver());
29
30 14
        $this->nodeTraverser = $traverser;
31
    }
32
33
    /**
34
     * @return iterable<class-string>
35
     */
36 11
    protected function getAvailableClasses(): iterable
37
    {
38 11
        $files = $this->getFiles();
39 11
        $visitor = new ParserVisitor($this->interfaces, $this->attributes, $this->parentClass);
40 11
        $this->nodeTraverser->addVisitor($visitor);
41
42 11
        foreach ($files as $file) {
43
            try {
44 11
                $nodes = $this->parser->parse($file->getContents());
45 11
                if ($nodes !== null) {
46 11
                    $this->nodeTraverser->traverse($nodes);
47
                }
48 7
            } catch (\Throwable) {
49
                // Ignore broken files or parsing errors
50
            }
51
        }
52
53 11
        return $visitor->getClassNames();
54
    }
55
}
56