lithium\analysis\Inspector::executable()
Gets the executable lines of a class, by examining the start and end lines of each method.
Parameters
-
mixed
$class
Class name as a string or object instance.
-
array
$options
Set of options:
'self'
boolean: Iftrue
(default), only returns lines of methods defined in$class
, excluding methods from inherited classes.'methods'
array: An arbitrary list of methods to search, as a string (single method name) or array of method names.'filter'
boolean: Iftrue
, filters out lines containing only whitespace or braces. Note: for some reason, the Zend engine does not reportswitch
andtry
statements as executable lines, as well as parts of multi-line assignment statements, so they are filtered out as well.
Returns
arrayReturns an array of the executable line numbers of the class.
Source
public static function executable($class, array $options = []) {
$defaults = [
'self' => true,
'filter' => true,
'methods' => [],
'empty' => [' ', "\t", '}', ')', ';'],
'pattern' => null,
'blockOpeners' => ['switch (', 'try {', '} else {', 'do {', '} while']
];
$options += $defaults;
if (empty($options['pattern']) && $options['filter']) {
$pattern = str_replace(' ', '\s*', join('|', array_map(
function($str) { return preg_quote($str, '/'); },
$options['blockOpeners']
)));
$pattern = join('|', [
"({$pattern})",
"\\$(.+)\($",
"\s*['\"]\w+['\"]\s*=>\s*.+[\{\(]$",
"\s*['\"]\w+['\"]\s*=>\s*['\"]*.+['\"]*\s*"
]);
$options['pattern'] = "/^({$pattern})/";
}
if (!$class instanceof ReflectionClass) {
$class = new ReflectionClass(is_object($class) ? get_class($class) : $class);
}
$options += ['group' => false];
$result = array_filter(static::methods($class, 'ranges', $options));
if ($options['filter'] && $class->getFileName() && $result) {
$lines = static::lines($class->getFileName(), $result);
$start = key($lines);
$code = implode("\n", $lines);
$tokens = token_get_all('<' . '?php' . $code);
$tmp = [];
foreach ($tokens as $token) {
if (is_array($token)) {
if (!in_array($token[0], [T_COMMENT, T_DOC_COMMENT, T_WHITESPACE])) {
$tmp[] = $token[2];
}
}
}
$filteredLines = array_values(array_map(
function($ln) use ($start) { return $ln + $start - 1; },
array_unique($tmp))
);
$lines = array_intersect_key($lines, array_flip($filteredLines));
$result = array_keys(array_filter($lines, function($line) use ($options) {
$line = trim($line);
$empty = preg_match($options['pattern'], $line);
return $empty ? false : (str_replace($options['empty'], '', $line) !== '');
}));
}
return $result;
}