Failed Conditions
Pull Request — new-parser-ast-metadata (#4)
by Michael
05:13 queued 03:35
created

Assembler.php$0 ➔ visitParameters()   A

Complexity

Conditions 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.8333
c 0
b 0
f 0
cc 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Annotations\Assembler;
6
7
use Doctrine\Annotations\Assembler\Acceptor\ReferenceAcceptor;
8
use Doctrine\Annotations\Assembler\Constant\ConstantResolver;
9
use Doctrine\Annotations\Constructor\Constructor;
10
use Doctrine\Annotations\Metadata\MetadataCollection;
11
use Doctrine\Annotations\Metadata\Reflection\ClassReflectionProvider;
12
use Doctrine\Annotations\Parser\Ast\Annotation;
13
use Doctrine\Annotations\Parser\Ast\Annotations;
14
use Doctrine\Annotations\Parser\Ast\ClassConstantFetch;
15
use Doctrine\Annotations\Parser\Ast\Collection\ListCollection;
16
use Doctrine\Annotations\Parser\Ast\Collection\MapCollection;
17
use Doctrine\Annotations\Parser\Ast\ConstantFetch;
18
use Doctrine\Annotations\Parser\Ast\Pair;
19
use Doctrine\Annotations\Parser\Ast\Parameter\NamedParameter;
20
use Doctrine\Annotations\Parser\Ast\Parameter\UnnamedParameter;
21
use Doctrine\Annotations\Parser\Ast\Parameters;
22
use Doctrine\Annotations\Parser\Ast\Reference;
23
use Doctrine\Annotations\Parser\Ast\Scalar\BooleanScalar;
24
use Doctrine\Annotations\Parser\Ast\Scalar\FloatScalar;
25
use Doctrine\Annotations\Parser\Ast\Scalar\Identifier;
26
use Doctrine\Annotations\Parser\Ast\Scalar\IntegerScalar;
27
use Doctrine\Annotations\Parser\Ast\Scalar\NullScalar;
28
use Doctrine\Annotations\Parser\Ast\Scalar\StringScalar;
29
use Doctrine\Annotations\Parser\Reference\ReferenceResolver;
30
use Doctrine\Annotations\Parser\Scope;
31
use Doctrine\Annotations\Parser\Visitor\Visitor;
32
use SplObjectStorage;
33
use SplStack;
34
use function array_key_exists;
35
use function assert;
36
use function constant;
37
use function strtolower;
38
39
final class Assembler
40
{
41
    /** @var MetadataCollection */
42
    private $metadataCollection;
43
44
    /** @var ReferenceResolver */
45
    private $referenceResolver;
46
47
    /** @var Constructor */
48
    private $constructor;
49
50
    /** @var ClassReflectionProvider */
51
    private $classReflectionProvider;
52
53
    /** @var ReferenceAcceptor */
54
    private $referenceAcceptor;
55
56
    /** @var ConstantResolver */
57
    private $constantResolver;
58
59 9
    public function __construct(
60
        MetadataCollection $metadataCollection,
61
        ReferenceResolver $referenceResolver,
62
        Constructor $constructor,
63
        ClassReflectionProvider $classReflectionProvider,
64
        ReferenceAcceptor $referenceAcceptor,
65
        ConstantResolver $constantResolver
66
    ) {
67 9
        $this->metadataCollection      = $metadataCollection;
68 9
        $this->referenceResolver       = $referenceResolver;
69 9
        $this->constructor             = $constructor;
70 9
        $this->classReflectionProvider = $classReflectionProvider;
71 9
        $this->referenceAcceptor       = $referenceAcceptor;
72 9
        $this->constantResolver        = $constantResolver;
73 9
    }
74
75
    /**
76
     * @return object[]
77
     */
78 9
    public function collect(Annotations $node, Scope $scope) : iterable
79
    {
80 9
        $storage = new SplObjectStorage();
81
82 9
        $node->dispatch($this->createInternalVisitor($storage, $scope));
83
84 9
        return yield from $storage;
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type array<mixed,object>.
Loading history...
85
    }
86
87
    private function createInternalVisitor(SplObjectStorage $storage, Scope $scope) : Visitor
88
    {
89
        return new class (
90
            $this->metadataCollection,
91
            $this->referenceResolver,
92
            $this->constructor,
93
            $this->classReflectionProvider,
94
            $this->referenceAcceptor,
95
            $this->constantResolver,
96
            $scope,
97
            $storage
98
        ) implements Visitor {
99
            /** @var MetadataCollection */
100
            private $metadataCollection;
101
102
            /** @var ReferenceResolver */
103
            private $referenceResolver;
104
105
            /** @var Constructor */
106
            private $constructor;
107
108
            /** @var ClassReflectionProvider */
109
            private $classReflectionProvider;
110
111
            /** @var ReferenceAcceptor */
112
            private $referenceAcceptor;
113
114
            /** @var ConstantResolver */
115
            private $constantResolver;
116
117
            /** @var Scope */
118
            private $scope;
119
120
            /** @var SplObjectStorage<object> */
121
            private $storage;
122
123
            /** @var SplStack<mixed> */
124
            private $stack;
125
126 9
            public function __construct(
127
                MetadataCollection $metadataCollection,
128
                ReferenceResolver $referenceResolver,
129
                Constructor $constructor,
130
                ClassReflectionProvider $classReflectionProvider,
131
                ReferenceAcceptor $referenceAcceptor,
132
                ConstantResolver $constantResolver,
133
                Scope $scope,
134
                SplObjectStorage $storage
135
            ) {
136 9
                $this->metadataCollection      = $metadataCollection;
137 9
                $this->referenceResolver       = $referenceResolver;
138 9
                $this->constructor             = $constructor;
139 9
                $this->classReflectionProvider = $classReflectionProvider;
140 9
                $this->referenceAcceptor       = $referenceAcceptor;
141 9
                $this->constantResolver        = $constantResolver;
142 9
                $this->scope                   = $scope;
143 9
                $this->storage                 = $storage;
144 9
                $this->stack                   = new SplStack();
145 9
            }
146
147 9
            public function visitAnnotations(Annotations $annotations) : void
148
            {
149 9
                foreach ($annotations as $annotation) {
150 9
                    $stackSize = $this->stack->count();
151
152 9
                    $annotation->dispatch($this);
153
154 9
                    if ($this->stack->count() === $stackSize) {
155 5
                        continue;
156
                    }
157
158 9
                    $this->storage->attach($this->stack->pop());
159
                }
160
161 9
                assert($this->stack->isEmpty());
162 9
            }
163
164 9
            public function visitAnnotation(Annotation $annotation) : void
165
            {
166 9
                if (! $this->referenceAcceptor->accepts($annotation->getName(), $this->scope)) {
167 5
                    return;
168
                }
169
170 9
                $this->scope->increaseNestingLevel();
171
172 9
                $annotation->getParameters()->dispatch($this);
173 9
                $annotation->getName()->dispatch($this);
174
175 9
                $this->stack->push(
176 9
                    $this->constructor->construct(
177 9
                        $this->metadataCollection[$this->stack->pop()],
178 9
                        $this->scope,
179 9
                        $this->stack->pop()
180
                    )
181
                );
182
183 9
                $this->scope->decreaseNestingLevel();
184 9
            }
185
186 9
            public function visitReference(Reference $reference) : void
187
            {
188 9
                $this->stack->push($this->referenceResolver->resolve($reference, $this->scope));
189 9
            }
190
191 9
            public function visitParameters(Parameters $parameters) : void
192
            {
193 9
                $new = [];
194
195 9
                foreach ($parameters as $parameter) {
196 9
                    $parameter->dispatch($this);
197
198 9
                    assert(! array_key_exists($this->stack->current(), $new));
199
200 9
                    $new[$this->stack->pop()] = $this->stack->pop();
201
                }
202
203 9
                $this->stack->push($new);
204 9
            }
205
206 6
            public function visitUnnamedParameter(UnnamedParameter $parameter) : void
207
            {
208 6
                $parameter->getValue()->dispatch($this);
209
210 6
                $this->stack->push($this->stack->pop());
211 6
                $this->stack->push(null);
212 6
            }
213
214 4
            public function visitNamedParameter(NamedParameter $parameter) : void
215
            {
216 4
                $parameter->getValue()->dispatch($this);
217 4
                $parameter->getName()->dispatch($this);
218
                // pass through
219 4
            }
220
221 4
            public function visitIdentifier(Identifier $identifier) : void
222
            {
223 4
                $this->stack->push($identifier->getValue());
224 4
            }
225
226 1
            public function visitPair(Pair $pair) : void
227
            {
228 1
                $pair->getValue()->dispatch($this);
229 1
                $pair->getKey()->dispatch($this);
230
                // pass through
231 1
            }
232
233 1
            public function visitBooleanScalar(BooleanScalar $booleanScalar) : void
234
            {
235 1
                $this->stack->push($booleanScalar->getValue());
236 1
            }
237
238 3
            public function visitIntegerScalar(IntegerScalar $integerScalar) : void
239
            {
240 3
                $this->stack->push($integerScalar->getValue());
241 3
            }
242
243 1
            public function visitFloatScalar(FloatScalar $floatScalar) : void
244
            {
245 1
                $this->stack->push($floatScalar->getValue());
246 1
            }
247
248 7
            public function visitStringScalar(StringScalar $stringScalar) : void
249
            {
250 7
                $this->stack->push($stringScalar->getValue());
251 7
            }
252
253 1
            public function visitNullScalar(NullScalar $nullScalar) : void
254
            {
255 1
                $this->stack->push($nullScalar->getValue());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $nullScalar->getValue() targeting Doctrine\Annotations\Par...\NullScalar::getValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
256 1
            }
257
258 3
            public function visitListCollection(ListCollection $listCollection) : void
259
            {
260 3
                $list = [];
261
262 3
                foreach ($listCollection as $listItem) {
263 3
                    $listItem->dispatch($this);
264
265 3
                    $list[] = $this->stack->pop();
266
                }
267
268 3
                $this->stack->push($list);
269 3
            }
270
271 1
            public function visitMapCollection(MapCollection $mapCollection) : void
272
            {
273 1
                $map = [];
274
275 1
                foreach ($mapCollection as $mapItem) {
276 1
                    $mapItem->dispatch($this);
277 1
                    $map[$this->stack->pop()] = $this->stack->pop();
278
                }
279
280 1
                $this->stack->push($map);
281 1
            }
282
283
            public function visitConstantFetch(ConstantFetch $constantFetch) : void
284
            {
285
                $constantFetch->getName()->dispatch($this);
286
287
                $constantName = $this->stack->pop();
288
289
                $this->stack->push($this->constantResolver->resolveStandaloneConstant($constantName));
290
            }
291
292 1
            public function visitClassConstantFetch(ClassConstantFetch $classConstantFetch) : void
293
            {
294 1
                $classConstantFetch->getName()->dispatch($this);
295 1
                $classConstantFetch->getClass()->dispatch($this);
296
297 1
                $className    = $this->stack->pop();
298 1
                $constantName = $this->stack->pop();
299
300 1
                if (strtolower($constantName) === 'class') {
301
                    $this->stack->push($className);
302
                    return;
303
                }
304
305 1
                $this->stack->push($this->constantResolver->resolveClassOrInterfaceConstant($className, $constantName));
306 1
            }
307
        };
308
    }
309
}
310