Skip to content

Commit 30e9e6a

Browse files
committed
Profiler v2
1 parent eed3764 commit 30e9e6a

File tree

2 files changed

+47
-105
lines changed

2 files changed

+47
-105
lines changed

src/SimpleProfiler/Profiler.php

Lines changed: 42 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -218,121 +218,63 @@ public static function loadFile($filename, $inject_profiler = true) {
218218
eval($file);
219219
}
220220

221-
/**
222-
* @param $source
223-
* @return string
224-
*/
225-
public static function injectProfilerToCode($source) {
226-
$function_positions = self::getFunctionPositions($source);
227-
foreach ($function_positions as $pos) {
228-
$source = self::injectProfilerByFunctionPosition($source, $pos);
229-
}
230-
return $source;
231-
}
232-
233221
/**
234222
* @param string $source
235-
* @param int $pos
236223
* @return string
237224
*/
238-
protected static function injectProfilerByFunctionPosition($source, $pos) {
239-
$info = self::getFunctionInfo($source, $pos);
240-
241-
if ($info['name']) {
242-
$name = '__METHOD__';
243-
} else {
244-
$name = '__METHOD__ . \'#' . base_convert($pos, 10, 36) . '\'';
245-
}
246-
247-
$offset = $info['body_pos'];
248-
$source = substr($source, 0, $offset + 1)
249-
. '$SimpleProfilerTimer = new \SimpleProfiler\Timer(\'Profiler.\' . ' . $name . ');'
250-
. substr($source, $offset + 1);
251-
252-
return $source;
253-
}
254-
255-
/**
256-
* @param string $source
257-
* @param int $pos
258-
* @return array
259-
*/
260-
protected static function getFunctionInfo($source, $pos) {
261-
$params_pos = strpos($source, '(', $pos);
262-
$name = substr($source, $pos + 8, $params_pos - $pos - 8);
263-
264-
$stack = ['('];
265-
$i = $params_pos;
266-
while (isset($source[++$i])) {
267-
268-
$chr = $source[$i];
269-
$last = $stack[count($stack) - 1];
270-
271-
if ($chr === '\'' && $last === '\'' && $source[$i - 1] !== '\\') {
272-
array_pop($stack);
273-
continue;
274-
}
225+
public static function injectProfilerToCode($source) {
226+
$tokens = token_get_all($source);
227+
$code = '';
275228

276-
if ($chr === '"' && $last === '"' && $source[$i - 1] !== '\\') {
277-
array_pop($stack);
278-
continue;
279-
}
229+
$function_found = false;
230+
$function_name = null;
231+
$stack = [];
280232

281-
if ($last === '\'' || $last === '"') {
282-
continue;
233+
foreach ($tokens as $i => $token) {
234+
if (is_string($token)) {
235+
$id = null;
236+
$text = $token;
237+
} else {
238+
list($id, $text) = $token;
283239
}
240+
$code .= $text;
284241

285-
if ($chr === '\'' || $chr === '"') {
286-
array_push($stack, $chr);
242+
if ($id === T_FUNCTION) {
243+
$function_found = true;
244+
$function_name = null;
245+
$stack = [];
287246
continue;
288247
}
289248

290-
if ($last === '(' && $chr === ')') {
291-
array_pop($stack);
292-
if (!$stack) {
293-
$i++;
294-
break;
249+
if ($function_found) {
250+
if ($id === T_STRING && !$stack) {
251+
$function_name = $text;
252+
continue;
295253
}
296-
}
297254

298-
if ($chr === '(') {
299-
array_push($stack, $chr);
300-
}
301-
}
302-
303-
$func_body = strpos($source, '{', $i);
304-
305-
return [
306-
'name' => trim($name),
307-
'body_pos' => $func_body,
308-
];
309-
}
310-
311-
/**
312-
* @param string $source
313-
* @return int[]
314-
*/
315-
protected static function getFunctionPositions($source) {
316-
$function_positions = [];
317-
$code = '';
318-
$tokens = token_get_all($source);
319-
320-
foreach ($tokens as $token) {
321-
if (is_string($token)) {
322-
$code .= $token;
323-
continue;
324-
}
325-
list($id, $text) = $token;
326-
if ($id === T_FUNCTION) {
327-
$function_positions[] = strlen($code);
255+
if (!isset($id)) {
256+
if ($text === '(') {
257+
$stack[] = '(';
258+
continue;
259+
}
260+
if ($text === ')') {
261+
array_pop($stack);
262+
continue;
263+
}
264+
if ($text === '{' && !$stack) {
265+
$function_found = false;
266+
if ($function_name) {
267+
$name = '__METHOD__';
268+
} else {
269+
$name = '__METHOD__ . \'_' . base_convert($i, 10, 36) . '\'';
270+
}
271+
$code .= '$SimpleProfilerTimer = new \SimpleProfiler\Timer(\'Profiler.\' . ' . $name . ');';
272+
continue;
273+
}
274+
}
328275
}
329-
$code .= $text;
330-
}
331276

332-
if (count($function_positions) > 1) {
333-
krsort($function_positions);
334277
}
335-
336-
return $function_positions;
278+
return $code;
337279
}
338280
}

tests/Unit/ProfilerTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public function testInjectProfilerToCode() {
119119

120120
$expect =<<<'EXPECT'
121121
<?php
122-
namespace SimpleProfiler\Tests; $foo = function() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__ . '#1a'); return 'foo'; }; $foo(); function bar() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return 'bar'; } bar(); class TestClass { public static function getSomeData() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return 'some data'; } public static function get_random_int ($min = 0, $max = 100) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return mt_rand($min, $max); } public static function __strange__name__ ($_a = 'Alexander') {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $_a; } public static function multi_line_name ( $a, $b, $c ) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $a . $b . $c; } public static function anonymous() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); $get42 = function() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__ . '#du'); return 42; }; return $get42(); } public static function sleep() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); usleep(100); } public static function withParams($function = null) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $function; } public static function withParams2($a = 'function', $b = '){', $c = '{}') {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $a; } }
122+
namespace SimpleProfiler\Tests; $foo = function() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__ . '_h'); return 'foo'; }; $foo(); function bar() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return 'bar'; } bar(); class TestClass { public static function getSomeData() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return 'some data'; } public static function get_random_int ($min = 0, $max = 100) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return mt_rand($min, $max); } public static function __strange__name__ ($_a = 'Alexander') {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $_a; } public static function multi_line_name ( $a, $b, $c ) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $a . $b . $c; } public static function anonymous() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); $get42 = function() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__ . '_5h'); return 42; }; return $get42(); } public static function sleep() {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); usleep(100); } public static function withParams($function = null) {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $function; } public static function withParams2($a = 'function', $b = '){', $c = '{}') {$SimpleProfilerTimer = new \SimpleProfiler\Timer('Profiler.' . __METHOD__); return $a; } }
123123
EXPECT;
124124

125125
$this->assertSame($expect, $result);
@@ -142,20 +142,20 @@ public function testProfilerCode() {
142142

143143
$this->assertSame(
144144
[
145-
'SimpleProfiler\Tests\{closure}#1a',
145+
'SimpleProfiler\Tests\{closure}_h',
146146
'SimpleProfiler\Tests\bar',
147147
'SimpleProfiler\Tests\TestClass::anonymous',
148-
'SimpleProfiler\Tests\TestClass::SimpleProfiler\Tests\{closure}#du',
148+
'SimpleProfiler\Tests\TestClass::SimpleProfiler\Tests\{closure}_5h',
149149
'SimpleProfiler\Tests\TestClass::sleep',
150150
'SimpleProfiler\Tests\TestClass::get_random_int',
151151
],
152152
array_keys($data['Profiler'])
153153
);
154154

155-
$this->assertSame(1, $data['Profiler']['SimpleProfiler\Tests\{closure}#1a']['count']);
155+
$this->assertSame(1, $data['Profiler']['SimpleProfiler\Tests\{closure}_h']['count']);
156156
$this->assertSame(1, $data['Profiler']['SimpleProfiler\Tests\bar']['count']);
157157
$this->assertSame(10, $data['Profiler']['SimpleProfiler\Tests\TestClass::anonymous']['count']);
158-
$this->assertSame(10, $data['Profiler']['SimpleProfiler\Tests\TestClass::SimpleProfiler\Tests\{closure}#du']['count']);
158+
$this->assertSame(10, $data['Profiler']['SimpleProfiler\Tests\TestClass::SimpleProfiler\Tests\{closure}_5h']['count']);
159159
$this->assertSame(1, $data['Profiler']['SimpleProfiler\Tests\TestClass::sleep']['count']);
160160
$this->assertSame(2, $data['Profiler']['SimpleProfiler\Tests\TestClass::get_random_int']['count']);
161161
}

0 commit comments

Comments
 (0)