GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( a1e45f...4cf84e )
by Baptiste
05:27
created

Primitive::toSetOf()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 12
ccs 6
cts 6
cp 1
crap 3
rs 10
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable\Map;
5
6
use Innmind\Immutable\{
7
    Map,
8
    Type,
9
    Str,
10
    Sequence,
11
    Set,
12
    Pair,
13
    ValidateArgument,
14
    Exception\LogicException,
15
    Exception\ElementNotFound,
16
    Exception\CannotGroupEmptyStructure,
17
};
18
19
/**
20
 * @template T
21
 * @template S
22
 */
23
final class Primitive implements Implementation
24
{
25
    private string $keyType;
26
    private string $valueType;
27
    private ValidateArgument $validateKey;
28
    private ValidateArgument $validateValue;
29
    /** @var array<T, S> */
30
    private array $values;
31
    private ?int $size;
32
33 65
    public function __construct(string $keyType, string $valueType)
34
    {
35 65
        $this->validateKey = Type::of($keyType);
36
37 65
        if (!in_array($keyType, ['int', 'integer', 'string'], true)) {
38 1
            throw new LogicException;
39
        }
40
41 64
        $this->validateValue = Type::of($valueType);
42 64
        $this->keyType = $keyType;
43 64
        $this->valueType = $valueType;
44 64
        $this->values = [];
45 64
        $this->size = null;
46 64
    }
47
48 22
    public function keyType(): string
49
    {
50 22
        return $this->keyType;
51
    }
52
53 20
    public function valueType(): string
54
    {
55 20
        return $this->valueType;
56
    }
57
58 19
    public function size(): int
59
    {
60
        /** @psalm-suppress MixedArgumentTypeCoercion */
61 19
        return $this->size ?? $this->size = \count($this->values);
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67 3
    public function count(): int
68
    {
69 3
        return $this->size();
70
    }
71
72
    /**
73
     * @param T $key
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Map\T 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...
74
     * @param S $value
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Map\S 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...
75
     *
76
     * @return self<T, S>
77
     */
78 51
    public function put($key, $value): self
79
    {
80 51
        ($this->validateKey)($key, 1);
81 50
        ($this->validateValue)($value, 2);
82
83 49
        $map = clone $this;
84 49
        $map->size = null;
85 49
        $map->values[$key] = $value;
86
87 49
        return $map;
88
    }
89
90
    /**
91
     * @param T $key
92
     *
93
     * @throws ElementNotFound
94
     *
95
     * @return S
96
     */
97 22
    public function get($key)
98
    {
99 22
        if (!$this->contains($key)) {
100 2
            throw new ElementNotFound($key);
101
        }
102
103 20
        return $this->values[$key];
104
    }
105
106
    /**
107
     * @param T $key
108
     */
109 27
    public function contains($key): bool
110
    {
111
        /** @psalm-suppress MixedArgumentTypeCoercion */
112 27
        return \array_key_exists($key, $this->values);
113
    }
114
115
    /**
116
     * @return self<T, S>
117
     */
118 10
    public function clear(): self
119
    {
120 10
        $map = clone $this;
121 10
        $map->size = null;
122 10
        $map->values = [];
123
124 10
        return $map;
125
    }
126
127
    /**
128
     * @param Implementation<T, S> $map
129
     */
130 7
    public function equals(Implementation $map): bool
131
    {
132 7
        if ($map->size() !== $this->size()) {
133 2
            return false;
134
        }
135
136 7
        foreach ($this->values as $k => $v) {
137 6
            if (!$map->contains($k)) {
138 2
                return false;
139
            }
140
141 6
            if ($map->get($k) !== $v) {
142 3
                return false;
143
            }
144
        }
145
146 6
        return true;
147
    }
148
149
    /**
150
     * @param callable(T, S): bool $predicate
151
     *
152
     * @return self<T, S>
153
     */
154 2
    public function filter(callable $predicate): self
155
    {
156 2
        $map = $this->clear();
157
158 2
        foreach ($this->values as $k => $v) {
159 2
            if ($predicate($this->normalizeKey($k), $v) === true) {
160 2
                $map->values[$k] = $v;
161
            }
162
        }
163
164 2
        return $map;
165
    }
166
167
    /**
168
     * @param callable(T, S): void $function
169
     */
170 3
    public function foreach(callable $function): void
171
    {
172 3
        foreach ($this->values as $k => $v) {
173 3
            $function($this->normalizeKey($k), $v);
174
        }
175 3
    }
176
177
    /**
178
     * @template D
179
     * @param callable(T, S): D $discriminator
180
     *
181
     * @throws CannotGroupEmptyStructure
182
     *
183
     * @return Map<D, Map<T, S>>
184
     */
185 4
    public function groupBy(callable $discriminator): Map
186
    {
187 4
        if ($this->empty()) {
188 2
            throw new CannotGroupEmptyStructure;
189
        }
190
191 2
        $groups = null;
192
193 2
        foreach ($this->values as $k => $v) {
194
            /** @var T */
195 2
            $key = $this->normalizeKey($k);
196
            /** @var S */
197 2
            $value = $v;
198 2
            $discriminant = $discriminator($key, $value);
199
200 2
            if ($groups === null) {
201
                /** @var Map<D, Map<T, S>> */
202 2
                $groups = Map::of(
203 2
                    Type::determine($discriminant),
204 2
                    Map::class,
205
                );
206
            }
207
208 2
            if ($groups->contains($discriminant)) {
209
                /** @var Map<T, S> */
210 2
                $group = $groups->get($discriminant);
211
                /** @var Map<T, S> */
212 2
                $group = ($group)($key, $value);
213
214 2
                $groups = ($groups)($discriminant, $group);
215
            } else {
216
                /** @var Map<T, S> */
217 2
                $group = $this->clearMap()($key, $value);
218
219 2
                $groups = ($groups)($discriminant, $group);
220
            }
221
        }
222
223
        /** @var Map<D, Map<T, S>> */
224 2
        return $groups;
225
    }
226
227
    /**
228
     * @return Set<T>
229
     */
230 14
    public function keys(): Set
231
    {
232
        /** @psalm-suppress MixedArgumentTypeCoercion */
233 14
        $keys = \array_keys($this->values);
234
235 14
        return Set::of(
236 14
            $this->keyType,
237 14
            ...\array_map(
238
                function($key) {
239 14
                    return $this->normalizeKey($key);
240 14
                },
241 14
                $keys,
242
            ),
243
        );
244
    }
245
246
    /**
247
     * @return Sequence<S>
248
     */
249 14
    public function values(): Sequence
250
    {
251
        /** @psalm-suppress MixedArgumentTypeCoercion */
252 14
        $values = \array_values($this->values);
253
254 14
        return Sequence::of($this->valueType, ...$values);
255
    }
256
257
    /**
258
     * @param callable(T, S): (S|Pair<T, S>) $function
259
     *
260
     * @return self<T, S>
261
     */
262 6
    public function map(callable $function): self
263
    {
264 6
        $map = $this->clear();
265
266 6
        foreach ($this->values as $k => $v) {
267 6
            $return = $function($this->normalizeKey($k), $v);
268
269 6
            if ($return instanceof Pair) {
270 4
                ($this->validateKey)($return->key(), 1);
271
272
                /** @var T */
273 2
                $key = $return->key();
274
                /** @var S */
275 2
                $value = $return->value();
276
            } else {
277 4
                $key = $k;
278 4
                $value = $return;
279
            }
280
281 4
            ($this->validateValue)($value, 2);
282
283 2
            $map->values[$key] = $value;
284
        }
285
286 2
        return $map;
287
    }
288
289 2
    public function join(string $separator): Str
290
    {
291 2
        return $this->values()->join($separator);
292
    }
293
294
    /**
295
     * @param T $key
296
     *
297
     * @return self<T, S>
298
     */
299 2
    public function remove($key): self
300
    {
301 2
        if (!$this->contains($key)) {
302 2
            return $this;
303
        }
304
305 2
        $map = clone $this;
306 2
        $map->size = null;
307
        /** @psalm-suppress MixedArrayTypeCoercion */
308 2
        unset($map->values[$key]);
309
310 2
        return $map;
311
    }
312
313
    /**
314
     * @param Implementation<T, S> $map
315
     *
316
     * @return self<T, S>
317
     */
318 1
    public function merge(Implementation $map): self
319
    {
320
        /** @var self<T, S> $merged */
321 1
        $merged = $map->reduce(
322 1
            $this,
323
            function(self $carry, $key, $value): self {
324 1
                return $carry->put($key, $value);
325 1
            }
326
        );
327
328 1
        return $merged;
329
    }
330
331
    /**
332
     * @param callable(T, S): bool $predicate
333
     *
334
     * @return Map<bool, Map<T, S>>
335
     */
336 2
    public function partition(callable $predicate): Map
337
    {
338 2
        $truthy = $this->clearMap();
339 2
        $falsy = $this->clearMap();
340
341 2
        foreach ($this->values as $k => $v) {
342 2
            $return = $predicate($this->normalizeKey($k), $v);
343
344 2
            if ($return === true) {
345 2
                $truthy = ($truthy)($k, $v);
346
            } else {
347 2
                $falsy = ($falsy)($k, $v);
348
            }
349
        }
350
351
        /**
352
         * @psalm-suppress InvalidScalarArgument
353
         * @psalm-suppress InvalidArgument
354
         */
355 2
        return Map::of('bool', Map::class)
356 2
            (true, $truthy)
357 2
            (false, $falsy);
358
    }
359
360
    /**
361
     * @template R
362
     * @param R $carry
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Map\R 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...
363
     * @param callable(R, T, S): R $reducer
364
     *
365
     * @return R
366
     */
367 5
    public function reduce($carry, callable $reducer)
368
    {
369 5
        foreach ($this->values as $k => $v) {
370 5
            $carry = $reducer($carry, $this->normalizeKey($k), $v);
371
        }
372
373 5
        return $carry;
374
    }
375
376 5
    public function empty(): bool
377
    {
378
        /** @psalm-suppress MixedArgumentTypeCoercion */
379 5
        \reset($this->values);
380
381
        /** @psalm-suppress MixedArgumentTypeCoercion */
382 5
        return \is_null(\key($this->values));
383
    }
384
385
    /**
386
     * @param mixed $value
387
     *
388
     * @return T
389
     */
390 25
    private function normalizeKey($value)
391
    {
392 25
        if ($this->keyType === 'string' && !\is_null($value)) {
393
            /** @var T */
394 1
            return (string) $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return (string)$value returns the type string which is incompatible with the documented return type Innmind\Immutable\Map\T.
Loading history...
395
        }
396
397
        /** @var T */
398 24
        return $value;
399
    }
400
401
    /**
402
     * @template ST
403
     *
404
     * @param callable(T, S): \Generator<ST> $mapper
405
     *
406
     * @return Set<ST>
407
     */
408 2
    public function toSetOf(string $type, callable $mapper): Set
409
    {
410
        /** @var Set<ST> */
411 2
        $set = Set::of($type);
412
413 2
        foreach ($this->values as $key => $value) {
414 2
            foreach ($mapper($key, $value) as $newValue) {
415 2
                $set = ($set)($newValue);
416
            }
417
        }
418
419 2
        return $set;
420
    }
421
422
    /**
423
     * @return Map<T, S>
424
     */
425 4
    private function clearMap(): Map
426
    {
427 4
        return Map::of($this->keyType, $this->valueType);
428
    }
429
}
430