Passed
Push — master ( 67a020...fe0e28 )
by butschster
04:26 queued 17s
created

AbstractLocator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
c 1
b 0
f 0
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Tokenizer;
6
7
use Psr\Log\LoggerAwareInterface;
8
use Spiral\Core\Container\InjectableInterface;
9
use Spiral\Logger\Traits\LoggerTrait;
10
use Spiral\Tokenizer\Exception\LocatorException;
11
use Spiral\Tokenizer\Reflection\ReflectionFile;
12
use Spiral\Tokenizer\Traits\TargetTrait;
13
use Symfony\Component\Finder\Finder;
14
15
/**
16
 * Base class for Class and Invocation locators.
17
 */
18
abstract class AbstractLocator implements InjectableInterface, LoggerAwareInterface
19
{
20
    use LoggerTrait;
21
    use TargetTrait;
22
23
    public const INJECTOR = Tokenizer::class;
24
25 403
    public function __construct(
26
        protected Finder $finder,
27
        protected readonly bool $debug = false,
28
    ) {
29 403
    }
30
31
    /**
32
     * Available file reflections. Generator.
33
     *
34
     * @throws \Exception
35
     *
36
     * @return \Generator<int, ReflectionFile, mixed, void>
37
     */
38 399
    protected function availableReflections(): \Generator
39
    {
40 399
        foreach ($this->finder->getIterator() as $file) {
41 399
            $reflection = new ReflectionFile((string)$file);
42
43 399
            if ($reflection->hasIncludes()) {
44
                // We are not analyzing files which has includes, it's not safe to require such reflections
45 30
                $this->getLogger()->warning(
46 30
                    \sprintf('File `%s` has includes and excluded from analysis', (string) $file),
47 30
                    ['file' => $file]
48 30
                );
49
50 30
                continue;
51
            }
52
53 399
            yield $reflection;
54
        }
55
    }
56
57
    /**
58
     * Safely get class reflection, class loading errors will be blocked and reflection will be
59
     * excluded from analysis.
60
     *
61
     * @template T
62
     * @param class-string<T> $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
63
     * @return \ReflectionClass<T>
64
     *
65
     * @throws LocatorException
66
     */
67 392
    protected function classReflection(string $class): \ReflectionClass
68
    {
69 392
        $loader = static function ($class) {
70 303
            if ($class === LocatorException::class) {
71
                return;
72
            }
73
74 303
            throw new LocatorException(\sprintf("Class '%s' can not be loaded", $class));
75 392
        };
76
77
        //To suspend class dependency exception
78 392
        \spl_autoload_register($loader);
79
80
        try {
81
            //In some cases reflection can thrown an exception if class invalid or can not be loaded,
82
            //we are going to handle such exception and convert it soft exception
83 392
            return new \ReflectionClass($class);
84 303
        } catch (\Throwable $e) {
85 303
            if ($e instanceof LocatorException && $e->getPrevious() != null) {
86
                $e = $e->getPrevious();
87
            }
88
89 303
            $this->getLogger()->error(
90 303
                \sprintf(
91 303
                    '%s: %s in %s:%s',
92 303
                    $class,
93 303
                    $e->getMessage(),
94 303
                    $e->getFile(),
95 303
                    $e->getLine()
96 303
                ),
97 303
                ['error' => $e]
98 303
            );
99
100 303
            throw new LocatorException($e->getMessage(), (int) $e->getCode(), $e);
101
        } finally {
102 392
            \spl_autoload_unregister($loader);
103
        }
104
    }
105
106
    /**
107
     * Safely get enum reflection, class loading errors will be blocked and reflection will be
108
     * excluded from analysis.
109
     *
110
     * @param class-string $enum
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
111
     *
112
     * @throws LocatorException
113
     */
114 7
    protected function enumReflection(string $enum): \ReflectionEnum
0 ignored issues
show
Bug introduced by
The type ReflectionEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
115
    {
116 7
        $loader = static function (string $enum): void {
117 6
            if ($enum === LocatorException::class) {
118
                return;
119
            }
120
121 6
            throw new LocatorException(\sprintf("Enum '%s' can not be loaded", $enum));
122 7
        };
123
124
        //To suspend class dependency exception
125 7
        \spl_autoload_register($loader);
126
127
        try {
128
            //In some enum reflection can thrown an exception if enum invalid or can not be loaded,
129
            //we are going to handle such exception and convert it soft exception
130 7
            return new \ReflectionEnum($enum);
131 6
        } catch (\Throwable $e) {
132 6
            if ($e instanceof LocatorException && $e->getPrevious() != null) {
133
                $e = $e->getPrevious();
134
            }
135
136 6
            $this->getLogger()->error(
137 6
                \sprintf(
138 6
                    '%s: %s in %s:%s',
139 6
                    $enum,
140 6
                    $e->getMessage(),
141 6
                    $e->getFile(),
142 6
                    $e->getLine()
143 6
                ),
144 6
                ['error' => $e]
145 6
            );
146
147 6
            throw new LocatorException($e->getMessage(), (int) $e->getCode(), $e);
148
        } finally {
149 7
            \spl_autoload_unregister($loader);
150
        }
151
    }
152
}
153