Passed
Branch symfony-console (b1e45d)
by Kacper
03:35
created

VerboseOutput::tokenize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 13
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 0
dl 13
loc 13
rs 9.4285
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2016, 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\bin;
17
18
19
use Kadet\Highlighter\Formatter\DebugFormatter;
20
use Kadet\Highlighter\Formatter\FormatterInterface;
21
use Kadet\Highlighter\Language\Language;
22
use Kadet\Highlighter\Parser\Tokens;
23
use Symfony\Component\Console\Input\InputInterface;
24
use Symfony\Component\Console\Output\OutputInterface;
25
26
class VerboseOutput
27
{
28
    /** @var OutputInterface */
29
    private $_output;
30
    /** @var InputInterface */
31
    private $_input;
32
33
    private $_source;
34
    /** @var Language */
35
    private $_language;
36
37
    private $_counts = ['before' => null, 'after' => null];
38
    private $_times  = ['tokenization' => null, 'parsing' => null, 'formatting' => null];
39
40
    /** @var DebugFormatter */
41
    private $_debug;
42
43
    /**
44
     * VerboseOutput constructor.
45
     *
46
     * @param OutputInterface    $output
47
     * @param InputInterface     $input
48
     * @param Language           $language
49
     * @param FormatterInterface $formatter
50
     * @param                    $source
51
     */
52
    public function __construct(
53
        OutputInterface $output, InputInterface $input, Language $language, FormatterInterface $formatter, $source
54
    ) {
55
        $this->_output = $output;
56
        $this->_input  = $input;
57
58
        $this->_source    = $source;
59
        $this->_debug     = new DebugFormatter();
60
        $this->_formatter = $formatter;
0 ignored issues
show
Bug introduced by
The property _formatter does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
61
62
        $this->_language = $language;
63
    }
64
65
    public function process()
66
    {
67
        $tokenized = $this->tokenize();
68
        $parsed    = $this->parse($tokenized);
69
        $formatted = $this->format($parsed);
70
71
        if($this->wants('time')) {
72
            $this->_output->writeln(sprintf(
73
                '<info>Overall:</info> %.4fs, %s chars/s',
74
                array_sum($this->_times), number_format(strlen($this->_source) / array_sum($this->_times))
75
            ));
76
        }
77
78
        if($this->wants('detailed-time')) {
79
            $this->_slashed('Times             [s]', array_map(function($t) {
80
                return number_format($t, 5);
81
            }, $this->_times));
82
            $this->_slashed('Performance [chars/s]', array_map(function($t) {
83
                return number_format(strlen($this->_source) / $t);
84
            }, $this->_times));
85
        }
86
87
        if($this->wants('count')) {
88
            $this->_slashed('Token count', array_map('number_format', $this->_counts));
89
        }
90
91
        if($this->wants('density')) {
92
            $this->_slashed('Token density [tokens/kB]', array_map(function($c) {
93
                return number_format($c / strlen($this->_source) * 1024, 1);
94
            }, $this->_counts));
95
        }
96
97
        return $formatted;
98
    }
99
100
    public function wants($feature)
101
    {
102
        return in_array($feature, $this->_input->getOption('debug'));
103
    }
104
105 View Code Duplication
    protected function tokenize()
106
    {
107
        $tokens = $this->benchmark(function () {
108
            return $this->_language->tokenize($this->_source);
109
        }, $this->_times['tokenization']);
110
111
        $this->_counts['before'] = count($tokens);
112
        if ($this->wants('tree-before')) {
113
            $this->_tree($tokens, 'before parsing', false);
114
        }
115
116
        return $tokens;
117
    }
118
119
    protected function benchmark(callable $callable, &$time = null)
120
    {
121
        $start  = microtime(true);
122
        $return = $callable();
123
        $time   = microtime(true) - $start;
124
125
        return $return;
126
    }
127
128
    private function _tree(Tokens $tree, $message, $indented = true)
129
    {
130
        $this->_output->writeln("Token tree <comment>$message</comment>: ");
131
        $this->_output->writeln($this->_debug->format(clone $tree, $indented));
132
    }
133
134 View Code Duplication
    protected function parse(Tokens $tokens)
135
    {
136
        $tokens = $this->benchmark(function () use ($tokens) {
137
            return $this->_language->parse($tokens);
0 ignored issues
show
Documentation introduced by
$tokens is of type object<Kadet\Highlighter\Parser\Tokens>, but the function expects a object<Kadet\Highlighter...enIterator>|string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
138
        }, $this->_times['parsing']);
139
140
        $this->_counts['after'] = count($tokens);
141
        if ($this->wants('tree-after')) {
142
            $this->_tree($tokens, 'after parsing', true);
143
        }
144
145
        return $tokens;
146
    }
147
148
    protected function format(Tokens $tokens)
149
    {
150
        return $this->benchmark(function () use ($tokens) {
151
            return $this->_formatter->format($tokens);
152
        }, $this->_times['formatting']);
153
    }
154
155
    private function _slashed($message, $data)
156
    {
157
        $this->_output->writeln(sprintf(
158
            "$message %s: %s",
159
            implode(' / ', array_map(function ($f) {
160
                return "<comment>{$f}</comment>";
161
            }, array_keys($data))),
162
            implode(' / ', array_map(function ($f) {
163
                return "<info>{$f}</info>";
164
            }, array_values($data)))
165
        ));
166
    }
167
}
168