PhpdocParser::joinMultilineNotations()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0092

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
nc 4
nop 1
dl 0
loc 21
ccs 11
cts 12
cp 0.9167
crap 4.0092
rs 9.8666
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jasny\PhpdocParser;
6
7
use Jasny\PhpdocParser\TagInterface;
8
use Jasny\PhpdocParser\TagSet;
9
10
/**
11
 * Class PhpdocParser
12
 */
13
class PhpdocParser
14
{
15
    /**
16
     * @var TagSet|TagInterface[]
17
     */
18
    protected $tags;
19
20
    /**
21
     * PhpdocParser constructor.
22
     *
23
     * @param TagSet|TagInterface[] $tags
24
     */
25 9
    public function __construct(TagSet $tags)
26
    {
27 9
        $this->tags = $tags;
28
    }
29
30
    /**
31
     * Parse a PHP doc comment
32
     *
33
     * @param string $doc
34
     * @param callable $callback
35
     * @return array
36
     */
37 9
    public function parse(string $doc, ?callable $callback = null): array
38
    {
39 9
        $notations = [];
40 9
        $rawNotations = $this->extractNotations($doc);
41 9
        $rawNotations = $this->joinMultilineNotations($rawNotations);
42
43 9
        foreach ($rawNotations as $item) {
44 8
            if (!isset($this->tags[$item['tag']])) {
45 2
                continue;
46
            }
47
48 7
            $notations = $this->tags[$item['tag']]->process($notations, $item['value'] ?? '');
49
        }
50
51 9
        if (isset($this->tags['summery'])) {
52 1
            $notations = $this->tags['summery']->process($notations, $doc);
53
        }
54
55 9
        if ($callback !== null) {
56 1
            $notations = $callback($notations);
57
        }
58
59 9
        return $notations;
60
    }
61
62
63
    /**
64
     * Extract notation from doc comment
65
     *
66
     * @param string $doc
67
     * @return array
68
     */
69 9
    protected function extractNotations(string $doc): array
70
    {
71 9
        $matches = null;
72
73 9
        $tag = '\s*@(?<tag>\S+)(?:\h+(?<value>\S.*?)|\h*)';
74 9
        $tagContinue = '(?:\040){2}(?<multiline_value>\S.*?)';
75 9
        $regex = '/^\s*(?:(?:\/\*)?\*)?(?:' . $tag . '|' . $tagContinue . ')(?:\s*\*\*\/)?\r?$/m';
76
77 9
        return preg_match_all($regex, $doc, $matches, PREG_SET_ORDER) ? $matches : [];
78
    }
79
80
    /**
81
     * Join multiline notations
82
     *
83
     * @param array $rawNotations
84
     * @return array
85
     */
86 9
    protected function joinMultilineNotations(array $rawNotations): array
87
    {
88 9
        $result = [];
89 9
        $tagsNotations = $this->filterTagsNotations($rawNotations);
90
91 9
        foreach ($tagsNotations as $item) {
92 8
            if ($item['tag'] !== '') {
93 8
                $result[] = $item;
94
            } else {
95 1
                $lastIdx = count($result) - 1;
96
97 1
                if (!isset($result[$lastIdx]['value'])) {
98
                    $result[$lastIdx]['value'] = '';
99
                }
100
101 1
                $result[$lastIdx]['value'] = trim($result[$lastIdx]['value'])
102 1
                    . ' ' . trim($item['multiline_value']);
103
            }
104
        }
105
106 9
        return $result;
107
    }
108
109
    /**
110
     * Remove everything that goes before tags
111
     *
112
     * @param array $rawNotations
113
     * @return array
114
     */
115 9
    protected function filterTagsNotations(array $rawNotations): array
116
    {
117 9
        for ($i = 0; $i < count($rawNotations); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
118 8
            if ($rawNotations[$i]['tag'] !== '') {
119 8
                return array_slice($rawNotations, $i);
120
            }
121
        }
122
123 1
        return [];
124
    }
125
}
126