/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 1 ĠSlack ĠTechnologies , ĠLLC Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġslack . lint . rx Ċ Ċ import Ġcom . android . tools . lint . detector . api . Category Ċ import Ġcom . android . tools . lint . detector . api . Detector Ċ import Ġcom . android . tools . lint . detector . api . Implementation Ċ import Ġcom . android . tools . lint . detector . api . Issue Ċ import Ġcom . android . tools . lint . detector . api . Java Context Ċ import Ġcom . android . tools . lint . detector . api . Lint Fix Ċ import Ġcom . android . tools . lint . detector . api . Severity Ċ import Ġcom . android . tools . lint . detector . api . Source Code Scanner Ċ import Ġcom . intellij . lang . java . Java Language Ċ import Ġcom . intellij . psi . Psi Field Ċ import Ġcom . intellij . psi . Psi Local Variable Ċ import Ġcom . intellij . psi . Psi Method Ċ import Ġcom . intellij . psi . Psi MethodCall Expression Ċ import Ġorg . jetbrains . kotlin . as Java . elements . Kt Light Field Ċ import Ġorg . jetbrains . kotlin . idea . Kotlin Language Ċ import Ġorg . jetbrains . kotlin . psi . Kt Property Ċ import Ġorg . jetbrains . u ast . U Call Expression Ċ import Ġorg . jetbrains . u ast . U Expression Ċ import Ġorg . jetbrains . u ast . java . Java U Call Expression Ċ import Ġorg . jetbrains . u ast . java . Java U Composite Qualified Expression Ċ import Ġorg . jetbrains . u ast . kotlin . Kotlin U Function Call Expression Ċ import Ġorg . jetbrains . u ast . kotlin . Kotlin U Qualified Reference Expression Ċ import Ġorg . jetbrains . u ast . kotlin . Kotlin US imple Reference Expression Ċ import Ġorg . jetbrains . u ast . kotlin . psi . U ast Kotlin Psi Variable Ċ import Ġslack . lint . util . source Implementation Ċ import Ġkotlin . reflect . full . safe Cast Ċ Ċ /** Ċ Ġ* Ġ[ Detector ] Ġfor Ġusage s Ġof Ġ` Observable . subscribe On ( Android Schedulers . main Thread ()) `. ĠTypically , Ġthis Ġis Ġnot Ġdesired Ċ Ġ* Ġand Ġinstead Ġusers Ġare Ġlooking Ġfor Ġ` observe On ( Android Schedulers . main Thread ()) `. Ċ Ġ*/ Ċ class ĠRx Subscribe On Main Detector Ġ: ĠDetector (), ĠSource Code Scanner Ġ{ ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġfun ĠImplementation . to Issue () Ġ= ĠIssue . create ( ĊĠĠĠĠĠ Ġid Ġ= Ġ" Subscribe On Main ", ĊĠĠĠĠĠ Ġbrief Description Ġ= Ġ" subscribe On Ġcalled Ġwith Ġthe Ġmain Ġthread Ġscheduler .", ĊĠĠĠĠĠ Ġexplanation Ġ= Ġ""" ĊĠĠĠĠĠĠĠ ĠCalling Ġ` subscribe On ( Android Schedulers . main Thread ()) ` Ġwill Ġcause Ġthe Ġcode Ġran Ġat Ġsubscription Ġtime Ġto Ġbe Ġexecuted Ġ\ ĊĠĠĠĠĠĠĠ Ġon Ġthe Ġmain Ġthread Ġ- Ġthat Ġis , Ġcode Ġabove Ġthis Ġline . ĊĠĠĠĠĠĠĠ ĠTypically Ġthis Ġis Ġnot Ġactually Ġdesired , Ġand Ġinstead Ġyou Ġwant Ġto Ġuse Ġobserve On ( Android Schedulers . main Thread ()) Ġ\ ĊĠĠĠĠĠĠĠ Ġwhich Ġwill Ġcause Ġthe Ġcode Ġbelow Ġthis Ġline Ġto Ġbe Ġrun Ġon Ġthe Ġmain Ġthread Ġ( eg Ġthe Ġcode Ġinside Ġyour Ġsubscribe () Ġ\ ĊĠĠĠĠĠĠĠ Ġblock ). ĊĠĠĠĠĠ Ġ"" ", ĊĠĠĠĠĠ Ġcategory Ġ= ĠCategory . CORRECT NESS , ĊĠĠĠĠĠ Ġpriority Ġ= Ġ 4 , ĊĠĠĠĠĠ Ġseverity Ġ= ĠSeverity . ERROR , ĊĠĠĠĠĠ Ġimplementation Ġ= Ġthis ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġval ĠISS UE Ġ= Ġsource Implementation < Rx Subscribe On Main Detector >(). to Issue () ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġget Applicable Method Names (): ĠList < String > Ġ= ĠlistOf (" subscribe On ") ĊĊĠ Ġoverride Ġfun Ġget Applicable Call Owners () Ġ= ĠlistOf ( ĊĠĠĠ Ġ" io / reactivex / rx java 3 / core / Comp letable ", ĊĠĠĠ Ġ" io / reactivex / rx java 3 / core / Flow able ", ĊĠĠĠ Ġ" io / reactivex / rx java 3 / core / Maybe ", ĊĠĠĠ Ġ" io / reactivex / rx java 3 / core / Observable ", ĊĠĠĠ Ġ" io / reactivex / rx java 3 / core / Single " ĊĠ Ġ) ĊĊĠ Ġoverride Ġfun Ġvisit MethodCall ( context : ĠJava Context , Ġnode : ĠU Call Expression , Ġmethod : ĠPsi Method ) Ġ{ ĊĠĠĠ Ġval Ġarg Ġ= Ġnode . value Arguments . first () ĊĠĠĠ Ġwhen Ġ( arg ) Ġ{ ĊĠĠĠĠĠ Ġis ĠJava U Composite Qualified Expression Ġ-> Ġcheck Call Ġ{ ĠJava U Call Expression :: class . safe Cast ( arg . selector ) Ġ} ĊĠĠĠĠĠ Ġis ĠJava U Call Expression Ġ-> Ġcheck Call Ġ{ Ġarg Ġ} ĊĠĠĠĠĠ Ġis ĠKotlin U Qualified Reference Expression Ġ-> Ġcheck Call Ġ{ ĠKotlin U Function Call Expression :: class . safe Cast ( arg . selector ) Ġ} ĊĠĠĠĠĠ Ġis ĠKotlin U Function Call Expression Ġ-> Ġcheck Call Ġ{ Ġarg Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġcheck Variable Ġ{ Ġarg Ġ} ĊĠĠĠ Ġ}. let Ġ{ Ġmain Thread Found Ġ-> ĊĠĠĠĠĠ Ġif Ġ( main Thread Found ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . report ( ĊĠĠĠĠĠĠĠĠĠ ĠISS UE , ĊĠĠĠĠĠĠĠĠĠ Ġcontext . get Call Location ( node , Ġinclude Receiver Ġ= Ġfalse , Ġinclude Arguments Ġ= Ġtrue ), ĊĠĠĠĠĠĠĠĠĠ Ġ" This Ġwill Ġmake Ġthe Ġcode Ġfor Ġthe Ġinitial Ġsubscription Ġ( above Ġthis Ġline ) Ġrun Ġon Ġthe Ġmain Ġthread . Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" You Ġprobably Ġwant Ġ` observe On ( Android Schedulers . main Thread ()) `. ", ĊĠĠĠĠĠĠĠĠĠ ĠL int Fix . create () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. replace () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. name (" Replace Ġwith Ġobserve On () ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. text (" subscribe On ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. with (" observe On ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* Ġreturn Ġtrue Ġif Ġthe Ġresolved Ġ[ U Call Expression ] Ġhas Ġmethod Ġname Ġ" main Thread " Ġor Ġ" immediate MainThread ", ĊĠĠ Ġ* Ġfalse Ġotherwise ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcheck Call ( fn : Ġ() Ġ-> ĠU Call Expression ?): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġfn ()?. let Ġ{ Ġcall Ġ-> Ġ" main Thread " Ġ== Ġcall . methodName Ġ|| Ġ" immediate MainThread " Ġ== Ġcall . methodName Ġ} Ġ?: Ġfalse ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* Ġreturn Ġtrue Ġif Ġthe Ġresolved Ġ[ U Expression ] Ġwas Ġcreated Ġfrom Ġthe Ġ" main Thread " Ġor Ġ" immediate MainThread " Ġmethods , ĊĠĠ Ġ* Ġfalse Ġotherwise ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcheck Variable ( fn : Ġ() Ġ-> ĠU Expression ?): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġfn ()?. let Ġ{ Ġexp Ġ-> ĊĠĠĠĠĠ Ġwhen Ġ( exp . lang ) Ġ{ ĊĠĠĠĠĠĠĠ Ġis ĠKotlin Language Ġ-> Ġcheck Kotlin Variable ( exp ) ĊĠĠĠĠĠĠĠ Ġis ĠJava Language Ġ-> Ġcheck Java Variable ( exp ) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġ?: Ġfalse ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcheck Kotlin Variable ( exp : ĠU Expression ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġwhen Ġ( exp ) Ġ{ ĊĠĠĠĠĠ Ġis ĠKotlin US imple Reference Expression Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinitializer Text Ġ= Ġwhen Ġ( val Ġreference Ġ= Ġexp . resolve ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġis ĠK t Light Field Ġ-> Ġ{ Ġ// ĠThe Ġvariable Ġreference Ġis Ġa Ġmember ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinitializer Ġ= Ġ( reference . kotlin Origin Ġas ? ĠK t Property )?. initializer ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitializer ?. node ?. text ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġis ĠU ast Kotlin Psi Variable Ġ-> Ġ{ Ġ// ĠThe Ġvariable Ġreference Ġis Ġlocal ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinitializer Ġ= Ġreference . initializer ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitializer ?. node ?. text ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġinitializer Text ?. let Ġ{ Ġit . endsWith (" main Thread () ") Ġ|| Ġit . endsWith (" immediate MainThread () ") Ġ} Ġ?: Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcheck Java Variable ( exp : ĠU Expression ): ĠBoolean Ġ{ ĊĠĠĠ Ġval Ġassignment Ġ= Ġwhen Ġ( val Ġvariable Ġ= Ġexp . source Psi ?. reference ?. resolve ()) Ġ{ ĊĠĠĠĠĠ Ġis ĠPsi Field Ġ-> Ġvariable . initializer Ġas ? ĠPsi MethodCall Expression ĊĠĠĠĠĠ Ġis ĠPsi Local Variable Ġ-> Ġvariable . initializer Ġas ? ĠPsi MethodCall Expression ĊĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠ Ġ} ĊĠĠĠ Ġval ĠmethodName Ġ= Ġassignment ?. resolve Method ()?. name ĊĠĠĠ Ġreturn ĠmethodName Ġ== Ġ" main Thread " Ġ|| ĠmethodName Ġ== Ġ" immediate MainThread " ĊĠ Ġ} Ċ } Ċ