1212use PhpParser \Node \Expr \BinaryOp \NotIdentical ;
1313use PhpParser \Node \Expr \Cast \Bool_ ;
1414use PhpParser \Node \Expr \ClassConstFetch ;
15- use PhpParser \Node \Expr \Closure ;
1615use PhpParser \Node \Expr \FuncCall ;
1716use PhpParser \Node \Expr \Instanceof_ ;
1817use PhpParser \Node \Expr \MethodCall ;
1918use PhpParser \Node \Expr \StaticCall ;
2019use PhpParser \Node \Expr \Variable ;
2120use PhpParser \Node \Name \FullyQualified ;
22- use PhpParser \Node \Stmt \ClassMethod ;
23- use PhpParser \NodeVisitor ;
21+ use PhpParser \Node \Stmt \Class_ ;
2422use PHPStan \Reflection \ClassReflection ;
2523use Rector \PhpParser \Node \Value \ValueResolver ;
2624use Rector \PHPStan \ScopeFetcher ;
@@ -81,105 +79,111 @@ public function test()
8179 */
8280 public function getNodeTypes (): array
8381 {
84- return [ClassMethod::class, Closure::class, FuncCall ::class];
82+ return [Class_ ::class];
8583 }
8684
8785 /**
88- * @param ClassMethod|Closure|FuncCall $node
89- * @return StaticCall|MethodCall|null|NodeVisitor::DONT_TRAVERSE_CHILDREN
86+ * @param Class_ $node
9087 */
91- public function refactor (Node $ node ): StaticCall | MethodCall | null | int
88+ public function refactor (Node $ node ): ? Class_
9289 {
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 ()) {
90+ if ($ this ->testsNodeAnalyzer ->isInTestClass ($ node ) && ! $ this ->isBehatContext ($ node )) {
11591 return null ;
11692 }
11793
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 ;
94+ $ hasChanged = false ;
12895
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 ;
96+ foreach ($ node ->getMethods () as $ classMethod ) {
97+ if ($ classMethod ->stmts === null ) {
98+ continue ;
16599 }
166100
167- $ exprs [] = $ comparedExpr ->expr ;
168- } else {
169- return null ;
101+ $ useStaticAssert = $ classMethod ->isStatic () ?: $ this ->isBehatContext ($ node );
102+
103+ $ this ->traverseNodesWithCallable ($ classMethod ->stmts , function (\PhpParser \Node $ node ) use (
104+ $ useStaticAssert ,
105+ &$ hasChanged
106+ ) {
107+ if (! $ node instanceof FuncCall) {
108+ return null ;
109+ }
110+
111+ if ($ node ->isFirstClassCallable ()) {
112+ return null ;
113+ }
114+
115+ if (! $ this ->isName ($ node , 'assert ' )) {
116+ return null ;
117+ }
118+
119+ $ comparedExpr = $ node ->getArgs ()[0 ]
120+ ->value ;
121+
122+ if ($ comparedExpr instanceof Equal) {
123+ $ methodName = AssertMethod::ASSERT_EQUALS ;
124+ $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
125+
126+ } elseif ($ comparedExpr instanceof Identical) {
127+ $ methodName = AssertMethod::ASSERT_SAME ;
128+ $ exprs = [$ comparedExpr ->right , $ comparedExpr ->left ];
129+
130+ } elseif ($ comparedExpr instanceof NotIdentical) {
131+ if ($ this ->valueResolver ->isNull ($ comparedExpr ->right )) {
132+ $ methodName = 'assertNotNull ' ;
133+ $ exprs = [$ comparedExpr ->left ];
134+ } else {
135+ return null ;
136+ }
137+
138+ } elseif ($ comparedExpr instanceof Bool_) {
139+ $ methodName = 'assertTrue ' ;
140+ $ exprs = [$ comparedExpr ];
141+ } elseif ($ comparedExpr instanceof FuncCall) {
142+ if ($ this ->isName ($ comparedExpr , 'method_exists ' )) {
143+ $ methodName = 'assertTrue ' ;
144+ $ exprs = [$ comparedExpr ];
145+ } else {
146+ return null ;
147+ }
148+ } elseif ($ comparedExpr instanceof Instanceof_) {
149+ // outside TestCase
150+ $ methodName = 'assertInstanceOf ' ;
151+ $ exprs = [];
152+
153+ if ($ comparedExpr ->class instanceof FullyQualified) {
154+ $ classConstFetch = new ClassConstFetch ($ comparedExpr ->class , 'class ' );
155+ $ exprs [] = $ classConstFetch ;
156+ } else {
157+ return null ;
158+ }
159+
160+ $ exprs [] = $ comparedExpr ->expr ;
161+ } else {
162+ return null ;
163+ }
164+
165+ // is there a comment message
166+ if (isset ($ node ->getArgs ()[1 ])) {
167+ $ exprs [] = $ node ->getArgs ()[1 ]->value ;
168+ }
169+
170+ $ hasChanged = true ;
171+
172+ return $ this ->createAssertCall ($ methodName , $ exprs , $ useStaticAssert );
173+
174+ });
170175 }
171176
172- // is there a comment message
173- if (isset ($ node ->getArgs ()[1 ])) {
174- $ exprs [] = $ node ->getArgs ()[1 ]->value ;
177+ if (! $ hasChanged ) {
178+ return null ;
175179 }
176180
177- return $ this -> createCall ( $ node, $ methodName , $ exprs ) ;
181+ return $ node ;
178182 }
179183
180- private function isBehatContext (FuncCall $ funcCall ): bool
184+ private function isBehatContext (Class_ $ class ): bool
181185 {
182- $ scope = ScopeFetcher::fetch ($ funcCall );
186+ $ scope = ScopeFetcher::fetch ($ class );
183187 if (! $ scope ->getClassReflection () instanceof ClassReflection) {
184188 return false ;
185189 }
@@ -191,33 +195,17 @@ private function isBehatContext(FuncCall $funcCall): bool
191195 return str_ends_with ($ className , 'Context ' );
192196 }
193197
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-
210198 /**
211199 * @param Expr[] $exprs
212200 */
213- private function createCall ( FuncCall $ funcCall , string $ methodName , array $ exprs ): MethodCall |StaticCall
201+ private function createAssertCall ( string $ methodName , array $ exprs, bool $ useStaticAssert ): MethodCall |StaticCall
214202 {
215203 $ args = [];
216204 foreach ($ exprs as $ expr ) {
217205 $ args [] = new Arg ($ expr );
218206 }
219207
220- if ($ this -> isBehatContext ( $ funcCall ) ) {
208+ if ($ useStaticAssert ) {
221209 $ assertFullyQualified = new FullyQualified (PHPUnitClassName::ASSERT );
222210 return new StaticCall ($ assertFullyQualified , $ methodName , $ args );
223211 }
0 commit comments