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.
Passed
Push — develop ( 3d4c79...7ab88f )
by Baptiste
05:30
created

Primitive::toMapOf()   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
nc 3
nop 3
dl 0
loc 12
ccs 6
cts 6
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable\Sequence;
5
6
use Innmind\Immutable\{
7
    Map,
8
    Sequence,
9
    Str,
10
    Set,
11
    Type,
12
    ValidateArgument,
13
    Exception\OutOfBoundException,
14
    Exception\LogicException,
15
    Exception\ElementNotFound,
16
    Exception\CannotGroupEmptyStructure,
17
};
18
19
/**
20
 * @template T
21
 */
22
final class Primitive implements Implementation
23
{
24
    private string $type;
25
    private ValidateArgument $validate;
26
    /** @var list<T> */
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Sequence\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...
27
    private array $values;
28
    private ?int $size;
29
30
    /**
31
     * @param T $values
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Sequence\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...
32
     */
33 259
    public function __construct(string $type, ...$values)
34
    {
35 259
        $this->type = $type;
36 259
        $this->validate = Type::of($type);
37 259
        $this->values = $values;
0 ignored issues
show
Documentation Bug introduced by
It seems like $values of type array<integer,Innmind\Immutable\Sequence\T> is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
38 259
        $this->size = null;
39 259
    }
40
41 3
    public function type(): string
42
    {
43 3
        return $this->type;
44
    }
45
46 162
    public function size(): int
47
    {
48 162
        return $this->size ?? $this->size = \count($this->values);
49
    }
50
51 1
    public function count(): int
52
    {
53 1
        return $this->size();
54
    }
55
56 37
    public function toArray(): array
57
    {
58 37
        return $this->values;
59
    }
60
61
    /**
62
     * @throws OutOfBoundException
63
     *
64
     * @return T
65
     */
66 34
    public function get(int $index)
67
    {
68 34
        if (!$this->has($index)) {
69 4
            throw new OutOfBoundException;
70
        }
71
72 30
        return $this->values[$index];
73
    }
74
75
    /**
76
     * @param Implementation<T> $sequence
77
     *
78
     * @return self<T>
79
     */
80 4
    public function diff(Implementation $sequence): self
81
    {
82
        return $this->filter(static function($value) use ($sequence): bool {
83
            /** @var T $value */
84 4
            return !$sequence->contains($value);
85 4
        });
86
    }
87
88
    /**
89
     * @return self<T>
90
     */
91 97
    public function distinct(): self
92
    {
93 97
        return $this->reduce(
94 97
            $this->clear(),
95
            static function(self $values, $value): self {
96 60
                if ($values->contains($value)) {
97 8
                    return $values;
98
                }
99
100 60
                return $values->add($value);
101 97
            }
102
        );
103
    }
104
105
    /**
106
     * @return self<T>
107
     */
108 5
    public function drop(int $size): self
109
    {
110 5
        $self = $this->clear();
111 5
        $self->values = \array_slice($this->values, $size);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_slice($this->values, $size) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
112
113 5
        return $self;
114
    }
115
116
    /**
117
     * @return self<T>
118
     */
119 2
    public function dropEnd(int $size): self
120
    {
121 2
        $self = $this->clear();
122 2
        $self->values = \array_slice($this->values, 0, $this->size() - $size);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_slice($this->value... $this->size() - $size) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
123
124 2
        return $self;
125
    }
126
127
    /**
128
     * @param Implementation<T> $sequence
129
     */
130 7
    public function equals(Implementation $sequence): bool
131
    {
132 7
        return $this->values === $sequence->toArray();
133
    }
134
135
    /**
136
     * @param callable(T): bool $predicate
137
     *
138
     * @return self<T>
139
     */
140 22
    public function filter(callable $predicate): self
141
    {
142 22
        $self = $this->clear();
143 22
        $self->values = \array_values(\array_filter(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_values(array_filte...s->values, $predicate)) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
144 22
            $this->values,
145 22
            $predicate
146
        ));
147
148 22
        return $self;
149
    }
150
151
    /**
152
     * @param callable(T): void $function
153
     */
154 4
    public function foreach(callable $function): void
155
    {
156 4
        foreach ($this->values as $value) {
157 4
            $function($value);
158
        }
159 4
    }
160
161
    /**
162
     * @template D
163
     * @param callable(T): D $discriminator
164
     *
165
     * @throws CannotGroupEmptyStructure
166
     *
167
     * @return Map<D, Sequence<T>>
168
     */
169 6
    public function groupBy(callable $discriminator): Map
170
    {
171 6
        if ($this->empty()) {
172 2
            throw new CannotGroupEmptyStructure;
173
        }
174
175 4
        $groups = null;
176
177 4
        foreach ($this->values as $value) {
178 4
            $key = $discriminator($value);
179
180 4
            if ($groups === null) {
181
                /** @var Map<D, Sequence<T>> */
182 4
                $groups = Map::of(
183 4
                    Type::determine($key),
184 4
                    Sequence::class,
185
                );
186
            }
187
188 4
            if ($groups->contains($key)) {
189
                /** @var Sequence<T> */
190 4
                $group = $groups->get($key);
191
                /** @var Sequence<T> */
192 4
                $group = ($group)($value);
193
194 4
                $groups = ($groups)($key, $group);
195
            } else {
196 4
                $groups = ($groups)($key, Sequence::of($this->type, $value));
197
            }
198
        }
199
200
        /** @var Map<D, Sequence<T>> */
201 4
        return $groups;
202
    }
203
204
    /**
205
     * @return T
206
     */
207 5
    public function first()
208
    {
209 5
        return $this->get(0);
210
    }
211
212
    /**
213
     * @return T
214
     */
215 5
    public function last()
216
    {
217 5
        return $this->get($this->size() - 1);
218
    }
219
220
    /**
221
     * @param T $element
222
     */
223 110
    public function contains($element): bool
224
    {
225 110
        return \in_array($element, $this->values, true);
226
    }
227
228
    /**
229
     * @param T $element
230
     *
231
     * @throws ElementNotFound
232
     */
233 21
    public function indexOf($element): int
234
    {
235 21
        $index = \array_search($element, $this->values, true);
236
237 21
        if ($index === false) {
238 1
            throw new ElementNotFound($element);
239
        }
240
241 20
        return $index;
242
    }
243
244
    /**
245
     * @psalm-suppress LessSpecificImplementedReturnType Don't why it complains
246
     *
247
     * @return self<int>
248
     */
249 4
    public function indices(): self
250
    {
251 4
        if ($this->empty()) {
252
            /** @var self<int> */
253 2
            return new self('int');
254
        }
255
256
        /** @var self<int> */
257 2
        return new self('int', ...\range(0, $this->size() - 1));
258
    }
259
260
    /**
261
     * @param callable(T): T $function
262
     *
263
     * @return self<T>
264
     */
265 5
    public function map(callable $function): self
266
    {
267
        /**
268
         * @psalm-suppress MissingClosureParamType
269
         * @psalm-suppress MissingClosureReturnType
270
         */
271
        $function = function($value) use ($function) {
272
            /** @var T $value */
273 5
            $returned = $function($value);
274 5
            ($this->validate)($returned, 1);
275
276 3
            return $returned;
277 5
        };
278
279 5
        $self = clone $this;
280 5
        $self->values = \array_map($function, $this->values);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_map($function, $this->values) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
281
282 3
        return $self;
283
    }
284
285
    /**
286
     * @param T $element
287
     *
288
     * @return self<T>
289
     */
290 2
    public function pad(int $size, $element): self
291
    {
292 2
        $self = $this->clear();
293 2
        $self->values = \array_pad($this->values, $size, $element);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_pad($this->values, $size, $element) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
294
295 2
        return $self;
296
    }
297
298
    /**
299
     * @param callable(T): bool $predicate
300
     *
301
     * @return Map<bool, Sequence<T>>
302
     */
303 4
    public function partition(callable $predicate): Map
304
    {
305
        /** @var list<T> */
306 4
        $truthy = [];
307
        /** @var list<T> */
308 4
        $falsy = [];
309
310 4
        foreach ($this->values as $value) {
311 4
            if ($predicate($value) === true) {
312 4
                $truthy[] = $value;
313
            } else {
314 4
                $falsy[] = $value;
315
            }
316
        }
317
318
        /** @var Sequence<T> */
319 4
        $true = Sequence::of($this->type, ...$truthy);
320
        /** @var Sequence<T> */
321 4
        $false = Sequence::of($this->type, ...$falsy);
322
323
        /**
324
         * @psalm-suppress InvalidScalarArgument
325
         * @psalm-suppress InvalidArgument
326
         */
327 4
        return Map::of('bool', Sequence::class)
328 4
            (true, $true)
329 4
            (false, $false);
330
    }
331
332
    /**
333
     * @return self<T>
334
     */
335 14
    public function slice(int $from, int $until): self
336
    {
337 14
        $self = $this->clear();
338 14
        $self->values = \array_slice(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_slice($this->values, $from, $until - $from) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
339 14
            $this->values,
340 14
            $from,
341 14
            $until - $from,
342
        );
343
344 14
        return $self;
345
    }
346
347
    /**
348
     * @throws OutOfBoundException
349
     *
350
     * @return Sequence<Sequence<T>>
351
     */
352 2
    public function splitAt(int $index): Sequence
353
    {
354
        /** @var Sequence<T> */
355 2
        $first = Sequence::of($this->type, ...$this->slice(0, $index)->toArray());
356
        /** @var Sequence<T> */
357 2
        $second = Sequence::of($this->type, ...$this->slice($index, $this->size())->toArray());
358
359
        /** @var Sequence<Sequence<T>> */
360 2
        return Sequence::of(Sequence::class, $first, $second);
361
    }
362
363
    /**
364
     * @return self<T>
365
     */
366 5
    public function take(int $size): self
367
    {
368 5
        return $this->slice(0, $size);
369
    }
370
371
    /**
372
     * @return self<T>
373
     */
374 2
    public function takeEnd(int $size): self
375
    {
376 2
        return $this->slice($this->size() - $size, $this->size());
377
    }
378
379
    /**
380
     * @param Implementation<T> $sequence
381
     *
382
     * @return self<T>
383
     */
384 8
    public function append(Implementation $sequence): self
385
    {
386 8
        $self = $this->clear();
387
        /** @var list<T> */
388 8
        $self->values = \array_merge($this->values, $sequence->toArray());
389
390 8
        return $self;
391
    }
392
393
    /**
394
     * @param Implementation<T> $sequence
395
     *
396
     * @return self<T>
397
     */
398 14
    public function intersect(Implementation $sequence): self
399
    {
400
        return $this->filter(static function($value) use ($sequence): bool {
401
            /** @var T $value */
402 14
            return $sequence->contains($value);
403 14
        });
404
    }
405
406
    /**
407
     * @param T $element
408
     *
409
     * @return self<T>
410
     */
411 155
    public function add($element): self
412
    {
413 155
        $self = clone $this;
414 155
        $self->values[] = $element;
415 155
        $self->size = $this->size() + 1;
416
417 155
        return $self;
418
    }
419
420
    /**
421
     * @param callable(T, T): int $function
422
     *
423
     * @return self<T>
424
     */
425 4
    public function sort(callable $function): self
426
    {
427 4
        $self = clone $this;
428 4
        \usort($self->values, $function);
429
430 4
        return $self;
431
    }
432
433
    /**
434
     * @template R
435
     * @param R $carry
0 ignored issues
show
Bug introduced by
The type Innmind\Immutable\Sequence\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...
436
     * @param callable(R, T): R $reducer
437
     *
438
     * @return R
439
     */
440 224
    public function reduce($carry, callable $reducer)
441
    {
442
        /** @var R */
443 224
        return \array_reduce($this->values, $reducer, $carry);
444
    }
445
446
    /**
447
     * @return self<T>
448
     */
449 121
    public function clear(): Implementation
450
    {
451 121
        return new self($this->type);
452
    }
453
454
    /**
455
     * @return self<T>
456
     */
457 4
    public function reverse(): self
458
    {
459 4
        $self = clone $this;
460 4
        $self->values = \array_reverse($this->values);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reverse($this->values) of type array is incompatible with the declared type Innmind\Immutable\Sequence\list of property $values.

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...
461
462 4
        return $self;
463
    }
464
465 19
    public function empty(): bool
466
    {
467 19
        return !$this->has(0);
468
    }
469
470
    /**
471
     * @template ST
472
     *
473
     * @param callable(T): \Generator<ST> $mapper
474
     *
475
     * @return Sequence<ST>
476
     */
477 11
    public function toSequenceOf(string $type, callable $mapper): Sequence
478
    {
479
        /** @var Sequence<ST> */
480 11
        $sequence = Sequence::of($type);
481
482 11
        foreach ($this->values as $value) {
483 11
            foreach ($mapper($value) as $newValue) {
484 11
                $sequence = ($sequence)($newValue);
485
            }
486
        }
487
488 11
        return $sequence;
489
    }
490
491
    /**
492
     * @template ST
493
     *
494
     * @param callable(T): \Generator<ST> $mapper
495
     *
496
     * @return Set<ST>
497
     */
498 4
    public function toSetOf(string $type, callable $mapper): Set
499
    {
500
        /** @var Set<ST> */
501 4
        $set = Set::of($type);
502
503 4
        foreach ($this->values as $value) {
504 4
            foreach ($mapper($value) as $newValue) {
505 4
                $set = ($set)($newValue);
506
            }
507
        }
508
509 4
        return $set;
510
    }
511
512
513
514
    /**
515
     * @template MT
516
     * @template MS
517
     *
518
     * @param callable(T): \Generator<MT, MS> $mapper
519
     *
520
     * @return Map<MT, MS>
521
     */
522 4
    public function toMapOf(string $key, string $value, callable $mapper): Map
523
    {
524
        /** @var Map<MT, MS> */
525 4
        $map = Map::of($key, $value);
526
527 4
        foreach ($this->values as $value) {
528 4
            foreach ($mapper($value) as $newKey => $newValue) {
529 4
                $map = ($map)($newKey, $newValue);
530
            }
531
        }
532
533 4
        return $map;
534
    }
535
536 53
    private function has(int $index): bool
537
    {
538 53
        return \array_key_exists($index, $this->values);
539
    }
540
}
541