Passed
Branch master (f3f280)
by Maciej
03:18
created

JavaScript::setupRules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 63
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 38
nc 1
nop 0
dl 0
loc 63
ccs 32
cts 32
cp 1
crap 1
rs 9.312
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Highlighter
5
 *
6
 * Copyright (C) 2016, Some right reserved.
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\Language;
17
18
use Kadet\Highlighter\Matcher\CommentMatcher;
19
use Kadet\Highlighter\Matcher\RegexMatcher;
20
use Kadet\Highlighter\Matcher\SubStringMatcher;
21
use Kadet\Highlighter\Matcher\WordMatcher;
22
use Kadet\Highlighter\Parser\OpenRule;
23
use Kadet\Highlighter\Parser\Rule;
24
use Kadet\Highlighter\Parser\Token\ContextualToken;
25
use Kadet\Highlighter\Parser\Token\MetaToken;
26
use Kadet\Highlighter\Parser\TokenFactory;
27
use Kadet\Highlighter\Parser\Validator\Validator;
28
29
/**
30
 * Class JavaScriptLanguage
31
 *
32
 * @package Kadet\Highlighter\Language
33
 *
34
 * @property bool $variables
35
 */
36
class JavaScript extends GreedyLanguage
37
{
38
    
39
    protected $_options = [
40
        'variables' => false,
41
    ];
42
43
    private const IDENTIFIER = '[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*';
44
45
    /**
46
     * Tokenization rules
47
     */
48 2
    public function setupRules()
49
    {
50
        // we need to allow all the tokens in json
51 2
        $this->rules->validator = new Validator(['*none', '*meta.json', '!comment']);
52
53 2
        $this->rules->addMany([
54 2
            'string' => CommonFeatures::strings(['single' => '\'', 'double' => '"'], [
55 2
                'context' => ['!operator.escape', '!comment', '!string'],
56
            ]),
57
58 2
            'symbol.function' => new Rule(new RegexMatcher('/function\s+([a-z_]\w+)\s*\(/i')),
59
60 2
            'operator.escape' => new Rule(new RegexMatcher('/(\\\(?:x[0-9a-fA-F]{1,2}|u\{[0-9a-fA-F]{1,6}\}|[0-7]{1,3}|.))/i'), [
61 2
                'context' => ['string']
62
            ]),
63
64 2
            'comment' => new Rule(new CommentMatcher(['//'], [['/*', '*/']]), ['priority' => 3]),
65
66 2
            'call' => new Rule(new RegexMatcher('/(' . self::IDENTIFIER . ')\s*\(/iu'), ['priority' => -1]),
67
68 2
            'keyword' => new Rule(new WordMatcher([
69 2
                'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval',
70
                'void', 'with', 'break', 'catch', 'class', 'const', 'super', 'throw',
71
                'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch',
72
                'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger',
73
                'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof', 'get', 'set', 'from'
74 2
            ]), ['context' => ['!string', '!comment', '!symbol', '!call']]),
75
76 2
            'constant.special' => new Rule(new WordMatcher(['null', 'true', 'false'])),
77 2
            'variable.special' => new Rule(new SubStringMatcher('this')),
78
79 2
            'number' => new Rule(new RegexMatcher('/\b(-?(?:0[0-7]+|0[xX][0-9a-fA-F]+|0b[01]+|\d+))\b/')),
80
81 2
            'operator.punctuation' => new Rule(new WordMatcher([',', ';'], ['separated' => false]), ['priority' => 0]),
82 2
            'operator'             => new Rule(new RegexMatcher('/(=>|\+{1,2}|-{1,2}|={1,3}|\|{1,2}|&{1,2})/'), ['priority' => 0]),
83
84
            'string.regex' => [
85 2
                new OpenRule(new RegexMatcher('#(?>[\[=(?:+,!]|^|return|=>|&&|\|\|)\s*(/).*?/#m'), [
86 2
                    'context' => ['!comment', '!string']
87
                ]),
88 2
                new Rule(new RegexMatcher('#\/.*(/[gimuy]{0,5})#m'), [
89 2
                    'priority' => 1,
90 2
                    'factory'  => new TokenFactory(ContextualToken::class),
91
                    'context'  => ['!operator.escape', 'string.regex']
92
                ])
93
            ],
94
95 2
            'variable' => new Rule(new RegexMatcher('/\b(?<!\.)(' . self::IDENTIFIER . ':?)/iu'), [
96 2
                'priority' => -1,
97 2
                'enabled'  => $this->variables
98
            ]),
99
100
            'variable.property' => [
101 2
                new Rule(new RegexMatcher('/(?=[\w)\]]\s*\.([a-z_]\w*))/i'), [
102 2
                    'priority' => -2
103
                ]),
104 2
                new Rule(new RegexMatcher('/(\w+)\s*:/si'), [
105 2
                    'context' => ['meta.json', '!comment', '!string']
106
                ]),
107
            ],
108
109 2
            'meta.json' => new Rule(new RegexMatcher('/(?<=[=(,])\s*(\{(?>[^{}]|(?1))+\})/m'), [
110 2
                'factory' => new TokenFactory(MetaToken::class)
111
            ])
112
        ]);
113 2
    }
114
115 2
    public function getIdentifier()
116
    {
117 2
        return 'javascript';
118
    }
119
120
    public static function getMetadata()
121
    {
122
        return [
123
            'name'      => ['js', 'jscript', 'javascript'],
124
            'mime'      => ['application/javascript', 'application/x-javascript', 'text/x-javascript', 'text/javascript', 'application/json'],
125
            'extension' => ['*.js', '*.jsx'],
126
        ];
127
    }
128
}
129