1919use PhpParser \Node \Expr \StaticCall ;
2020use PhpParser \Node \Expr \Variable ;
2121use PhpParser \Node \Name \FullyQualified ;
22- use PhpParser \Node \Stmt \ClassMethod ;
23- use PhpParser \NodeVisitor ;
22+ use PhpParser \Node \Stmt \Class_ ;
2423use PHPStan \Reflection \ClassReflection ;
2524use Rector \PhpParser \Node \Value \ValueResolver ;
2625use Rector \PHPStan \ScopeFetcher ;
@@ -81,105 +80,115 @@ public function test()
8180 */
8281 public function getNodeTypes (): array
8382 {
84- return [ClassMethod::class, Closure::class, FuncCall ::class];
83+ return [Class_ ::class];
8584 }
8685
8786 /**
88- * @param ClassMethod|Closure|FuncCall $node
89- * @return StaticCall|MethodCall|null|NodeVisitor::DONT_TRAVERSE_CHILDREN
87+ * @param Class_ $node
9088 */
91- public function refactor (Node $ node ): StaticCall | MethodCall | null | int
89+ public function refactor (Node $ node ): ? Class_
9290 {
93- // @todo handle only in test classes!
94-
95- // most liekly hook to ClassMethod :) + traverse then
96- $ this ->testsNodeAnalyzer ->isInTestClass ($ node );
97-
98- // if ($node instanceof ClassMethod) {
99- // if ($node->isStatic()) {
100- // return NodeVisitor::DONT_TRAVERSE_CHILDREN;
101- // }
102- //
103- // return null;
104- // }
105-
106- // if ($node instanceof Closure) {
107- // if ($node->static) {
108- // return NodeVisitor::DONT_TRAVERSE_CHILDREN;
109- // }
110- //
111- // return null;
112- // }
113-
114- if ($ node ->isFirstClassCallable ()) {
91+ if (! $ this ->testsNodeAnalyzer ->isInTestClass ($ node ) && ! $ this ->isBehatContext ($ node )) {
11592 return null ;
11693 }
11794
118- if (! $ this ->isName ($ node , 'assert ' )) {
119- return null ;
120- }
121-
122- if (! $ this ->isTestFilePath ($ node ) && ! $ this ->isBehatContext ($ node )) {
123- return null ;
124- }
125-
126- $ comparedExpr = $ node ->getArgs ()[0 ]
127- ->value ;
95+ $ hasChanged = false ;
12896
129- if ($ comparedExpr instanceof Equal) {
130- $ methodName = AssertMethod::ASSERT_EQUALS ;
131- $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
132-
133- } elseif ($ comparedExpr instanceof Identical) {
134- $ methodName = AssertMethod::ASSERT_SAME ;
135- $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
136-
137- } elseif ($ comparedExpr instanceof NotIdentical) {
138- if ($ this ->valueResolver ->isNull ($ comparedExpr ->right )) {
139- $ methodName = 'assertNotNull ' ;
140- $ exprs = [$ comparedExpr ->left ];
141- } else {
142- return null ;
143- }
144-
145- } elseif ($ comparedExpr instanceof Bool_) {
146- $ methodName = 'assertTrue ' ;
147- $ exprs = [$ comparedExpr ];
148- } elseif ($ comparedExpr instanceof FuncCall) {
149- if ($ this ->isName ($ comparedExpr , 'method_exists ' )) {
150- $ methodName = 'assertTrue ' ;
151- $ exprs = [$ comparedExpr ];
152- } else {
153- return null ;
154- }
155- } elseif ($ comparedExpr instanceof Instanceof_) {
156- // outside TestCase
157- $ methodName = 'assertInstanceOf ' ;
158- $ exprs = [];
159-
160- if ($ comparedExpr ->class instanceof FullyQualified) {
161- $ classConstFetch = new ClassConstFetch ($ comparedExpr ->class , 'class ' );
162- $ exprs [] = $ classConstFetch ;
163- } else {
164- return null ;
97+ foreach ($ node ->getMethods () as $ classMethod ) {
98+ if ($ classMethod ->stmts === null ) {
99+ continue ;
165100 }
166101
167- $ exprs [] = $ comparedExpr ->expr ;
168- } else {
169- return null ;
102+ $ useStaticAssert = $ classMethod ->isStatic () ?: $ this ->isBehatContext ($ node );
103+
104+ $ this ->traverseNodesWithCallable ($ classMethod ->stmts , function (Node $ node ) use (
105+ &$ useStaticAssert ,
106+ &$ hasChanged
107+ ): null |MethodCall |StaticCall {
108+ if ($ node instanceof Closure && $ node ->static ) {
109+ $ useStaticAssert = true ;
110+ return null ;
111+ }
112+
113+ if (! $ node instanceof FuncCall) {
114+ return null ;
115+ }
116+
117+ if ($ node ->isFirstClassCallable ()) {
118+ return null ;
119+ }
120+
121+ if (! $ this ->isName ($ node , 'assert ' )) {
122+ return null ;
123+ }
124+
125+ $ comparedExpr = $ node ->getArgs ()[0 ]
126+ ->value ;
127+
128+ if ($ comparedExpr instanceof Equal) {
129+ $ methodName = AssertMethod::ASSERT_EQUALS ;
130+ $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
131+
132+ } elseif ($ comparedExpr instanceof Identical) {
133+ $ methodName = AssertMethod::ASSERT_SAME ;
134+ $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
135+
136+ } elseif ($ comparedExpr instanceof NotIdentical) {
137+ if ($ this ->valueResolver ->isNull ($ comparedExpr ->right )) {
138+ $ methodName = 'assertNotNull ' ;
139+ $ exprs = [$ comparedExpr ->left ];
140+ } else {
141+ return null ;
142+ }
143+
144+ } elseif ($ comparedExpr instanceof Bool_) {
145+ $ methodName = 'assertTrue ' ;
146+ $ exprs = [$ comparedExpr ];
147+ } elseif ($ comparedExpr instanceof FuncCall) {
148+ if ($ this ->isName ($ comparedExpr , 'method_exists ' )) {
149+ $ methodName = 'assertTrue ' ;
150+ $ exprs = [$ comparedExpr ];
151+ } else {
152+ return null ;
153+ }
154+ } elseif ($ comparedExpr instanceof Instanceof_) {
155+ // outside TestCase
156+ $ methodName = 'assertInstanceOf ' ;
157+ $ exprs = [];
158+
159+ if ($ comparedExpr ->class instanceof FullyQualified) {
160+ $ classConstFetch = new ClassConstFetch ($ comparedExpr ->class , 'class ' );
161+ $ exprs [] = $ classConstFetch ;
162+ } else {
163+ return null ;
164+ }
165+
166+ $ exprs [] = $ comparedExpr ->expr ;
167+ } else {
168+ return null ;
169+ }
170+
171+ // is there a comment message
172+ if (isset ($ node ->getArgs ()[1 ])) {
173+ $ exprs [] = $ node ->getArgs ()[1 ]->value ;
174+ }
175+
176+ $ hasChanged = true ;
177+
178+ return $ this ->createAssertCall ($ methodName , $ exprs , $ useStaticAssert );
179+ });
170180 }
171181
172- // is there a comment message
173- if (isset ($ node ->getArgs ()[1 ])) {
174- $ exprs [] = $ node ->getArgs ()[1 ]->value ;
182+ if (! $ hasChanged ) {
183+ return null ;
175184 }
176185
177- return $ this -> createCall ( $ node, $ methodName , $ exprs ) ;
186+ return $ node ;
178187 }
179188
180- private function isBehatContext (FuncCall $ funcCall ): bool
189+ private function isBehatContext (Class_ $ class ): bool
181190 {
182- $ scope = ScopeFetcher::fetch ($ funcCall );
191+ $ scope = ScopeFetcher::fetch ($ class );
183192 if (! $ scope ->getClassReflection () instanceof ClassReflection) {
184193 return false ;
185194 }
@@ -191,33 +200,17 @@ private function isBehatContext(FuncCall $funcCall): bool
191200 return str_ends_with ($ className , 'Context ' );
192201 }
193202
194- private function isTestFilePath (FuncCall $ funcCall ): bool
195- {
196- $ scope = ScopeFetcher::fetch ($ funcCall );
197- if (! $ scope ->getClassReflection () instanceof ClassReflection) {
198- return false ;
199- }
200-
201- $ className = $ scope ->getClassReflection ()
202- ->getName ();
203- if (str_ends_with ($ className , 'Test ' )) {
204- return true ;
205- }
206-
207- return str_ends_with ($ className , 'TestCase ' );
208- }
209-
210203 /**
211204 * @param Expr[] $exprs
212205 */
213- private function createCall ( FuncCall $ funcCall , string $ methodName , array $ exprs ): MethodCall |StaticCall
206+ private function createAssertCall ( string $ methodName , array $ exprs, bool $ useStaticAssert ): MethodCall |StaticCall
214207 {
215208 $ args = [];
216209 foreach ($ exprs as $ expr ) {
217210 $ args [] = new Arg ($ expr );
218211 }
219212
220- if ($ this -> isBehatContext ( $ funcCall ) ) {
213+ if ($ useStaticAssert ) {
221214 $ assertFullyQualified = new FullyQualified (PHPUnitClassName::ASSERT );
222215 return new StaticCall ($ assertFullyQualified , $ methodName , $ args );
223216 }
0 commit comments