Completed
Push — master ( 0770f8...218e56 )
by Ryosuke
21:28
created

GeneratorContainer::getReturnOrThrown()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 6

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 8.8571
cc 6
eloc 7
nc 4
nop 0
crap 6
1
<?php
2
3
namespace mpyw\Co\Internal;
4
use mpyw\Co\CoInterface;
5
use mpyw\Co\Internal\CoOption;
6
7
class GeneratorContainer
8
{
9
    /**
10
     * Generator.
11
     * @var Generator
12
     */
13
    private $g;
14
15
    /**
16
     * Generator object hash.
17
     * @var string
18
     */
19
    private $h;
20
21
    /**
22
     * Thrown exception.
23
     * @var Throwable|Exception
24
     */
25
    private $e;
26
27
    /**
28
     * Default options.
29
     * @var CoOption
30
     */
31
    private $options;
32
33
    /**
34
     * Constructor.
35
     * @param Generator $g
36
     * @param CoOption  $options
37
     * @param mixed     $yield_key
38
     */
39 15
    public function __construct(\Generator $g, CoOption $options = null, $yield_key = null)
40 15
    {
41 15
        $this->g = $g;
0 ignored issues
show
Documentation Bug introduced by
It seems like $g of type object<Generator> is incompatible with the declared type object<mpyw\Co\Internal\Generator> of property $g.

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...
42 15
        $this->h = spl_object_hash($g);
43 15
        if ($options === null) {
44 9
            $options = new CoOption;
45
        }
46 15
        if ($yield_key === CoInterface::SAFE) {
47 2
            $options = $options->reconfigure(['throw' => false]);
48
        }
49 15
        if ($yield_key === CoInterface::UNSAFE) {
50 1
            $options = $options->reconfigure(['throw' => true]);
51
        }
52 15
        $this->options = $options;
53 15
        $this->valid();
54 15
    }
55
56
    /**
57
     * Return options.
58
     * @return CoOption
59
     */
60 4
    public function getOptions()
61 4
    {
62 4
        return $this->options;
63
    }
64
65
    /**
66
     * Return generator hash.
67
     * @return string
68
     */
69 3
    public function __toString()
70 3
    {
71 3
        return $this->h;
72
    }
73
74
    /**
75
     * Return whether generator is actually working.
76
     * @return bool
77
     */
78 15
    public function valid()
79 15
    {
80
        try {
81 15
            $this->g->current();
82 15
            return $this->e === null && $this->g->valid() && $this->g->key() !== CoInterface::RETURN_WITH;
83 2
        } catch (\RuntimeException $e) {
84 2
            $this->e = $e;
0 ignored issues
show
Documentation Bug introduced by
It seems like $e of type object<RuntimeException> is incompatible with the declared type object<mpyw\Co\Internal\...\Co\Internal\Exception> of property $e.

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...
85 2
            return false;
86
        }
87
    }
88
89
    /**
90
     * Return current key.
91
     * @return mixed
92
     */
93 3
    public function key()
94 3
    {
95 3
        $this->validateValidity();
96 3
        return $this->g->key();
97
    }
98
99
    /**
100
     * Return current value.
101
     * @return mixed
102
     */
103 6
    public function current()
104 6
    {
105 6
        $this->validateValidity();
106 6
        return $this->g->current();
107
    }
108
109
    /**
110
     * Send value into generator.
111
     * @param mixed $value
112
     * @NOTE: This method returns nothing,
113
     *        while original generator returns something.
114
     */
115 7
    public function send($value)
116 7
    {
117 7
        $this->validateValidity();
118
        try {
119 7
            $this->g->send($value);
120
        } catch (\RuntimeException $e) {
121
            $this->e = $e;
0 ignored issues
show
Documentation Bug introduced by
It seems like $e of type object<RuntimeException> is incompatible with the declared type object<mpyw\Co\Internal\...\Co\Internal\Exception> of property $e.

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...
122
        }
123 7
    }
124
125
    /**
126
     * Throw exception into generator.
127
     * @param RuntimeException $e
128
     * @NOTE: This method returns nothing,
129
     *        while original generator returns something.
130
     */
131 2
    public function throw_(\RuntimeException $e)
1 ignored issue
show
Unused Code introduced by
The parameter $e is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
132 2
    {
133 2
        $this->validateValidity();
134
        try {
135 2
            $this->g->throw($e);
136 2
        } catch (\RuntimeException $e) {
137 2
            $this->e = $e;
0 ignored issues
show
Documentation Bug introduced by
It seems like $e of type object<RuntimeException> is incompatible with the declared type object<mpyw\Co\Internal\...\Co\Internal\Exception> of property $e.

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...
138
        }
139 2
    }
140
141 3
    public function throwAcceptable()
142 3
    {
143 3
        $this->validateValidity();
144 3
        return $this->g->key() === CoInterface::UNSAFE ||
145 3
               $this->g->key() !== CoInterface::SAFE && $this->options['throw'];
146
    }
147
148
    /**
149
     * Return whether exception is thrown.
150
     * @return bool
151
     */
152 6
    public function thrown()
153 6
    {
154 6
        return $this->e !== null && $this->options['throw'];
155
    }
156
157
    /**
158
     * Return value that generator has returned or thrown.
159
     * @return mixed
160
     */
161 8
    public function getReturnOrThrown()
162 8
    {
163 8
        $this->validateInvalidity();
164 7
        if ($this->e === null && $this->g->valid() && !$this->valid()) {
165 2
            return $this->g->current();
166
        }
167 6
        if ($this->e) {
168 3
            return $this->e;
169
        }
170 3
        return method_exists($this->g, 'getReturn') ? $this->g->getReturn() : null;
171
    }
172
173
    /**
174
     * Validate that generator has finished running.
175
     * @throws LogicException
176
     */
177 7
    private function validateValidity()
178 7
    {
179 7
        if (!$this->valid()) {
180 2
            throw new \LogicException('Unreachable here.');
181
        }
182 7
    }
183
184
    /**
185
     * Validate that generator is still running.
186
     * @throws LogicException
187
     */
188 8
    private function validateInvalidity()
189 8
    {
190 8
        if ($this->valid()) {
191 1
            throw new \LogicException('Unreachable here.');
192
        }
193 7
    }
194
}
195