Passed
Push — master ( eb8fe1...f9b36a )
by Maxim
03:07
created

CommentLexer::addSlashes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
ccs 0
cts 7
cp 0
crap 2
rs 9.4285
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 = '{^((accessi|(writ|read)a)ble|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 = '{^((?(1)\s*(&&|\|\|)\s*)(\d+(,\d+)?\.\.\d+(,\d+)?|((<|>|!|=)=|%|<|>)\s+\d+(,\d+)?|`([^`]|\\\\`)+((?<!\\\\)`)))+}';
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
    public function getClassData(): ClassData
56
    {
57
        $classData = new ClassData($this->reflection);
58
        for ($i = $this->startLine; $this->isLineEmpty() && $i <= $this->endLine; ++$i) {
59
            $this->readLine();
60
            if (!$this->isAxsPropertyDef()) {
61
                continue;
62
            }
63
            $injProcessor = new InjectedStringParser($this->getAxsComment());
64
            $code = $injProcessor->addSlashes('\\');
65
            $propertyData = new PropertyData(
66
                $this->reflection->getProperty($this->getPropertyName()),
67
                $this->parse(
68
                    $code,
69
                    self::TOKEN_LIST,
70
                    self::REQUIRED_TOKENS
71
                )
72
            );
73
            $classData->addProperty($this->getPropertyName(), $propertyData);
74
        }
75
        return $classData;
76
    }
77
78
    /**
79
     * Extracts Axessors comment from the code.
80
     * 
81
     * @return string Axessors comment
82
     */
83
    private function getAxsComment(): string
84
    {
85
        return substr($this->currentLine, strpos($this->currentLine, self::AXS_COMMENT_TOKEN));
86
    }
87
88
    /**
89
     * Extracts property name from the code.
90
     * 
91
     * @return string property name
92
     */
93
    private function getPropertyName(): string
94
    {
95
        preg_match('{\$[a-zA-Z_][a-zA-Z0-9_]*}', $this->currentLine, $property);
96
        return substr($property[0], 1);
97
    }
98
99
    /**
100
     * Checks if the code given is Axessors property definition. 
101
     * 
102
     * @return bool result of the checkout
103
     */
104
    private function isAxsPropertyDef(): bool
105
    {
106
        return (bool)preg_match('{^\s*(public|private|protected)\s+(static\s+)?\$[a-zA-Z_][a-zA-Z0-9_]*.*?;\s+#>}',
107
            $this->currentLine);
108
    }
109
}
110