You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.2 KiB
125 lines
3.2 KiB
<?php declare(strict_types=1); |
|
/* |
|
* This file is part of sebastian/code-unit-reverse-lookup. |
|
* |
|
* (c) Sebastian Bergmann <sebastian@phpunit.de> |
|
* |
|
* For the full copyright and license information, please view the LICENSE |
|
* file that was distributed with this source code. |
|
*/ |
|
namespace SebastianBergmann\CodeUnitReverseLookup; |
|
|
|
use function array_merge; |
|
use function assert; |
|
use function get_declared_classes; |
|
use function get_declared_traits; |
|
use function get_defined_functions; |
|
use function is_array; |
|
use function range; |
|
use ReflectionClass; |
|
use ReflectionFunction; |
|
use ReflectionFunctionAbstract; |
|
use ReflectionMethod; |
|
|
|
/** |
|
* @since Class available since Release 1.0.0 |
|
*/ |
|
class Wizard |
|
{ |
|
/** |
|
* @var array |
|
*/ |
|
private $lookupTable = []; |
|
|
|
/** |
|
* @var array |
|
*/ |
|
private $processedClasses = []; |
|
|
|
/** |
|
* @var array |
|
*/ |
|
private $processedFunctions = []; |
|
|
|
/** |
|
* @param string $filename |
|
* @param int $lineNumber |
|
* |
|
* @return string |
|
*/ |
|
public function lookup($filename, $lineNumber) |
|
{ |
|
if (!isset($this->lookupTable[$filename][$lineNumber])) { |
|
$this->updateLookupTable(); |
|
} |
|
|
|
if (isset($this->lookupTable[$filename][$lineNumber])) { |
|
return $this->lookupTable[$filename][$lineNumber]; |
|
} |
|
|
|
return $filename . ':' . $lineNumber; |
|
} |
|
|
|
private function updateLookupTable(): void |
|
{ |
|
$this->processClassesAndTraits(); |
|
$this->processFunctions(); |
|
} |
|
|
|
private function processClassesAndTraits(): void |
|
{ |
|
$classes = get_declared_classes(); |
|
$traits = get_declared_traits(); |
|
|
|
assert(is_array($classes)); |
|
assert(is_array($traits)); |
|
|
|
foreach (array_merge($classes, $traits) as $classOrTrait) { |
|
if (isset($this->processedClasses[$classOrTrait])) { |
|
continue; |
|
} |
|
|
|
$reflector = new ReflectionClass($classOrTrait); |
|
|
|
foreach ($reflector->getMethods() as $method) { |
|
$this->processFunctionOrMethod($method); |
|
} |
|
|
|
$this->processedClasses[$classOrTrait] = true; |
|
} |
|
} |
|
|
|
private function processFunctions(): void |
|
{ |
|
foreach (get_defined_functions()['user'] as $function) { |
|
if (isset($this->processedFunctions[$function])) { |
|
continue; |
|
} |
|
|
|
$this->processFunctionOrMethod(new ReflectionFunction($function)); |
|
|
|
$this->processedFunctions[$function] = true; |
|
} |
|
} |
|
|
|
private function processFunctionOrMethod(ReflectionFunctionAbstract $functionOrMethod): void |
|
{ |
|
if ($functionOrMethod->isInternal()) { |
|
return; |
|
} |
|
|
|
$name = $functionOrMethod->getName(); |
|
|
|
if ($functionOrMethod instanceof ReflectionMethod) { |
|
$name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name; |
|
} |
|
|
|
if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) { |
|
$this->lookupTable[$functionOrMethod->getFileName()] = []; |
|
} |
|
|
|
foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) { |
|
$this->lookupTable[$functionOrMethod->getFileName()][$line] = $name; |
|
} |
|
} |
|
}
|
|
|