Completed
Push — master ( 137204...824e9d )
by Alec
08:58
created

BenchmarkFunctionFormatter   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Test Coverage

Coverage 98.67%

Importance

Changes 0
Metric Value
eloc 72
dl 0
loc 176
ccs 74
cts 75
cp 0.9867
rs 10
c 0
b 0
f 0
wmc 21

11 Methods

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