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 ( fff013...7af216 )
by Baptiste
05:28
created

src/Map/DoubleIndex.php (8 issues)

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