CommentLexer::getClassData()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 3
nop 0
dl 0
loc 19
ccs 15
cts 15
cp 1
crap 5
rs 9.4888
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is a part of "Axessors" library.
4
 *
5
 * @author <[email protected]>
6
 * @license GPL
7
 */
8
9
namespace NoOne4rever\Axessors;
10
11
/**
12
 * Class CommentLexer.
13
 *
14
 * Splits Axessors comment into array of possible tokens.
15
 *
16
 * @package NoOne4rever\Axessors
17
 */
18
class CommentLexer extends Lexer
19
{
20
    private const AXS_COMMENT = '#:';
21
    private const ACCESS_MODIFIER = '[+\-~]';
22
    private const KEYWORD = '(accessible|writable|readable|axs|wrt|rdb)';
23
    private const TYPE = '((((\\\\)?[a-zA-Z_][a-zA-Z\d_]*(\\\\[a-zA-Z_][a-zA-Z\d_]*)*)(\[(?1)\])?)(\|(?2))*)';
24
    private const HANDLERS = '((?(1),\s*)([a-zA-Z_][a-zA-Z0-9_]*|`([^`]|\\\\`)+((?<!\\\\)`)))+';
25
    private const CONDITIONS = '((((([<>])=?|([!=])=)\s*\d+|\d+\.\.\d+|`[^`]+`)|\((?1)\))((\s*(&&|\|\|)\s*)(?1))*)';
26
    private const HANDLERS_SIGN = '->';
27
    private const ALIAS_SIGN = '=>';
28
    private const ALIAS = '[a-zA-Z_][a-zA-Z0-9_]*';
29
30
    private const TOKEN_LIST = [
31
        self::AXS_COMMENT,
32
        self::ACCESS_MODIFIER,
33
        self::KEYWORD,
34
        self::TYPE,
35
        self::CONDITIONS,
36
        self::HANDLERS_SIGN,
37
        self::HANDLERS,
38
        self::ACCESS_MODIFIER,
39
        self::KEYWORD,
40
        self::CONDITIONS,
41
        self::HANDLERS_SIGN,
42
        self::HANDLERS,
43
        self::ALIAS_SIGN,
44
        self::ALIAS
45
    ];
46
    private const REQUIRED_TOKENS = [0, 1, 2];
47
48
    private const AXS_COMMENT_TOKEN = '#:';
49
50
    /**
51
     * Returns class' data with Axessors properties.
52
     *
53
     * @return ClassData class' data
54
     */
55 5
    public function getClassData(): ClassData
56
    {
57 5
        $classData = new ClassData($this->reflection);
58 5
        for ($i = $this->startLine; $this->isLineEmpty() && $i <= $this->endLine; ++$i) {
59 5
            $this->readLine();
60 5
            if (!$this->isAxsPropertyDef()) {
61 5
                continue;
62
            }
63 5
            $injProcessor = new InjectedStringSuit($this->getAxsComment());
64 5
            $code = $injProcessor->addSlashes('\\')->get();
65 5
            $properties = $this->getProperties();
66 5
            $tokenList = $this->getTokenList(count($properties));
67 5
            $tokens = $this->parse($code, $tokenList, self::REQUIRED_TOKENS);
68 5
            foreach ($this->getProperties() as $propertyName) {
69 5
                $propertyData = new PropertyData($this->reflection->getProperty($propertyName), $tokens);
70 2
                $classData->addProperty($propertyName, $propertyData);
71
            }
72
        }
73 2
        return $classData;
74
    }
75
76
    /**
77
     * Returns dynamically created array of token signatures.
78
     *
79
     * @param int $properties number of properties 
80
     * 
81
     * @return array tokens
82
     */
83 5
    private function getTokenList(int $properties): array 
84
    {
85 5
        if ($properties == 1) {
86 5
            return self::TOKEN_LIST;
87
        } else {
88 2
            return array_slice(self::TOKEN_LIST, 0, count(self::TOKEN_LIST) - 2);
89
        }
90
    }
91
92
    /**
93
     * Extracts Axessors comment from the code.
94
     *
95
     * @return string Axessors comment
96
     */
97 5
    private function getAxsComment(): string
98
    {
99 5
        return substr($this->currentLine, strpos($this->currentLine, self::AXS_COMMENT_TOKEN));
100
    }
101
102
    /**
103
     * Extracts property name from the code.
104
     *
105
     * @return string[] property name
106
     */
107 5
    private function getProperties(): array
108
    {
109 5
        $line = substr($this->currentLine, 0, strpos($this->currentLine, self::AXS_COMMENT_TOKEN));
110 5
        preg_match_all('/(?<=\$)[a-z_][a-z\d_]*/i', $line, $properties);
111 5
        return $properties[0];
112
    }
113
114
    /**
115
     * Checks if the code given is Axessors property definition.
116
     *
117
     * @return bool result of the checkout
118
     */
119 5
    private function isAxsPropertyDef(): bool
120
    {
121 5
        return (bool)preg_match('/\s*(public|protected|private)(\s*static)?\s+((?(3),)\s*\$[a-z_][a-z\d_]*)+.*?;\s*#:.+/i',
122 5
            $this->currentLine);
123
    }
124
}
125