• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jojo1981 / json-ast-builder / 17578687754

09 Sep 2025 09:48AM UTC coverage: 35.019%. Remained the same
17578687754

push

github

jojo1981
Fix: Make compatible with PHP versions: ^8.0|^8.1|^8.2|^8.3|^8.4. Closes #1
https://github.com/jojo1981/json-ast-builder/issues/1

161 of 407 new or added lines in 17 files covered. (39.56%)

290 existing lines in 25 files now uncovered.

374 of 1068 relevant lines covered (35.02%)

3.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Visitor/AnalyzerVisitor.php
1
<?php
2
/*
3
 * This file is part of the jojo1981/json-ast-builder package
4
 *
5
 * Copyright (c) 2019 Joost Nijhuis <jnijhuis81@gmail.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed in the root of the source code
9
 */
10
declare(strict_types=1);
11

12
namespace Jojo1981\JsonAstBuilder\Visitor;
13

14
use Jojo1981\JsonAstBuilder\Ast\ArrayNode;
15
use Jojo1981\JsonAstBuilder\Ast\BooleanNode;
16
use Jojo1981\JsonAstBuilder\Ast\ElementNode;
17
use Jojo1981\JsonAstBuilder\Ast\IntegerNode;
18
use Jojo1981\JsonAstBuilder\Ast\JsonNode;
19
use Jojo1981\JsonAstBuilder\Ast\KeyNode;
20
use Jojo1981\JsonAstBuilder\Ast\MemberNode;
21
use Jojo1981\JsonAstBuilder\Ast\NodeInterface;
22
use Jojo1981\JsonAstBuilder\Ast\NullNode;
23
use Jojo1981\JsonAstBuilder\Ast\NumberNode;
24
use Jojo1981\JsonAstBuilder\Ast\ObjectNode;
25
use Jojo1981\JsonAstBuilder\Ast\StringNode;
26
use Jojo1981\JsonAstBuilder\Ast\ValueNode;
27
use function array_filter;
28
use function array_key_exists;
29
use function array_keys;
30
use function array_pop;
31
use function array_sum;
32
use function count;
33
use function end;
34
use function explode;
35
use function get_class;
36
use function max;
37

38
/**
39
 * @package Jojo1981\JsonAstBuilder\Visitor
40
 */
41
final class AnalyzerVisitor implements VisitorInterface
42
{
43
    /** @var int */
44
    private int $level = 0;
45

46
    /** @var int[] */
47
    private array $levelCounts = [];
48

49
    /** @var int[] */
50
    private array $nodeTypeCounts = [];
51

52
    /** @var string[] */
53
    private array $parents = [];
54

55
    /**
56
     * @param JsonNode $jsonNode
57
     * @return array
58
     */
59
    public function visitJsonNode(JsonNode $jsonNode): array
60
    {
UNCOV
61
        $nodeTree = [];
×
UNCOV
62
        $this->pushNode($jsonNode);
×
UNCOV
63
        $nodeTree['JsonNode'] = $jsonNode->getElement()->accept($this);
×
UNCOV
64
        $this->popNode();
×
65

NEW
66
        $maxLevel = count($this->levelCounts);
×
NEW
67
        $nodeCount = array_sum($this->levelCounts);
×
NEW
68
        $maxSiblings = max($this->levelCounts);
×
NEW
69
        $levelsWithMaxSiblings = array_keys(array_filter(
×
UNCOV
70
            $this->levelCounts,
×
UNCOV
71
            static function (int $count) use ($maxSiblings): bool {
×
72
                return $count === $maxSiblings;
×
73
            }
×
74
        ));
×
75

UNCOV
76
        return [
×
77
            'maxLevel' => $maxLevel,
×
78
            'nodeCount' => $nodeCount,
×
79
            'maxSiblings' => $maxSiblings,
×
80
            'levelsWithMaxSiblings' => $levelsWithMaxSiblings,
×
81
            'averageSiblings' => $nodeCount / $maxLevel,
×
82
            'nodeTree' => $nodeTree
×
83
        ];
×
84
    }
85

86
    /**
87
     * @param NodeInterface $node
88
     * @return void
89
     */
90
    private function pushNode(NodeInterface $node): void
91
    {
NEW
92
        $this->level++;
×
NEW
93
        if (!array_key_exists($this->level, $this->levelCounts)) {
×
NEW
94
            $this->levelCounts[$this->level] = 0;
×
95
        }
NEW
96
        $this->levelCounts[$this->level]++;
×
NEW
97
        $nodeName = $this->incrementNodeCount($node);
×
98

NEW
99
        $this->parents[] = $nodeName;
×
100
    }
101

102
    /**
103
     * @param NodeInterface $node
104
     * @return string
105
     */
106
    private function incrementNodeCount(NodeInterface $node): string
107
    {
NEW
108
        $nodeName = $this->getNodeNameFromNode($node);
×
NEW
109
        if (!array_key_exists($nodeName, $this->nodeTypeCounts)) {
×
NEW
110
            $this->nodeTypeCounts[$nodeName] = 0;
×
111
        }
112

NEW
113
        return $nodeName . ++$this->nodeTypeCounts[$nodeName];
×
114
    }
115

116
    /**
117
     * @param NodeInterface $node
118
     * @return string
119
     */
120
    private function getNodeNameFromNode(NodeInterface $node): string
121
    {
NEW
122
        $parts = explode('\\', get_class($node));
×
123

NEW
124
        return end($parts);
×
125
    }
126

127
    /**
128
     * @return void
129
     */
130
    private function popNode(): void
131
    {
NEW
132
        $this->level--;
×
NEW
133
        array_pop($this->parents);
×
134
    }
135

136
    /**
137
     * @param ElementNode $elementNode
138
     * @return array
139
     */
140
    public function visitElementNode(ElementNode $elementNode): array
141
    {
142
        $result = [];
×
143
        $this->pushNode($elementNode);
×
144
        $result['ElementNode'] = $elementNode->getValue()->accept($this);
×
UNCOV
145
        $this->popNode();
×
146

UNCOV
147
        return $result;
×
148
    }
149

150
    /**
151
     * @param ValueNode $valueNode
152
     * @return array
153
     */
154
    public function visitValueNode(ValueNode $valueNode): array
155
    {
UNCOV
156
        $result = [];
×
157
        $this->pushNode($valueNode);
×
158
        $result['ValueNode'] = $valueNode->getType()->accept($this);
×
UNCOV
159
        $this->popNode();
×
160

UNCOV
161
        return $result;
×
162
    }
163

164
    /**
165
     * @param ObjectNode $objectNode
166
     * @return array
167
     */
168
    public function visitObjectNode(ObjectNode $objectNode): array
169
    {
170
        $result = [];
×
171

UNCOV
172
        $this->pushNode($objectNode);
×
UNCOV
173
        foreach ($objectNode->getMembers() as $memberNode) {
×
174
            $result[] = $memberNode->accept($this);
×
175
        }
UNCOV
176
        $this->popNode();
×
177

UNCOV
178
        return [
×
UNCOV
179
            'ObjectNode' => $result
×
UNCOV
180
        ];
×
181
    }
182

183
    /**
184
     * @param MemberNode $memberNode
185
     * @return array
186
     */
187
    public function visitMemberNode(MemberNode $memberNode): array
188
    {
UNCOV
189
        $this->pushNode($memberNode);
×
UNCOV
190
        $result = [
×
UNCOV
191
            $memberNode->getKey()->accept($this),
×
UNCOV
192
            $memberNode->getValue()->accept($this)
×
193
        ];
×
194
        $this->popNode();
×
195

UNCOV
196
        return [
×
UNCOV
197
            'MemberNode' => $result
×
UNCOV
198
        ];
×
199
    }
200

201
    /**
202
     * @param ArrayNode $arrayNode
203
     * @return array
204
     */
205
    public function visitArrayNode(ArrayNode $arrayNode): array
206
    {
UNCOV
207
        $this->pushNode($arrayNode);
×
208
        $result = [];
×
UNCOV
209
        foreach ($arrayNode->getElements() as $elementNode) {
×
UNCOV
210
            $result[] = $elementNode->accept($this);
×
211
        }
UNCOV
212
        $this->popNode();
×
213

UNCOV
214
        return [
×
UNCOV
215
            'ArrayNode' => $result
×
UNCOV
216
        ];
×
217
    }
218

219
    /**
220
     * @param StringNode $stringNode
221
     * @return string
222
     */
223
    public function visitStringNode(StringNode $stringNode): string
224
    {
UNCOV
225
        $this->pushNode($stringNode);
×
UNCOV
226
        $this->popNode();
×
227

UNCOV
228
        return 'StringNode';
×
229
    }
230

231
    /**
232
     * @param NumberNode $numberNode
233
     * @return string
234
     */
235
    public function visitNumberNode(NumberNode $numberNode): string
236
    {
237
        $this->pushNode($numberNode);
×
UNCOV
238
        $this->popNode();
×
239

240
        return 'NumberNode';
×
241
    }
242

243
    /**
244
     * @param IntegerNode $integerNode
245
     * @return string
246
     */
247
    public function visitIntegerNode(IntegerNode $integerNode): string
248
    {
UNCOV
249
        $this->pushNode($integerNode);
×
250
        $this->popNode();
×
251

252
        return 'IntegerNode';
×
253
    }
254

255
    /**
256
     * @param BooleanNode $booleanNode
257
     * @return string
258
     */
259
    public function visitBooleanNode(BooleanNode $booleanNode): string
260
    {
UNCOV
261
        $this->pushNode($booleanNode);
×
UNCOV
262
        $this->popNode();
×
263

UNCOV
264
        return 'BooleanNode';
×
265
    }
266

267
    /**
268
     * @param NullNode $nullNode
269
     * @return string
270
     */
271
    public function visitNullNode(NullNode $nullNode): string
272
    {
273
        $this->pushNode($nullNode);
×
UNCOV
274
        $this->popNode();
×
275

276
        return 'NullNode';
×
277
    }
278

279
    /**
280
     * @param KeyNode $keyNode
281
     * @return string
282
     */
283
    public function visitKeyNode(KeyNode $keyNode): string
284
    {
UNCOV
285
        $this->pushNode($keyNode);
×
286
        $this->popNode();
×
287

UNCOV
288
        return 'KeyNode';
×
289
    }
290
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc