Passed
Push — master ( 8feb2a...cb2398 )
by Théo
01:57
created

SymbolRegistry   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 46
dl 0
loc 147
rs 10
c 1
b 0
f 0
wmc 14

8 Methods

Rating   Name   Duplication   Size   Complexity  
A createForConstants() 0 13 1
A create() 0 11 1
A getRegexes() 0 3 1
A __construct() 0 8 1
A merge() 0 20 3
A lowerCaseConstantName() 0 11 1
A matches() 0 18 5
A getNames() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Humbug\PhpScoper\Symbol;
6
7
use InvalidArgumentException;
8
use function array_key_exists;
9
use function array_keys;
10
use function array_map;
11
use function array_pop;
12
use function array_unique;
13
use function explode;
14
use function implode;
15
use function ltrim;
16
use function Safe\array_flip;
17
use function Safe\preg_match;
18
use function strtolower;
19
use function trim;
20
use const SORT_STRING;
21
22
final class SymbolRegistry
23
{
24
    /**
25
     * @var array<string, mixed>
26
     */
27
    private array $names;
28
29
    /**
30
     * @var list<string>
0 ignored issues
show
Bug introduced by
The type Humbug\PhpScoper\Symbol\list 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...
31
     */
32
    private array $regexes;
33
34
    private bool $constants;
35
36
    /**
37
     * @param string[] $names
38
     * @param string[] $regexes
39
     */
40
    public static function create(
41
        array $names = [],
42
        array $regexes = []
43
    ): self {
44
        return new self(
45
            array_map(
46
                static fn (string $name) => strtolower(trim($name, '\\')),
47
                $names,
48
            ),
49
            array_unique($regexes, SORT_STRING),
50
            false,
51
        );
52
    }
53
54
    /**
55
     * Unlike classes & functions, constants are not case-insensitive (although
56
     * the namespace part _is_). I.e. \Acme\FOO = \ACME\FOO but Acme\FOO ≠ Acme\Foo.
57
     *
58
     * @param string[] $names
59
     * @param string[] $regexes
60
     */
61
    public static function createForConstants(
62
        array $names = [],
63
        array $regexes = []
64
    ): self {
65
        return new self(
66
            array_map(
67
                static fn (string $name) => self::lowerCaseConstantName(
68
                    trim($name, '\\'),
69
                ),
70
                $names,
71
            ),
72
            array_unique($regexes, SORT_STRING),
73
            true,
74
        );
75
    }
76
77
    /**
78
     * @param list<string> $names
79
     * @param list<string> $regexes
80
     */
81
    private function __construct(
82
        array $names,
83
        array $regexes,
84
        bool $constants
85
    ) {
86
        $this->names = array_flip($names);
87
        $this->regexes = $regexes;
0 ignored issues
show
Documentation Bug introduced by
It seems like $regexes of type array is incompatible with the declared type Humbug\PhpScoper\Symbol\list of property $regexes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
88
        $this->constants = $constants;
89
    }
90
91
    public function matches(string $symbol): bool
92
    {
93
        $originalSymbol = ltrim($symbol, '\\');
94
        $symbol = $this->constants
95
            ? self::lowerCaseConstantName($originalSymbol)
96
            : strtolower($originalSymbol);
97
98
        if (array_key_exists($symbol, $this->names)) {
99
            return true;
100
        }
101
102
        foreach ($this->regexes as $regex) {
103
            if (preg_match($regex, $originalSymbol)) {
104
                return true;
105
            }
106
        }
107
108
        return false;
109
    }
110
111
    public function merge(SymbolRegistry $registry): self
112
    {
113
        if ($this->constants !== $registry->constants) {
114
            throw new InvalidArgumentException('Cannot merge registries of different symbol types');
115
        }
116
117
        $args = [
118
            [
119
                ...$this->getNames(),
120
                ...$registry->getNames(),
121
            ],
122
            [
123
                ...$this->getRegexes(),
124
                ...$registry->getRegexes(),
125
            ],
126
        ];
127
128
        return $this->constants
129
            ? self::createForConstants(...$args)
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $names of Humbug\PhpScoper\Symbol\...y::createForConstants() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
            ? self::createForConstants(/** @scrutinizer ignore-type */ ...$args)
Loading history...
130
            : self::create(...$args);
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $names of Humbug\PhpScoper\Symbol\SymbolRegistry::create() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

130
            : self::create(/** @scrutinizer ignore-type */ ...$args);
Loading history...
131
    }
132
133
    /**
134
     * @internal
135
     *
136
     * @return list<string>
137
     */
138
    public function getNames(): array
139
    {
140
        return array_keys($this->names);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_keys($this->names) returns the type array which is incompatible with the documented return type Humbug\PhpScoper\Symbol\list.
Loading history...
141
    }
142
143
    /**
144
     * @internal
145
     *
146
     * @erturn list<string>
147
     */
148
    public function getRegexes(): array
149
    {
150
        return $this->regexes;
151
    }
152
153
    /**
154
     * Transforms the constant FQ name "Acme\Foo\X" to "acme\foo\X" since the
155
     * namespace remains case-insensitive for constants regardless of whether
156
     * constants actually are case-insensitive.
157
     */
158
    private static function lowerCaseConstantName(string $name): string
159
    {
160
        $parts = explode('\\', $name);
161
162
        $lastPart = array_pop($parts);
163
164
        $parts = array_map('strtolower', $parts);
165
166
        $parts[] = $lastPart;
167
168
        return implode('\\', $parts);
169
    }
170
}
171