Chris@14
|
1 <?php
|
Chris@14
|
2 /*
|
Chris@14
|
3 * This file is part of code-unit-reverse-lookup.
|
Chris@14
|
4 *
|
Chris@14
|
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
|
Chris@14
|
6 *
|
Chris@14
|
7 * For the full copyright and license information, please view the LICENSE
|
Chris@14
|
8 * file that was distributed with this source code.
|
Chris@14
|
9 */
|
Chris@14
|
10
|
Chris@14
|
11 namespace SebastianBergmann\CodeUnitReverseLookup;
|
Chris@14
|
12
|
Chris@14
|
13 /**
|
Chris@14
|
14 * @since Class available since Release 1.0.0
|
Chris@14
|
15 */
|
Chris@14
|
16 class Wizard
|
Chris@14
|
17 {
|
Chris@14
|
18 /**
|
Chris@14
|
19 * @var array
|
Chris@14
|
20 */
|
Chris@14
|
21 private $lookupTable = [];
|
Chris@14
|
22
|
Chris@14
|
23 /**
|
Chris@14
|
24 * @var array
|
Chris@14
|
25 */
|
Chris@14
|
26 private $processedClasses = [];
|
Chris@14
|
27
|
Chris@14
|
28 /**
|
Chris@14
|
29 * @var array
|
Chris@14
|
30 */
|
Chris@14
|
31 private $processedFunctions = [];
|
Chris@14
|
32
|
Chris@14
|
33 /**
|
Chris@14
|
34 * @param string $filename
|
Chris@14
|
35 * @param int $lineNumber
|
Chris@14
|
36 *
|
Chris@14
|
37 * @return string
|
Chris@14
|
38 */
|
Chris@14
|
39 public function lookup($filename, $lineNumber)
|
Chris@14
|
40 {
|
Chris@14
|
41 if (!isset($this->lookupTable[$filename][$lineNumber])) {
|
Chris@14
|
42 $this->updateLookupTable();
|
Chris@14
|
43 }
|
Chris@14
|
44
|
Chris@14
|
45 if (isset($this->lookupTable[$filename][$lineNumber])) {
|
Chris@14
|
46 return $this->lookupTable[$filename][$lineNumber];
|
Chris@14
|
47 } else {
|
Chris@14
|
48 return $filename . ':' . $lineNumber;
|
Chris@14
|
49 }
|
Chris@14
|
50 }
|
Chris@14
|
51
|
Chris@14
|
52 private function updateLookupTable()
|
Chris@14
|
53 {
|
Chris@14
|
54 $this->processClassesAndTraits();
|
Chris@14
|
55 $this->processFunctions();
|
Chris@14
|
56 }
|
Chris@14
|
57
|
Chris@14
|
58 private function processClassesAndTraits()
|
Chris@14
|
59 {
|
Chris@14
|
60 foreach (array_merge(get_declared_classes(), get_declared_traits()) as $classOrTrait) {
|
Chris@14
|
61 if (isset($this->processedClasses[$classOrTrait])) {
|
Chris@14
|
62 continue;
|
Chris@14
|
63 }
|
Chris@14
|
64
|
Chris@14
|
65 $reflector = new \ReflectionClass($classOrTrait);
|
Chris@14
|
66
|
Chris@14
|
67 foreach ($reflector->getMethods() as $method) {
|
Chris@14
|
68 $this->processFunctionOrMethod($method);
|
Chris@14
|
69 }
|
Chris@14
|
70
|
Chris@14
|
71 $this->processedClasses[$classOrTrait] = true;
|
Chris@14
|
72 }
|
Chris@14
|
73 }
|
Chris@14
|
74
|
Chris@14
|
75 private function processFunctions()
|
Chris@14
|
76 {
|
Chris@14
|
77 foreach (get_defined_functions()['user'] as $function) {
|
Chris@14
|
78 if (isset($this->processedFunctions[$function])) {
|
Chris@14
|
79 continue;
|
Chris@14
|
80 }
|
Chris@14
|
81
|
Chris@14
|
82 $this->processFunctionOrMethod(new \ReflectionFunction($function));
|
Chris@14
|
83
|
Chris@14
|
84 $this->processedFunctions[$function] = true;
|
Chris@14
|
85 }
|
Chris@14
|
86 }
|
Chris@14
|
87
|
Chris@14
|
88 /**
|
Chris@14
|
89 * @param \ReflectionFunctionAbstract $functionOrMethod
|
Chris@14
|
90 */
|
Chris@14
|
91 private function processFunctionOrMethod(\ReflectionFunctionAbstract $functionOrMethod)
|
Chris@14
|
92 {
|
Chris@14
|
93 if ($functionOrMethod->isInternal()) {
|
Chris@14
|
94 return;
|
Chris@14
|
95 }
|
Chris@14
|
96
|
Chris@14
|
97 $name = $functionOrMethod->getName();
|
Chris@14
|
98
|
Chris@14
|
99 if ($functionOrMethod instanceof \ReflectionMethod) {
|
Chris@14
|
100 $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name;
|
Chris@14
|
101 }
|
Chris@14
|
102
|
Chris@14
|
103 if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) {
|
Chris@14
|
104 $this->lookupTable[$functionOrMethod->getFileName()] = [];
|
Chris@14
|
105 }
|
Chris@14
|
106
|
Chris@14
|
107 foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) {
|
Chris@14
|
108 $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name;
|
Chris@14
|
109 }
|
Chris@14
|
110 }
|
Chris@14
|
111 }
|