5
5
namespace Smeghead \PhpVariableHardUsage \Parse ;
6
6
7
7
use PhpParser \Node \Expr \Variable ;
8
- use PhpParser \Node \Stmt ;
9
- use PhpParser \Node \Stmt \ClassMethod ;
10
- use PhpParser \Node \Stmt \Class_ ;
11
- use PhpParser \Node \Stmt \Function_ ;
12
- use PhpParser \NodeDumper ;
13
- use PhpParser \NodeVisitor \FindingVisitor ;
8
+ use PhpParser \Node \FunctionLike ;
9
+ use PhpParser \NodeFinder ;
10
+ use PhpParser \NodeTraverser ;
14
11
use PhpParser \Parser ;
15
12
use Smeghead \PhpVariableHardUsage \Parse \Exception \ParseFailedException ;
13
+ use Smeghead \PhpVariableHardUsage \Parse \Visitor \FunctionLikeFindingVisitor ;
16
14
17
15
final class VariableParser
18
16
{
19
17
private Parser $ parser ;
20
18
19
+ private NodeFinder $ nodeFinder ;
20
+
21
21
public function __construct ()
22
22
{
23
23
$ this ->parser = (new \PhpParser \ParserFactory ())->createForNewestSupportedVersion ();
24
+ $ this ->nodeFinder = new NodeFinder ();
24
25
}
25
26
26
- /**
27
- * @param list<Stmt> $stmt
28
- * @return list<Function_>
29
- */
30
- private function getFunctions (array $ stmt ): array
27
+ public function parse (string $ content ): ParseResult
31
28
{
32
- $ functionVisitor = new FindingVisitor (function ($ node ) {
33
- return $ node instanceof Function_;
34
- });
35
- $ traverser = new \PhpParser \NodeTraverser ();
36
- $ traverser ->addVisitor ($ functionVisitor );
37
- $ traverser ->traverse ($ stmt );
29
+ $ stmts = $ this ->parser ->parse ($ content );
30
+ if ($ stmts === null ) {
31
+ throw new ParseFailedException ();
32
+ }
38
33
39
- return $ functionVisitor ->getFoundNodes (); // @phpstan-ignore-line
40
- }
34
+ $ traverser = new NodeTraverser ();
35
+ $ visitor = new FunctionLikeFindingVisitor (fn ($ node ) => $ node instanceof FunctionLike);
36
+ $ traverser ->addVisitor ($ visitor );
37
+ $ traverser ->traverse ($ stmts );
38
+ $ functionLikes = $ visitor ->getFoundNodes ();
41
39
42
- /**
43
- * @param Function_|ClassMethod $function
44
- * @return list<Variable>
45
- */
46
- private function getVariables (Function_ |ClassMethod $ function ): array
47
- {
48
- $ variableVisitor = new FindingVisitor (function ($ node ) {
49
- return $ node instanceof Variable;
50
- });
51
- $ traverser = new \PhpParser \NodeTraverser ();
52
- $ traverser ->addVisitor ($ variableVisitor );
53
- $ traverser ->traverse ([$ function ]);
40
+ $ functions = $ this ->collectParseResultPerFunctionLike ($ functionLikes );
54
41
55
- return $ variableVisitor -> getFoundNodes (); // @phpstan-ignore-line
42
+ return new ParseResult ( $ functions );
56
43
}
57
44
58
45
/**
59
- * @param list<Stmt > $stmts
46
+ * @param list<FunctionLike > $functionLikes
60
47
* @return list<Func>
61
48
*/
62
- private function parseFunctions (array $ stmts ): array
49
+ private function collectParseResultPerFunctionLike (array $ functionLikes ): array
63
50
{
64
- $ foundFunctions = $ this ->getFunctions ($ stmts );
65
-
66
- $ functions = [];
67
- foreach ($ foundFunctions as $ foundFunction ) {
68
- $ variables = $ this ->getVariables ($ foundFunction );
69
- $ func = new Func ($ foundFunction ->name ->name );
51
+ return array_map (function (FunctionLike $ function ) {
52
+ $ className = $ function ->getAttribute ('className ' ); // Get the class name set in FunctionLikeFindingVisitor
53
+ $ functionName = $ function ->name ->name ?? $ function ->getType () . '@ ' . $ function ->getStartLine ();
54
+ $ functionIdentifier = sprintf (
55
+ '%s%s ' ,
56
+ isset ($ className ) ? $ className . ':: ' : '' ,
57
+ $ functionName
58
+ );
59
+
60
+ $ func = new Func ($ functionIdentifier );
61
+
62
+ $ variables = $ this ->nodeFinder ->findInstanceOf ($ function , Variable::class);
70
63
foreach ($ variables as $ variable ) {
71
64
$ func ->addVariable (new VarReference ($ variable ->name , $ variable ->getLine ())); // @phpstan-ignore-line
72
65
}
73
- $ functions [] = $ func ;
74
- }
75
- return $ functions ;
76
- }
77
-
78
- /**
79
- * @param list<Stmt> $stmt
80
- * @return list<Class_>
81
- */
82
- private function getClasses (array $ stmt ): array
83
- {
84
- $ classVisitor = new FindingVisitor (function ($ node ) {
85
- return $ node instanceof \PhpParser \Node \Stmt \Class_;
86
- });
87
- $ traverser = new \PhpParser \NodeTraverser ();
88
- $ traverser ->addVisitor ($ classVisitor );
89
- $ traverser ->traverse ($ stmt );
90
-
91
- return $ classVisitor ->getFoundNodes (); // @phpstan-ignore-line
92
- }
93
-
94
- /**
95
- * @param list<Stmt> $stmts
96
- * @return list<Func>
97
- */
98
- private function parseClasses (array $ stmts ): array
99
- {
100
- $ foundClasses = $ this ->getClasses ($ stmts );
101
-
102
- $ methods = [];
103
- foreach ($ foundClasses as $ foundClass ) {
104
- foreach ($ foundClass ->getMethods () as $ method ) {
105
- $ variables = $ this ->getVariables ($ method );
106
- $ func = new Func (sprintf ('%s::%s ' , $ foundClass ->name , $ method ->name ->name ));
107
- foreach ($ variables as $ variable ) {
108
- $ func ->addVariable (new VarReference ($ variable ->name , $ variable ->getLine ())); // @phpstan-ignore-line
109
- }
110
- $ methods [] = $ func ;
111
- }
112
- }
113
- return $ methods ;
114
- }
115
-
116
- public function parse (string $ content ): ParseResult
117
- {
118
- $ stmts = $ this ->parser ->parse ($ content );
119
- if ($ stmts === null ) {
120
- throw new ParseFailedException ();
121
- }
122
- $ dumper = new NodeDumper ();
123
- // echo $dumper->dump($stmts) . PHP_EOL;
124
-
125
- $ functions = $ this ->parseFunctions ($ stmts ) + $ this ->parseClasses ($ stmts );
126
-
127
- return new ParseResult ($ functions );
66
+ return $ func ;
67
+ }, $ functionLikes );
128
68
}
129
69
}
0 commit comments