Passed
Branch fuck-54 (18c095)
by Kacper
03:37
created

Token::__construct()   C

Complexity

Conditions 7
Paths 64

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 7

Importance

Changes 7
Bugs 3 Features 0
Metric Value
c 7
b 3
f 0
dl 0
loc 30
ccs 22
cts 22
cp 1
rs 6.7272
cc 7
eloc 16
nc 64
nop 1
crap 7
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2015, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\Parser;
17
18
19
use Kadet\Highlighter\Language\Language;
20
use Kadet\Highlighter\Utils\Helper;
21
use Kadet\Highlighter\Utils\StringHelper;
22
23
class Token
24
{
25
    const NAME = null;
26
27
    protected static $_id = 0;
28
29
    public $pos;
30
    public $name;
31
    public $index = 1;
32
33
    /**
34
     * @var Token
35
     */
36
    protected $_end;
37
38
    /**
39
     * @var Token
40
     */
41
    protected $_start;
42
43
    /** @var Rule */
44
    protected $_rule;
45
46
    protected $_valid;
47
    protected $_length;
48
49
    public $id;
50
51
    /**
52
     * Token constructor.
53
     *
54
     * @param array $options
55
     */
56 49
    public function __construct(array $options)
57
    {
58 49
        if (isset($options[0])) {
59 37
            $this->name = $options[0];
60 37
        }
61
62 49
        if (isset($options['pos'])) {
63 46
            $this->pos = $options['pos'];
64 46
        }
65
66 49
        if (isset($options['index'])) {
67 6
            $this->index = $options['index'];
68 6
        }
69
70 49
        if (isset($options['start'])) {
71 2
            $this->setStart($options['start']);
72 2
        }
73
74 49
        if (isset($options['rule'])) {
75 18
            $this->setRule($options['rule']);
76 18
        } else {
77 32
            $this->setRule(new Rule());
78
        }
79
80 49
        if (isset($options['end'])) {
81 39
            $this->setEnd($options['end']);
82 39
        }
83
84 49
        $this->id = ++self::$_id;
85 49
    }
86
87 13
    public static function compare(Token $a, Token $b)
88
    {
89 13
        $multiplier = $a->isEnd() ? -1 : 1;
90
91 13
        if (($a->isStart() && $b->isEnd()) || ($a->isEnd() && $b->isStart())) {
92 1
            if($a->getEnd() == $b) {
93
                return -1;
94 1
            } elseif($a->getStart() == $b) {
95 1
                return 1;
96
            } else {
97 1
                return $multiplier;
98
            }
99 12
        } elseif (($rule = Helper::cmp($b->_rule->priority, $a->_rule->priority)) !== 0) {
100 10
            return $multiplier*$rule;
101 5
        } elseif (($rule = Helper::cmp($b->index, $a->index)) !== 0) {
102 1
            return $multiplier*$rule;
103
        } else {
104 4
            return $multiplier*($a->id < $b->id ? -1 : 1);
105
        }
106
    }
107
108 33
    public function isStart()
109
    {
110 33
        return $this->_start === null;
111
    }
112
113 31
    public function isEnd()
114
    {
115 31
        return $this->_end === null;
116
    }
117
118 15
    public function isValid(Language $language, $context = null)
119
    {
120 15
        if ($this->_valid === null) {
121 14
            $this->validate($language, $context);
122 14
        }
123
124 15
        return $this->_valid;
125
    }
126
127 11
    protected function validate(Language $language, $context)
128
    {
129 11
        $this->setValid(
130 11
            $language === $this->_rule->language &&
131 11
            $this->_rule->validateContext($context, $this->isEnd() ? [$this->name => Rule::CONTEXT_IN] : [])
132 11
        );
133 11
    }
134
135 14
    public function setValid($valid = true)
136
    {
137 14
        $this->_valid = $valid;
138
139 14
        if ($this->_end) {
140 11
            $this->_end->_valid = $this->_valid;
141 14
        } elseif ($this->_start) {
142 12
            $this->_start->_valid = $this->_valid;
143 12
        }
144 14
    }
145
146
    /**
147
     * @return mixed
148
     */
149 27
    public function getStart()
150
    {
151 27
        return $this->_start;
152
    }
153
154
    /**
155
     * @param Token|null|false $start
156
     */
157 3
    public function setStart($start = null)
158
    {
159 3
        $this->_end = null;
160 3
        $this->_start = $start;
0 ignored issues
show
Documentation Bug introduced by
It seems like $start can also be of type false. However, the property $_start is declared as type object<Kadet\Highlighter\Parser\Token>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
161
162 3
        if ($start instanceof Token) {
163 2
            $start->_end = $this;
164 2
        }
165 3
    }
166
167
    /**
168
     * @return Token|null
169
     */
170 37
    public function getEnd()
171
    {
172 37
        return $this->_end;
173
    }
174
175
    /**
176
     * @param Token|null|false $end
177
     */
178 39
    public function setEnd($end = null)
179
    {
180 39
        $this->_start = null;
181 39
        $this->_end = $end;
0 ignored issues
show
Documentation Bug introduced by
It seems like $end can also be of type false. However, the property $_end is declared as type object<Kadet\Highlighter\Parser\Token>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
182 39
        $this->_length = null;
183
184 39
        if ($end instanceof Token) {
185 39
            $end->_start = $this;
186 39
        }
187 39
    }
188
189
    /**
190
     * @return Rule
191
     */
192 15
    public function getRule()
193
    {
194 15
        return $this->_rule;
195
    }
196
197
    /**
198
     * @param Rule $rule
199
     */
200 49
    public function setRule(Rule $rule)
201
    {
202 49
        $this->_rule = $rule;
203 49
    }
204
205 2
    public function getLength()
206
    {
207 2
        if ($this->_length === null) {
208 2
            $this->_length = $this->_end === null ? 0 : $this->_end->pos - $this->pos;
209 2
        }
210
211 2
        return $this->_length;
212
    }
213
214
    /**
215
     * @codeCoverageIgnore
216
     */
217
    public function dump($text = null)
218
    {
219
        $pos = StringHelper::positionToLine($text, $this->pos);
220
        $pos = $pos['line'] . ':' . $pos['pos'];
221
222
        if ($this->isStart()) {
223
            $result = "Start ({$this->name}) $pos";
224
            if ($text !== null && $this->_end !== null) {
225
                $result .= "  \x02" . substr($text, $this->pos, $this->_end->pos - $this->pos) . "\x03";
226
            }
227
        } else {
228
            $result = "End ({$this->name}) $pos";
229
        }
230
231
        return $result;
232
    }
233
}