Failed Conditions
Pull Request — new-parser-ast-metadata (#5)
by
unknown
02:14
created

MetadataCollector   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Test Coverage

Coverage 72.15%

Importance

Changes 0
Metric Value
wmc 24
eloc 48
dl 0
loc 178
ccs 57
cts 79
cp 0.7215
rs 10
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$0 ➔ visitConstantFetch() 0 3 1
A __construct() 0 8 1
A hp$0 ➔ visitMapCollection() 0 4 2
A filldMissingMetadata() 0 13 3
A hp$0 ➔ visitBooleanScalar() 0 2 1
A hp$0 ➔ visitNamedParameter() 0 4 1
A collect() 0 7 1
A hp$0 ➔ visitReference() 0 3 1
A hp$0 ➔ visitIntegerScalar() 0 2 1
A hp$0 ➔ visitNullScalar() 0 2 1
A hp$0 ➔ __construct() 0 11 1
A hp$0 ➔ visitPair() 0 4 1
A hp$0 ➔ visitAnnotations() 0 4 2
A hp$0 ➔ visitParameters() 0 4 2
A hp$0 ➔ visitIdentifier() 0 2 1
A hp$0 ➔ visitListCollection() 0 4 2
A hp$0 ➔ visitUnnamedParameter() 0 3 1
A hp$0 ➔ visitFloatScalar() 0 2 1
A hp$0 ➔ visitClassConstantFetch() 0 4 1
A hp$0 ➔ visitAnnotation() 0 10 2
createInternalVisitor() 0 132 ?
A hp$0 ➔ visitStringScalar() 0 2 1
B hp$0 ➔ createInternalVisitor() 0 132 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Annotations\Metadata;
6
7
use Doctrine\Annotations\Assembler\Acceptor\ReferenceAcceptor;
8
use Doctrine\Annotations\Metadata\Assembler\AnnotationMetadataAssembler;
9
use Doctrine\Annotations\Parser\Ast\Annotation;
10
use Doctrine\Annotations\Parser\Ast\Annotations;
11
use Doctrine\Annotations\Parser\Ast\ClassConstantFetch;
12
use Doctrine\Annotations\Parser\Ast\Collection\ListCollection;
13
use Doctrine\Annotations\Parser\Ast\Collection\MapCollection;
14
use Doctrine\Annotations\Parser\Ast\ConstantFetch;
15
use Doctrine\Annotations\Parser\Ast\Pair;
16
use Doctrine\Annotations\Parser\Ast\Parameter\NamedParameter;
17
use Doctrine\Annotations\Parser\Ast\Parameter\UnnamedParameter;
18
use Doctrine\Annotations\Parser\Ast\Parameters;
19
use Doctrine\Annotations\Parser\Ast\Reference;
20
use Doctrine\Annotations\Parser\Ast\Scalar\BooleanScalar;
21
use Doctrine\Annotations\Parser\Ast\Scalar\FloatScalar;
22
use Doctrine\Annotations\Parser\Ast\Scalar\Identifier;
23
use Doctrine\Annotations\Parser\Ast\Scalar\IntegerScalar;
24
use Doctrine\Annotations\Parser\Ast\Scalar\NullScalar;
25
use Doctrine\Annotations\Parser\Ast\Scalar\StringScalar;
26
use Doctrine\Annotations\Parser\Reference\ReferenceResolver;
27
use Doctrine\Annotations\Parser\Scope;
28
use Doctrine\Annotations\Parser\Visitor\Visitor;
29
use SplObjectStorage;
30
use SplStack;
31
32
final class MetadataCollector
33
{
34
    /** @var AnnotationMetadataAssembler */
35
    private $assembler;
36
37
    /** @var ReferenceAcceptor */
38
    private $referenceAcceptor;
39
40
    /** @var ReferenceResolver */
41
    private $referenceResolver;
42
43 31
    public function __construct(
44
        AnnotationMetadataAssembler $assembler,
45
        ReferenceAcceptor $referenceAcceptor,
46
        ReferenceResolver $referenceResolver
47
    ) {
48 31
        $this->assembler         = $assembler;
49 31
        $this->referenceAcceptor = $referenceAcceptor;
50 31
        $this->referenceResolver = $referenceResolver;
51 31
    }
52
53 28
    public function collect(Annotations $node, Scope $scope, MetadataCollection $metadataCollection) : void
54
    {
55 28
        $storage = new SplObjectStorage();
56
57 28
        $node->dispatch($this->createInternalVisitor($storage, $scope));
58
59 28
        $this->filldMissingMetadata($metadataCollection, $scope, ...$storage);
60 23
    }
61
62 28
    private function filldMissingMetadata(
63
        MetadataCollection $metadataCollection,
64
        Scope $scope,
65
        Reference ...$references
66
    ) : void {
67 28
        foreach ($references as $reference) {
68 27
            $name = $this->referenceResolver->resolve($reference, $scope);
69
70 27
            if (isset($metadataCollection[$name])) {
71
                continue;
72
            }
73
74 27
            $metadataCollection[] = $this->assembler->assemble($reference, $scope);
75
        }
76 23
    }
77
78
    private function createInternalVisitor(SplObjectStorage $storage, Scope $scope) : Visitor
79
    {
80
        return new class ($this->assembler, $this->referenceAcceptor, $scope, $storage) implements Visitor
81
        {
82
            /** @var AnnotationMetadataAssembler */
83
            private $assembler;
84
85
            /** @var ReferenceAcceptor */
86
            private $referenceAcceptor;
87
88
            /** @var Scope */
89
            private $scope;
90
91
            /** @var SplObjectStorage<AnnotationMetadata> */
92
            private $storage;
93
94
            /** @var SplStack<mixed> */
95
            private $stack;
96
97 28
            public function __construct(
98
                AnnotationMetadataAssembler $assembler,
99
                ReferenceAcceptor $referenceAcceptor,
100
                Scope $scope,
101
                SplObjectStorage $storage
102
            ) {
103 28
                $this->assembler         = $assembler;
104 28
                $this->referenceAcceptor = $referenceAcceptor;
105 28
                $this->scope             = $scope;
106 28
                $this->storage           = $storage;
107 28
                $this->stack             = new SplStack();
108 28
            }
109
110 28
            public function visitAnnotations(Annotations $annotations) : void
111
            {
112 28
                foreach ($annotations as $annotation) {
113 28
                    $annotation->dispatch($this);
114
                }
115 28
            }
116
117 28
            public function visitAnnotation(Annotation $annotation) : void
118
            {
119 28
                if (! $this->referenceAcceptor->accepts($annotation->getName(), $this->scope)) {
120 3
                    return;
121
                }
122
123 27
                $annotation->getParameters()->dispatch($this);
124 27
                $annotation->getName()->dispatch($this);
125
126 27
                $this->storage->attach($this->stack->pop());
127 27
            }
128
129 27
            public function visitReference(Reference $reference) : void
130
            {
131 27
                $this->stack->push($reference);
132 27
            }
133
134 27
            public function visitParameters(Parameters $parameters) : void
135
            {
136 27
                foreach ($parameters as $parameter) {
137 20
                    $parameter->dispatch($this);
138
                }
139 27
            }
140
141 9
            public function visitNamedParameter(NamedParameter $parameter) : void
142
            {
143 9
                $parameter->getValue()->dispatch($this);
144 9
                $parameter->getName()->dispatch($this);
145 9
            }
146
147 11
            public function visitUnnamedParameter(UnnamedParameter $parameter) : void
148
            {
149 11
                $parameter->getValue()->dispatch($this);
150 11
            }
151
152
            public function visitListCollection(ListCollection $listCollection) : void
153
            {
154
                foreach ($listCollection as $item) {
155
                    $item->dispatch($this);
156
                }
157
            }
158
159
            public function visitMapCollection(MapCollection $mapCollection) : void
160
            {
161
                foreach ($mapCollection as $item) {
162
                    $item->dispatch($this);
163
                }
164
            }
165
166
            public function visitPair(Pair $pair) : void
167
            {
168
                $pair->getValue()->dispatch($this);
169
                $pair->getKey()->dispatch($this);
170
            }
171
172 10
            public function visitIdentifier(Identifier $identifier) : void
173
            {
174
                // leaf - no dispatch
175 10
            }
176
177
            public function visitConstantFetch(ConstantFetch $constantFetch) : void
178
            {
179
                $constantFetch->getName()->dispatch($this);
180
            }
181
182 1
            public function visitClassConstantFetch(ClassConstantFetch $classConstantFetch) : void
183
            {
184 1
                $classConstantFetch->getName()->dispatch($this);
185 1
                $classConstantFetch->getClass()->dispatch($this);
186 1
            }
187
188
            public function visitNullScalar(NullScalar $nullScalar) : void
189
            {
190
                // leaf - no dispatch
191
            }
192
193
            public function visitBooleanScalar(BooleanScalar $booleanScalar) : void
194
            {
195
                // leaf - no dispatch
196
            }
197
198 2
            public function visitIntegerScalar(IntegerScalar $integerScalar) : void
199
            {
200
                // leaf - no dispatch
201 2
            }
202
203
            public function visitFloatScalar(FloatScalar $floatScalar) : void
204
            {
205
                // leaf - no dispatch
206
            }
207
208 14
            public function visitStringScalar(StringScalar $stringScalar) : void
209
            {
210
                // leaf - no dispatch
211 14
            }
212
        };
213
    }
214
}
215