Completed
Push — master ( f9a123...73c14a )
by Alec
18:36
created

BenchmarkFunctionFormatter::average()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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