package Ġorg . cq fn . di kt at . rule set . rules . chapter 4 Ċ Ċ import Ġorg . cq fn . di kt at . common . config . rules . Rules Config Ċ import Ġorg . cq fn . di kt at . rule set . constants . Warnings . AV OID _ NULL _ CHECKS Ċ import Ġorg . cq fn . di kt at . rule set . rules . D ik tat Rule Ċ import Ġorg . cq fn . di kt at . rule set . utils .* Ċ Ċ import Ġcom . p interest . kt lint . core . ast . ElementType Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . BINARY _ EXPRESSION Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . BLOCK Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . BREAK Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . CONDITION Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . ELSE Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . IF Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . IF _ KEYWORD Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . NULL Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . REFERENCE _ EXPRESSION Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . THEN Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . VALUE _ ARGUMENT Ċ import Ġcom . p interest . kt lint . core . ast . ElementType . VALUE _ ARGUMENT _ LIST Ċ import Ġcom . p interest . kt lint . core . ast . parent Ċ import Ġorg . jetbrains . kotlin . com . intellij . lang . AST Node Ċ import Ġorg . jetbrains . kotlin . com . intellij . psi . tree . I ElementType Ċ import Ġorg . jetbrains . kotlin . psi . Kt Binary Expression Ċ import Ġorg . jetbrains . kotlin . psi . Kt Block Expression Ċ import Ġorg . jetbrains . kotlin . psi . Kt If Expression Ċ import Ġorg . jetbrains . kotlin . psi . psi Util . block Expressions Or Single Ċ Ċ /** Ċ Ġ* ĠThis Ġrule Ġcheck Ġand Ġfixes Ġexplicit Ġnull Ġchecks Ġ( explicit Ġcomparison Ġwith Ġ` null `) Ċ Ġ* ĠThere Ġare Ġseveral Ġcode - structures Ġthat Ġcan Ġbe Ġused Ġin ĠKotlin Ġto Ġavoid Ġnull - checks . ĠFor Ġexample : Ġ` ?: `, Ġ Ġ`. let Ġ{} `, Ġ`. also Ġ{} `, Ġe . t . c Ċ Ġ*/ Ċ class ĠNull Checks Rule ( config Rules : ĠList < Rules Config >) Ġ: ĠD ik tat Rule ( ĊĠĠĠ ĠNAME _ ID , ĊĠĠĠ Ġconfig Rules , ĊĠĠĠ ĠlistOf ( AV OID _ NULL _ CHECKS ) Ċ ) Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġlogic ( node : ĠAST Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( node . elementType Ġ== ĠCONDITION ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . parent ( IF )?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġexcluding Ġcomplex Ġcases Ġwith Ġelse - if Ġstatements , Ġbecause Ġthey Ġlook Ġbetter Ġwith Ġexplicit Ġnull - check ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Complex If Statement ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġcan Ġbe Ġautof ixed Ġas Ġthe Ġcondition Ġstays Ġin Ġsimple Ġif - statement ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcondition In If Statement ( node ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( node . elementType Ġ== ĠBINARY _ EXPRESSION ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ` condition ` Ġcase Ġis Ġalready Ġchecked Ġabove , Ġso Ġno Ġneed Ġto Ġcheck Ġit Ġonce Ġagain ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnode . parent ( CONDITION ) Ġ?: Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġonly Ġwarning Ġhere , Ġbecause Ġautof ix Ġin Ġother Ġstatements Ġ( like ) Ġlambda Ġ( or Ġvalue ) Ġcan Ġbreak Ġthe Ġcode ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull Check In Other Statements ( node ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġchecks Ġthat Ġif - statement Ġis Ġa Ġcomplex Ġcondition ĊĠĠĠĠ Ġ* ĠYou Ġcan Ġname Ġa Ġstatement Ġ- Ġ" complex Ġif - statement " Ġif Ġit Ġhas Ġother Ġif Ġin Ġthe Ġelse Ġbranch Ġ( else - if Ġstructure ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġis Complex If Statement ( parent If : ĠAST Node ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġparent If Psi Ġ= Ġparent If . psi ĊĠĠĠĠĠĠĠ Ġrequire ( parent If Psi Ġis ĠK t If Expression ) ĊĠĠĠĠĠĠĠ Ġreturn Ġ( parent If Psi .` else ` ?. node ?. firstChild Node ?. elementType Ġ== ĠIF _ KEYWORD ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcondition In If Statement ( node : ĠAST Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnode . findAll Desc endants With Specific Type ( BINARY _ EXPRESSION ). forEach Ġ{ Ġbinary Expr Node Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcondition Ġ= Ġ( binary Expr Node . psi Ġas ĠK t Binary Expression ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( isNull Check Binary Expression ( condition )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( condition . operation Token ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ` == ` Ġand Ġ` === ` Ġcomparison Ġcan Ġbe Ġfixed Ġwith Ġ` ?: ` Ġoperator ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠElementType . EQ EQ , ĠElementType . EQ EQ EQ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwarn And Fix On Null Check ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcondition , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Fix able ( node , Ġtrue ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" use Ġ'. let /. also / ?: / e . t . c ' Ġinstead Ġof Ġ${ condition . text }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfix Null In If Condition ( node , Ġcondition , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ` !== ` Ġand Ġ` !== ` Ġcomparison Ġcan Ġbe Ġfixed Ġwith Ġ`. let / also ` Ġoperators ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠElementType . EX CLE Q , ĠElementType . EX CLE Q EQ EQ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwarn And Fix On Null Check ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcondition , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Fix able ( node , Ġfalse ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" use Ġ'. let /. also / ?: / e . t . c ' Ġinstead Ġof Ġ${ condition . text }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfix Null In If Condition ( node , Ġcondition , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" Unsafe Call On Nullable Type ") ĊĠĠĠ Ġprivate Ġfun Ġis Fix able ( condition : ĠAST Node , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis EqualTo Null : ĠBoolean ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠHandle Ġcases Ġwith Ġ` break ` Ġword Ġin Ġblocks ĊĠĠĠĠĠĠĠ Ġval Ġtype Pair Ġ= Ġif Ġ( isEqualTo Null ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( ELSE Ġto ĠTHEN ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( THEN Ġto ĠELSE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġis Block In If With Break Ġ= Ġcondition . get Break Node From If ( type Pair . first ) ĊĠĠĠĠĠĠĠ Ġval Ġis One Line Block In If With Break Ġ= Ġcondition ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. tree Parent ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. find Child ByType ( type Pair . second ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ Ġit . find Child ByType ( BLOCK ) Ġ?: Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ Ġast Node Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġast Node . has Child OfType ( BREAK ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( ast Node . psi Ġas ? ĠK t Block Expression )?. statements ?. size Ġ!= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: Ġfalse ĊĠĠĠĠĠĠĠ Ġreturn Ġ(! is Block In If With Break Ġ&& Ġ! is One Line Block In If With Break ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" Unsafe Call On Nullable Type ", Ġ" TOO _ LONG _ FUNCTION ") ĊĠĠĠ Ġprivate Ġfun Ġfix Null In If Condition ( condition : ĠAST Node , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbinary Expression : ĠK t Binary Expression , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis EqualTo Null : ĠBoolean ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġvariable Name Ġ= Ġbinary Expression . left !!. text ĊĠĠĠĠĠĠĠ Ġval Ġthen From Existing Code Ġ= Ġcondition . extract Lines From Block ( THEN ) ĊĠĠĠĠĠĠĠ Ġval Ġelse From Existing Code Ġ= Ġcondition . extract Lines From Block ( ELSE ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ== Ġnull ) Ġ{ Ġfoo () Ġ} Ġelse Ġ{ Ġbar () Ġ} Ġ-> Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġbar () Ġ} Ġelse Ġ{ Ġfoo () Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġthen Code Lines Ġ= Ġif Ġ( isEqualTo Null ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse From Existing Code ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthen From Existing Code ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġelse Code Lines Ġ= Ġif Ġ( isEqualTo Null ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthen From Existing Code ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse From Existing Code ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval ĠnumberOf Statements In Else Block Ġ= Ġif Ġ( isEqualTo Null ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( condition . tree Parent . psi Ġas ĠK t If Expression ). then ?. block Expressions Or Single ()?. count () Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( condition . tree Parent . psi Ġas ĠK t If Expression ). ` else ` ?. block Expressions Or Single ()?. count () Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġelse Edited Code Lines Ġ= Ġget Edited Else Code Lines ( else Code Lines , ĠnumberOf Statements In Else Block ) ĊĠĠĠĠĠĠĠ Ġval Ġthen Edited Code Lines Ġ= Ġget Edited Then Code Lines ( variable Name , Ġthen Code Lines , Ġelse Edited Code Lines ) ĊĊĠĠĠĠĠĠĠ Ġval Ġtext Ġ= Ġ"$ then Edited Code Lines Ġ$ else Edited Code Lines " ĊĠĠĠĠĠĠĠ Ġval Ġtree Ġ= ĠKotlin Parser (). createNode ( text ) ĊĠĠĠĠĠĠĠ Ġcondition . tree Parent . tree Parent . addChild ( tree , Ġcondition . tree Parent ) ĊĠĠĠĠĠĠĠ Ġcondition . tree Parent . tree Parent . removeChild ( condition . tree Parent ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Edited Else Code Lines ( else Code Lines : ĠList < String > ?, ĠnumberOf Statements In Else Block : ĠInt ): ĠString Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġelse Ġ{ Ġ" null "/ empty Ġ} Ġ-> Ġ"" ĊĠĠĠĠĠĠĠ Ġelse Code Lines Ġ== Ġnull Ġ|| Ġelse Code Lines . single OrNull () Ġ== Ġ" null " Ġ-> Ġ"" ĊĠĠĠĠĠĠĠ Ġ// Ġelse Ġ{ Ġbar () Ġ} Ġ-> Ġ?: Ġbar () ĊĠĠĠĠĠĠĠ ĠnumberOf Statements In Else Block Ġ== Ġ 1 Ġ-> Ġ" ?: Ġ${ else Code Lines . join ToString ( postfix Ġ= Ġ"\ n ", Ġseparator Ġ= Ġ"\ n ") }" ĊĠĠĠĠĠĠĠ Ġ// Ġelse Ġ{ Ġ... Ġ} Ġ-> Ġ?: Ġrun Ġ{ Ġ... Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĠgetDefault Case Else Code Lines ( else Code Lines ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" Unsafe Call On Nullable Type ") ĊĠĠĠ Ġprivate Ġfun Ġget Edited Then Code Lines ( ĊĠĠĠĠĠĠĠ Ġvariable Name : ĠString , ĊĠĠĠĠĠĠĠ Ġthen Code Lines : ĠList < String > ?, ĊĠĠĠĠĠĠĠ Ġelse Edited Code Lines : ĠString ĊĠĠĠ Ġ): ĠString Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġ Ġ} Ġ-> Ġa Ġ?: Ġedited Else ĊĠĠĠĠĠĠĠ Ġ( then Code Lines . isNull OrEmpty () Ġ&& Ġelse Edited Code Lines . isNotEmpty ()) Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġa Ġ} Ġelse Ġ{ Ġ... Ġ} Ġ-> Ġa Ġ?: Ġedited Else ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( then Code Lines ?. single OrNull () Ġ== Ġvariable Name Ġ&& Ġelse Edited Code Lines . isNotEmpty ()) Ġ-> Ġvariable Name ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġa . foo () Ġ} Ġ-> Ġa ?. foo () ĊĠĠĠĠĠĠĠ Ġthen Code Lines ?. single OrNull ()?. startsWith ("$ variable Name .") Ġ?: Ġfalse Ġ-> Ġ"$ variable Name ? ${ then Code Lines ?. first OrNull () !!. remove Prefix ( variable Name )}" ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġbreak Ġ} Ġ-> Ġa ?. let Ġ{ Ġ... Ġ} ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġ( a Ġ!= Ġnull ) Ġ{ Ġfoo () Ġ} Ġ-> Ġa ?. let Ġ{ Ġ... Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĠgetDefault Case Then Code Lines ( variable Name , Ġthen Code Lines ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠgetDefault Case Then Code Lines ( variable Name : ĠString , Ġthen Code Lines : ĠList < String >? ): ĠString Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ variable Name ?. let Ġ{ ${ then Code Lines ?. join ToString ( prefix Ġ= Ġ"\ n ", Ġpostfix Ġ= Ġ"\ n ", Ġseparator Ġ= Ġ"\ n ") }}" ĊĊĠĠĠ Ġprivate Ġfun ĠgetDefault Case Else Code Lines ( else Code Lines : ĠList < String >): ĠString Ġ= Ġ" ?: Ġrun Ġ{ ${ else Code Lines . join ToString ( prefix Ġ= Ġ"\ n ", Ġpostfix Ġ= Ġ"\ n ", Ġseparator Ġ= Ġ"\ n ") }}" ĊĊĠĠĠ Ġ@ Suppress (" COMMENT _ WHITE _ SPACE ", Ġ" Unsafe Call On Nullable Type ") ĊĠĠĠ Ġprivate Ġfun Ġnull Check In Other Statements ( binary Expr Node : ĠAST Node ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcondition Ġ= Ġ( binary Expr Node . psi Ġas ĠK t Binary Expression ) ĊĠĠĠĠĠĠĠ Ġif Ġ( isNull Check Binary Expression ( condition )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġrequire ( a Ġ!= Ġnull ) Ġis Ġincorrect , ĠKotlin Ġhas Ġspecial Ġmethod : Ġ` require NotNull ` Ġ- Ġneed Ġto Ġuse Ġit Ġinstead ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġhierarchy Ġis Ġthe Ġfollowing : ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequire ( a Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ/ ĠĠĠĠĠĠĠĠĠĠĠ Ġ\ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠ ĠREFER ENCE _ EXPRESSION ĠĠĠ ĠVALUE _ ARGUMENT _ LIST ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ| ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠĠĠ ĠIDENT IFIER ( require ) ĠĠĠĠ ĠVALUE _ ARGUMENT ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparent Ġ= Ġbinary Expr Node . tree Parent ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( parent Ġ!= Ġnull Ġ&& Ġparent . elementType Ġ== ĠVALUE _ ARGUMENT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġgrand Parent Ġ= Ġparent . tree Parent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( grand Parent Ġ!= Ġnull Ġ&& Ġgrand Parent . elementType Ġ== ĠVALUE _ ARGUMENT _ LIST Ġ&& Ġis Require Fun ( grand Parent . tree Prev )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" COLL AP SE _ IF _ STATE MENTS ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( listOf ( ElementType . EX CLE Q , ĠElementType . EX CLE Q EQ EQ ). contains ( condition . operation Token )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwarn And Fix On Null Check ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcondition , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" use Ġ' require NotNull ' Ġinstead Ġof Ġrequire (${ condition . text })" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvariable Name Ġ= Ġ( binary Expr Node . psi Ġas ĠK t Binary Expression ). left !!. text ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Method Ġ= ĠKotlin Parser (). createNode (" require NotNull ($ variable Name )") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgrand Parent . tree Parent . tree Parent . addChild ( new Method , Ġgrand Parent . tree Parent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgrand Parent . tree Parent . tree Parent . removeChild ( grand Parent . tree Parent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠAST Node . get Break Node From If ( type : ĠI ElementType ) Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġ. tree Parent ĊĠĠĠĠĠĠĠ Ġ. find Child ByType ( type ) ĊĠĠĠĠĠĠĠ Ġ? . let Ġ{ Ġit . find Child ByType ( BLOCK ) Ġ?: Ġit Ġ} ĊĠĠĠĠĠĠĠ Ġ? . findAll Nodes With Condition Ġ{ Ġit . elementType Ġ== ĠBRE AK Ġ} ?. isNotEmpty () ĊĠĠĠĠĠĠĠ Ġ?: Ġfalse ĊĊĠĠĠ Ġprivate Ġfun ĠAST Node . extract Lines From Block ( type : ĠI ElementType ): ĠList < String >? Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtree Parent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. getFirst Child WithType ( type ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . text ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . trim ('{ ', Ġ' }') ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . split ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . filter Ġ{ Ġit . isNotBlank () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . map Ġ{ Ġit . trim () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . toList () ĊĊĠĠĠ Ġ@ Suppress (" Unsafe Call On Nullable Type ") ĊĠĠĠ Ġprivate Ġfun Ġis Null Check Binary Expression ( condition : ĠK t Binary Expression ): ĠBoolean Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcheck Ġthat Ġbinary Ġexpression Ġhas Ġ` null ` Ġas Ġright Ġor Ġleft Ġoperand ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Of ( condition . right , Ġcondition . left ). map Ġ{ Ġit !!. node . elementType Ġ}. contains ( NULL ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġchecks Ġthat Ġit Ġis Ġthe Ġcomparison Ġcondition ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Of ( ElementType . EQ EQ , ĠElementType . EQ EQ EQ , ĠElementType . EX CLE Q , ĠElementType . EX CLE Q EQ EQ ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. contains ( condition . operation Token ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġno Ġneed Ġto Ġraise Ġwarning Ġor Ġfix Ġnull Ġchecks Ġin Ġcomplex Ġexpressions ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ! condition . is Complex Condition () Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ! condition . isIn Lambda () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġchecks Ġif Ġcondition Ġis Ġa Ġcomplex Ġexpression . ĠFor Ġexample : ĊĠĠĠĠ Ġ* Ġ( a Ġ== Ġ 5 ) Ġ- Ġis Ġnot Ġa Ġcomplex Ġcondition , Ġbut Ġ( a Ġ== Ġ 5 Ġ&& Ġb Ġ!= Ġ 6 ) Ġis Ġa Ġcomplex Ġcondition ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun ĠK t Binary Expression . is Complex Condition (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠK t Binary Expression Ġis Ġcomplex Ġif Ġit Ġhas Ġa Ġparent Ġthat Ġis Ġalso Ġa Ġbinary Ġexpression ĊĠĠĠĠĠĠĠ Ġreturn Ġthis . parent Ġis ĠK t Binary Expression ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠExpression Ġcould Ġbe Ġused Ġin Ġlambda : ĊĠĠĠĠ Ġ* Ġif Ġ( a . any Ġ{ Ġit Ġ== Ġnull Ġ}) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun ĠK t Binary Expression . isIn Lambda (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠK t Binary Expression Ġis Ġin Ġlambda Ġif Ġit Ġhas Ġa Ġparent Ġthat Ġis Ġa Ġblock Ġexpression ĊĠĠĠĠĠĠĠ Ġreturn Ġthis . parent Ġis ĠK t Block Expression ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwarn And Fix On Null Check ( ĊĠĠĠĠĠĠĠ Ġcondition : ĠK t Binary Expression , ĊĠĠĠĠĠĠĠ Ġcan Be Auto Fixed : ĠBoolean , ĊĠĠĠĠĠĠĠ Ġfree Text : ĠString , ĊĠĠĠĠĠĠĠ Ġautof ix : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠA VOID _ NULL _ CHECKS . warn And Fix ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconfig Rules , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit Warn , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Fix Mode , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfree Text , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcondition . node . start Offset , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcondition . node , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcan Be Auto Fixed , ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġautof ix () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Require Fun ( reference Expression : ĠAST Node ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreference Expression . elementType Ġ== ĠREFER ENCE _ EXPRESSION Ġ&& Ġreference Expression . firstChild Node . text Ġ== Ġ" require " ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNAME _ ID Ġ= Ġ" ach - null - checks " ĊĠĠĠ Ġ} Ċ } Ċ