99use PhpParser \Node \Expr \BinaryOp \Coalesce ;
1010use PhpParser \Node \Expr \BinaryOp \Identical ;
1111use PhpParser \Node \Expr \BinaryOp \NotIdentical ;
12+ use PhpParser \Node \Expr \BooleanNot ;
13+ use PhpParser \Node \Expr \FuncCall ;
1214use PhpParser \Node \Expr \Isset_ ;
1315use PhpParser \Node \Expr \Ternary ;
1416use Rector \PhpParser \Node \Value \ValueResolver ;
@@ -35,6 +37,7 @@ public function getRuleDefinition(): RuleDefinition
3537 [
3638 new CodeSample ('$value === null ? 10 : $value; ' , '$value ?? 10; ' ),
3739 new CodeSample ('isset($value) ? $value : 10; ' , '$value ?? 10; ' ),
40+ new CodeSample ('is_null($value) ? 10 : $value; ' , '$value ?? 10; ' ),
3841 ]
3942 );
4043 }
@@ -56,6 +59,17 @@ public function refactor(Node $node): ?Node
5659 return $ this ->processTernaryWithIsset ($ node , $ node ->cond );
5760 }
5861
62+ if ($ node ->cond instanceof FuncCall && $ this ->isName ($ node ->cond , 'is_null ' )) {
63+ return $ this ->processTernaryWithIsNull ($ node , $ node ->cond , false );
64+ }
65+
66+ if (
67+ $ node ->cond instanceof BooleanNot && $ node ->cond ->expr instanceof FuncCall
68+ && $ this ->isName ($ node ->cond ->expr , 'is_null ' )
69+ ) {
70+ return $ this ->processTernaryWithIsNull ($ node , $ node ->cond ->expr , true );
71+ }
72+
5973 if ($ node ->cond instanceof Identical) {
6074 $ checkedNode = $ node ->else ;
6175 $ fallbackNode = $ node ->if ;
@@ -93,6 +107,33 @@ public function provideMinPhpVersion(): int
93107 return PhpVersionFeature::NULL_COALESCE ;
94108 }
95109
110+ private function processTernaryWithIsNull (Ternary $ ternary , FuncCall $ isNullFuncCall , bool $ isNegated ): ?Coalesce
111+ {
112+ if (count ($ isNullFuncCall ->args ) !== 1 ) {
113+ return null ;
114+ }
115+
116+ $ checkedExpr = $ isNullFuncCall ->args [0 ]->value ;
117+
118+ if ($ isNegated ) {
119+ if (! $ ternary ->if instanceof Expr) {
120+ return null ;
121+ }
122+
123+ if (! $ this ->nodeComparator ->areNodesEqual ($ ternary ->if , $ checkedExpr )) {
124+ return null ;
125+ }
126+
127+ return new Coalesce ($ ternary ->if , $ ternary ->else );
128+ }
129+
130+ if (! $ this ->nodeComparator ->areNodesEqual ($ ternary ->else , $ checkedExpr )) {
131+ return null ;
132+ }
133+
134+ return new Coalesce ($ ternary ->else , $ ternary ->if );
135+ }
136+
96137 private function processTernaryWithIsset (Ternary $ ternary , Isset_ $ isset ): ?Coalesce
97138 {
98139 if (! $ ternary ->if instanceof Expr) {
0 commit comments