Completed
Push — master ( c7a3c9...eed046 )
by Alec
16:25
created

BenchmarkFunctionFormatter   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 75
dl 0
loc 181
rs 10
c 0
b 0
f 0
wmc 21

11 Methods

Rating   Name   Duplication   Size   Complexity  
A returnToString() 0 11 2
A extractArgumentsTypes() 0 9 3
A preformatFunction() 0 14 1
A resetEqualReturns() 0 4 1
A formatException() 0 19 2
A noReturnIf() 0 4 1
A getExporter() 0 6 2
A process() 0 12 3
A formatBenchmarkRelative() 0 18 4
A average() 0 8 1
A relativePercent() 0 8 1
1
<?php declare(strict_types=1);
2
3
namespace AlecRabbit\Tools\Formatters;
4
5
use AlecRabbit\Accessories\Pretty;
6
use AlecRabbit\Tools\Formattable;
7
use AlecRabbit\Tools\Formatters\Contracts\BenchmarkFunctionFormatterInterface;
8
use AlecRabbit\Tools\Formatters\Core\Formatter;
9
use AlecRabbit\Tools\Internal\BenchmarkFunction;
10
use AlecRabbit\Tools\Internal\BenchmarkRelative;
11
use SebastianBergmann\Exporter\Exporter;
12
use function AlecRabbit\typeOf;
13
14
class BenchmarkFunctionFormatter extends Formatter implements BenchmarkFunctionFormatterInterface
15
{
16
    /** @var null|Exporter */
17
    protected static $exporter;
18
19
    /** @var bool */
20
    protected $equalReturns = false;
21
22
    /** {@inheritdoc} */
23
    public function resetEqualReturns(): BenchmarkFunctionFormatter
24
    {
25
        return
26
            $this->noReturnIf();
27
    }
28
29
    /** {@inheritdoc} */
30
    public function noReturnIf(bool $equalReturns = false): BenchmarkFunctionFormatter
31
    {
32
        $this->equalReturns = $equalReturns;
33
        return $this;
34
    }
35
36
    /** {@inheritdoc} */
37
    public function process(Formattable $function): string
38
    {
39
        if ($function instanceof BenchmarkFunction) {
40
            return
41
                $this->formatBenchmarkRelative($function) .
42
                (empty($exception = $this->formatException($function)) ?
43
                    PHP_EOL :
44
                    /*static::EXCEPTIONS .*/ $exception . PHP_EOL);
45
        }
46
        $this->wrongFormattableType(BenchmarkFunction::class, $function);
47
        // @codeCoverageIgnoreStart
48
        return ''; // never executes
49
        // @codeCoverageIgnoreEnd
50
    }
51
52
    /**
53
     * @param BenchmarkFunction $function
54
     * @return string
55
     */
56
    protected function formatBenchmarkRelative(BenchmarkFunction $function): string
57
    {
58
        if ($br = $function->getBenchmarkRelative()) {
59
            $argumentsTypes = $this->extractArgumentsTypes($function->getArgs());
60
            $executionReturn = $function->getReturn();
61
            if ($this->equalReturns || $function->isNotShowReturns()) {
62
                return $this->preformatFunction($br, $function, $argumentsTypes);
63
            }
64
            return
65
                sprintf(
66
                    '%s %s %s %s',
67
                    $this->preformatFunction($br, $function, $argumentsTypes),
68
                    PHP_EOL,
69
                    $this->returnToString($executionReturn),
70
                    PHP_EOL
71
                );
72
        }
73
        return '';
74
    }
75
76
    /**
77
     * @param array $arguments
78
     * @return array
79
     */
80
    protected function extractArgumentsTypes(array $arguments): array
81
    {
82
        $types = [];
83
        if (!empty($arguments)) {
84
            foreach ($arguments as $argument) {
85
                $types[] = typeOf($argument);
86
            }
87
        }
88
        return $types;
89
    }
90
91
    /**
92
     * @param BenchmarkRelative $br
93
     * @param BenchmarkFunction $function
94
     * @param array $argumentsTypes
95
     *
96
     * @return string
97
     */
98
    protected function preformatFunction(
99
        BenchmarkRelative $br,
100
        BenchmarkFunction $function,
101
        array $argumentsTypes
102
    ): string {
103
        return
104
            sprintf(
105
                '%s. %s (%s) %s(%s) %s',
106
                (string)$br->getRank(),
107
                $this->average($br->getAverage()),
108
                $this->relativePercent($br->getRelative()),
109
                $function->humanReadableName(),
110
                implode(', ', $argumentsTypes),
111
                $function->comment()
112
            );
113
    }
114
115
    /**
116
     * @param float $average
117
     * @return string
118
     */
119
    protected function average(float $average): string
120
    {
121
        return
122
            str_pad(
123
                Pretty::time($average),
124
                8,
125
                ' ',
126
                STR_PAD_LEFT
127
            );
128
    }
129
130
    /**
131
     * @param float $relative
132
     * @param string $prefix
133
     * @return string
134
     */
135
    protected function relativePercent(float $relative, string $prefix = ' '): string
136
    {
137
        return
138
            str_pad(
139
                $prefix . Pretty::percent($relative),
140
                9,
141
                ' ',
142
                STR_PAD_LEFT
143
            );
144
    }
145
146
    /** {@inheritdoc} */
147
    public function returnToString($executionReturn): string
148
    {
149
        $type = typeOf($executionReturn);
150
        $str = static::getExporter()->export($executionReturn);
151
        return
152
            'array' === $type ?
153
                $str :
154
                sprintf(
155
                    '%s(%s)',
156
                    $type,
157
                    $str
158
                );
159
    }
160
161
    /**
162
     * @return Exporter
163
     */
164
    protected static function getExporter(): Exporter
165
    {
166
        if (null === static::$exporter) {
167
            static::$exporter = new Exporter();
168
        }
169
        return static::$exporter;
170
    }
171
172
    /**
173
     * @param BenchmarkFunction $function
174
     * @return string
175
     */
176
    protected function formatException(BenchmarkFunction $function): string
177
    {
178
179
        if ($e = $function->getException()) {
180
            $argumentsTypes = $this->extractArgumentsTypes($function->getArgs());
181
182
            return
183
                sprintf(
184
                    '%s(%s) %s [%s: %s] %s',
185
                    $function->humanReadableName(),
186
                    implode(', ', $argumentsTypes),
187
                    $function->comment(),
188
                    typeOf($e),
189
                    $e->getMessage(),
190
                    PHP_EOL
191
                );
192
        }
193
194
        return '';
195
    }
196
}
197