66use Permafrost \PhpCodeSearch \Results \FileSearchResults ;
77use Permafrost \PhpCodeSearch \Results \SearchError ;
88use Permafrost \PhpCodeSearch \Support \Arr ;
9+ use Permafrost \PhpCodeSearch \Support \NameResolver ;
910use Permafrost \PhpCodeSearch \Support \VirtualFile ;
1011use Permafrost \PhpCodeSearch \Visitors \AssignmentVisitor ;
1112use Permafrost \PhpCodeSearch \Visitors \FunctionCallVisitor ;
1718use Permafrost \PhpCodeSearch \Visitors \VariableReferenceVisitor ;
1819use PhpParser \Error ;
1920use PhpParser \Node ;
20- use PhpParser \Node \Expr \FuncCall ;
2121use PhpParser \Node \Stmt ;
2222use PhpParser \NodeFinder ;
2323use PhpParser \NodeTraverser ;
@@ -32,19 +32,19 @@ class Searcher
3232 protected $ ast = [];
3333
3434 /** @var array */
35- protected $ functions = [];
35+ protected $ assignments = [];
3636
3737 /** @var array */
38- protected $ methods = [];
38+ protected $ classes = [];
3939
4040 /** @var array */
41- protected $ classes = [];
41+ protected $ functions = [];
4242
4343 /** @var array */
44- protected $ static = [];
44+ protected $ methods = [];
4545
4646 /** @var array */
47- protected $ assignments = [];
47+ protected $ static = [];
4848
4949 /** @var array */
5050 protected $ variables = [];
@@ -57,48 +57,44 @@ public function __construct($parser = null)
5757 $ this ->parser = $ parser ?? (new ParserFactory ())->create (ParserFactory::PREFER_PHP7 );
5858 }
5959
60- public function functions (array $ names ): self
60+ public function assignments (array $ varNames ): self
6161 {
62- $ this ->functions = array_merge ($ this ->functions , $ names );
62+ $ this ->assignments = array_merge ($ this ->assignments , $ varNames );
6363
6464 return $ this ;
6565 }
6666
67- public function methods (array $ names ): self
67+ public function classes (array $ names ): self
6868 {
69- $ this ->methods = array_merge ($ this ->methods , $ names );
69+ $ this ->classes = array_merge ($ this ->classes , $ names );
7070
7171 return $ this ;
7272 }
7373
74- public function variables (array $ names ): self
74+ public function functions (array $ names ): self
7575 {
76- $ this ->variables = array_merge ($ this ->variables , $ names );
76+ $ this ->functions = array_merge ($ this ->functions , $ names );
7777
7878 return $ this ;
7979 }
8080
81- public function static (array $ names ): self
81+ public function methods (array $ names ): self
8282 {
83- $ this ->static = array_merge ($ this ->static , $ names );
83+ $ this ->methods = array_merge ($ this ->methods , $ names );
8484
8585 return $ this ;
8686 }
8787
88- public function assignments (array $ varNames ): self
88+ public function static (array $ names ): self
8989 {
90- $ varNames = array_map (function ($ item ) {
91- return ltrim ($ item , '$ ' );
92- }, $ varNames );
93-
94- $ this ->assignments = array_merge ($ this ->assignments , $ varNames );
90+ $ this ->static = array_merge ($ this ->static , $ names );
9591
9692 return $ this ;
9793 }
9894
99- public function classes (array $ names ): self
95+ public function variables (array $ names ): self
10096 {
101- $ this ->classes = $ names ;
97+ $ this ->variables = array_merge ( $ this -> variables , $ names) ;
10298
10399 return $ this ;
104100 }
@@ -111,33 +107,30 @@ public function withoutSnippets(): self
111107 }
112108
113109 /**
114- * @param File|string $file
110+ * @param File|VirtualFile| string $file
115111 * @return FileSearchResults
116112 */
117113 public function search ($ file ): FileSearchResults
118114 {
119- if (is_string ($ file )) {
120- $ file = new File ($ file );
121- }
115+ $ file = is_string ($ file ) ? new File ($ file ) : $ file ;
122116
123117 $ results = new FileSearchResults ($ file , $ this ->withSnippets );
124118
125119 if (! $ this ->parseFile ($ file , $ results )) {
126120 return $ results ;
127121 }
128122
129- $ calls = $ this ->findAllReferences ($ this ->ast );
130-
131- $ this ->traverseNodes ($ results , $ calls );
123+ $ this ->traverseNodes (
124+ $ results ,
125+ $ this ->findAllReferences ($ this ->ast )
126+ );
132127
133128 return $ results ;
134129 }
135130
136131 public function searchCode (string $ code ): FileSearchResults
137132 {
138- $ file = new VirtualFile ($ code );
139-
140- return $ this ->search ($ file );
133+ return $ this ->search (new VirtualFile ($ code ));
141134 }
142135
143136 /**
@@ -161,147 +154,49 @@ protected function parseFile($file, FileSearchResults $results): bool
161154
162155 protected function findAllReferences (array $ ast ): array
163156 {
164- $ staticMethodCalls = $ this ->findReferences ($ ast , Node \Expr \StaticCall::class, 'class ' , $ this ->static );
165- $ staticProperties = $ this ->findReferences ($ ast , Node \Expr \StaticPropertyFetch::class, 'class ' , $ this ->static );
166- $ functionCalls = $ this ->findReferences ($ ast , FuncCall::class, 'name ' , $ this ->functions );
167- $ assignments = $ this ->findReferences ($ ast , Node \Expr \Assign::class, 'var ' , $ this ->assignments );
168- $ classes = $ this ->findReferences ($ ast , Node \Expr \New_::class, 'class ' , $ this ->classes );
169- $ methods = $ this ->findReferences ($ ast , Node \Expr \MethodCall::class, 'name ' , $ this ->methods );
170- $ variables = $ this ->findReferences ($ ast , Node \Expr \Variable::class, 'name ' , $ this ->variables );
171- $ functionDefs = $ this ->findReferences ($ ast , Node \Stmt \Function_::class, 'name ' , $ this ->functions );
172-
173- return $ this ->sortNodesByLineNumber (
174- $ assignments ,
175- $ classes ,
176- $ functionCalls ,
177- $ functionDefs ,
178- $ methods ,
179- $ staticMethodCalls ,
180- $ staticProperties ,
181- $ variables
182- );
183- }
184-
185- protected function findReferences (array $ ast , string $ class , ?string $ nodeNameProp , array $ names ): array
186- {
187- $ nodeFinder = new NodeFinder ();
188-
189- $ nodes = $ nodeFinder ->findInstanceOf ($ ast , $ class );
190-
191- if (! $ nodeNameProp ) {
192- return $ nodes ;
157+ $ nodeMap = [
158+ Node \Expr \Assign::class => $ this ->assignments ,
159+ Node \Expr \FuncCall::class => $ this ->functions ,
160+ Node \Expr \MethodCall::class => $ this ->methods ,
161+ Node \Expr \New_::class => $ this ->classes ,
162+ Node \Expr \StaticCall::class => $ this ->static ,
163+ Node \Expr \StaticPropertyFetch::class => $ this ->static ,
164+ Node \Expr \Variable::class => $ this ->variables ,
165+ Node \Stmt \Function_::class => $ this ->functions ,
166+ ];
167+
168+ $ result = [];
169+
170+ foreach ($ nodeMap as $ parserNodeClass => $ names ) {
171+ $ result [] = $ this ->findReferences ($ ast , $ parserNodeClass , $ names );
193172 }
194173
195- return array_filter ($ nodes , function (Node $ node ) use ($ names , $ nodeNameProp ) {
196- $ name = '' ;
197-
198- if ($ node instanceof FuncCall) {
199- if (! method_exists ($ node ->name , 'toString ' )) {
200- return false ;
201- }
202-
203- $ name = $ node ->name ->toString ();
204-
205- return Arr::matches ($ name , $ names , true );
206- }
207-
208- if ($ node instanceof Node \Expr \MethodCall) {
209- if (! method_exists ($ node ->name , 'toString ' )) {
210- return false ;
211- }
212-
213- $ name = $ node ->name ->toString ();
214-
215- return Arr::matches ($ name , $ names , true );
216- }
217-
218- if ($ node instanceof Node \Expr \StaticPropertyFetch) {
219- $ name = $ node ->class ->toString ();
220- $ methodName = $ node ->name ->name ;
221-
222- return Arr::matches ($ methodName , $ names , true ) || Arr::matches ("{$ name }:: \${$ methodName }" , $ names , true );
223- }
224-
225- if ($ node instanceof Node \Expr \StaticCall) {
226- if (! method_exists ($ node ->class , 'toString ' )) {
227- return false ;
228- }
229- if (! method_exists ($ node ->name , 'toString ' )) {
230- return false ;
231- }
232-
233- $ name = $ node ->class ->toString ();
234- $ methodName = $ node ->name ->toString ();
235-
236- return Arr::matches ($ name , $ names , true ) || Arr::matches ("{$ name }:: {$ methodName }" , $ names , true );
237- }
238-
239- if ($ node instanceof Node \Expr \Variable) {
240- $ name = $ node ->name ;
241-
242- return Arr::matches ($ name , $ names , true );
243- }
244-
245- if ($ node instanceof Node \Stmt \Function_) {
246- $ name = $ node ->name ->name ;
247-
248- return Arr::matches ($ name , $ names , true );
249- }
250-
251- if ($ node instanceof Node \Expr \Array_) {
252- return false ;
253- }
254-
255- if ($ node instanceof Node \Expr \ArrayItem) {
256- return false ;
257- }
258-
259- if ($ node instanceof Node \Expr \ArrayDimFetch) {
260- $ name = $ node ->var ->name ;
261-
262- return Arr::matches ($ name , $ names , true );
263- }
264-
265- // if ($node instanceof Node\Expr\New_) {
266- // $name = $node->class->name->name;
267- // }
268-
269- if ($ node instanceof Node \Expr \Assign) {
270- if (! $ node ->var instanceof Node \Expr \Variable) {
271- return false ;
272- }
273-
274- $ name = $ node ->var ->name ;
275- }
276-
277- if (! empty ($ name )) {
278- return in_array ($ name , $ names , true );
279- }
174+ return $ this ->sortNodesByLineNumber (...$ result );
175+ }
280176
281- if ( isset ( $ node ->{ $ nodeNameProp }-> name )) {
282- return in_array ( $ node ->{ $ nodeNameProp }-> name , $ names , true );
283- }
177+ protected function findReferences ( array $ ast , string $ class , array $ names ): array
178+ {
179+ $ nodes = ( new NodeFinder ())-> findInstanceOf ( $ ast , $ class );
284180
285- if (! isset ($ node ->{$ nodeNameProp }->parts )) {
286- return false ;
287- }
181+ return collect ($ nodes )->filter (function (Node $ node ) use ($ names ) {
182+ $ name = NameResolver::resolve ($ node ) ?? false ;
288183
289- return in_array ( $ node ->{ $ nodeNameProp }-> parts [ 0 ] , $ names , true );
290- });
184+ return $ name && Arr:: matchesAny ( $ name , $ names , true );
185+ })-> all () ;
291186 }
292187
293188 protected function traverseNodes (FileSearchResults $ results , array $ nodes ): void
294189 {
295190 $ traverser = new NodeTraverser ();
296191
192+ $ traverser ->addVisitor (new AssignmentVisitor ($ results , $ this ->assignments ));
297193 $ traverser ->addVisitor (new FunctionCallVisitor ($ results , $ this ->functions ));
298- $ traverser ->addVisitor (new StaticCallVisitor ($ results , $ this ->static ));
194+ $ traverser ->addVisitor (new FunctionDefinitionVisitor ($ results , $ this ->functions ));
299195 $ traverser ->addVisitor (new MethodCallVisitor ($ results , $ this ->methods ));
300- $ traverser ->addVisitor (new VariableReferenceVisitor ($ results , $ this ->variables ));
301196 $ traverser ->addVisitor (new NewClassVisitor ($ results , $ this ->classes ));
302- $ traverser ->addVisitor (new AssignmentVisitor ($ results , $ this ->assignments ));
197+ $ traverser ->addVisitor (new StaticCallVisitor ($ results , $ this ->static ));
303198 $ traverser ->addVisitor (new StaticPropertyVisitor ($ results , $ this ->static ));
304- $ traverser ->addVisitor (new FunctionDefinitionVisitor ($ results , $ this ->functions ));
199+ $ traverser ->addVisitor (new VariableReferenceVisitor ($ results , $ this ->variables ));
305200
306201 $ traverser ->traverse ($ nodes );
307202 }
0 commit comments