/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// 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 . Ċ Ġ*/ Ċ Ċ @ file : Suppress (" Un stable Api Usage ") Ċ Ċ package Ġandroidx . build . lint Ċ Ċ import Ġcom . android . tools . lint . client . api . Configuration Ċ import Ġcom . android . tools . lint . client . api . U Element Handler Ċ 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 . Incident Ċ import Ġcom . android . tools . lint . detector . api . Issue Ċ import Ġcom . android . tools . lint . detector . api . Java Context Ċ import Ġcom . android . tools . lint . detector . api . Scope Ċ import Ġcom . android . tools . lint . detector . api . Severity Ċ import Ġjava . io . File Ċ import Ġjava . io . FileNotFoundException Ċ import Ġorg . jetbrains . u ast . U Annotated Ċ import Ġorg . jetbrains . u ast . U Annotation Ċ import Ġorg . jetbrains . u ast . U Class Ċ import Ġorg . jetbrains . u ast . U Element Ċ import Ġorg . jetbrains . u ast . resolve ToU Element Ċ Ċ /** Ċ Ġ* ĠPre vents Ġusage Ġof Ġexperimental Ġannotations Ġoutside Ġthe Ġgroups Ġin Ġwhich Ġthey Ġwere Ġdefined . Ċ Ġ*/ Ċ class ĠB an In appro priate Experimental Usage Ġ: ĠDetector (), ĠDetector . U ast Scanner Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġget Applicable U ast Types () Ġ= ĠlistOf ( U Annotation :: class . java ) ĊĊĠĠĠ Ġoverride Ġfun Ġcreate U ast Handler ( context : ĠJava Context ): ĠU Element Handler Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠAnnotation Checker ( context ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġinner Ġclass ĠAnnotation Checker ( val Ġcontext : ĠJava Context ) Ġ: ĠU Element Handler () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġatomic Group List : ĠList < String > Ġby Ġlazy Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġload Atomic Library GroupData ( context . configuration , ĠISS UE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Annotation ( node : ĠU Annotation ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( DEBUG ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( AP PL IC ABLE _ AN NOT ATIONS . contains ( node . qualified Name ) Ġ&& Ġnode . source Psi Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( node . u ast Parent Ġas ? ĠU Class )?. let Ġ{ Ġannotation Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ context . driver . mode }: Ġdeclared Ġ${ annotation . qualified Name } Ġin Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ context . project }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġwe Ġfind Ġan Ġusage Ġof Ġan Ġexperiment ally - declared Ġannotation , Ġcheck Ġit . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġannotation Ġ= Ġnode . resolve ToU Element () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( annotation Ġis ĠU Annotated ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġannotations Ġ= Ġcontext . evaluator . getAll Annotations ( annotation , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( annotations . any Ġ{ ĠAP PL IC ABLE _ AN NOT ATIONS . contains ( it . qualified Name ) Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( DEBUG ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ context . driver . mode }: Ġused Ġ${ node . qualified Name } Ġin Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ context . project }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify Usage Of Element Is Within Same Group ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnode , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġannotation , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠISS UE , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġatomic Group List ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġload Atomic Library GroupData ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconfiguration : ĠConfiguration , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġissue : ĠIssue ĊĠĠĠĠĠĠĠ Ġ): ĠList < String > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilename Ġ= Ġconfiguration . getOption ( issue , ĠA TO MIC _ LIB GROUP _ FILE _ PROPERTY , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠRuntimeException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Property Ġ$ ATOMIC _ LIB GROUP _ FILE _ PROPERTY Ġis Ġnot Ġset Ġin Ġlint . xml .") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlib Group File Ġ= Ġif Ġ( filename . contains ( OUT _ DIR _ PLACE HOLDER )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Location Ġ= Ġfilename . replace ( OUT _ DIR _ PLACE HOLDER , ĠSystem . getenv (" OUT _ DIR ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( file Location ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! file . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠFileNotFoundException (" Couldn 't Ġfind Ġatomic Ġlibrary Ġgroup Ġfile Ġ$ filename ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfiguration . getOption As File ( issue , ĠA TO MIC _ LIB GROUP _ FILE _ PROPERTY , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠFileNotFoundException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Couldn 't Ġfind Ġatomic Ġlibrary Ġgroup Ġfile Ġ$ filename ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġatomic Library Groups Ġ= Ġlib Group File . read Lines () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( atomic Library Groups . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠRuntimeException (" Atomic Ġlibrary Ġgroup Ġfile Ġshould Ġnot Ġbe Ġempty ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġatomic Library Groups ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" UNUSED _ PARAMETER ") Ġ// ĠTODO : Ġwrite Ġlogic Ġ+ Ġtests Ġin Ġfuture ĠCL Ġthat Ġuses Ġgroup List ĊĠĠĠ Ġfun Ġverify Usage Of Element Is Within Same Group ( ĊĠĠĠĠĠĠĠ Ġcontext : ĠJava Context , ĊĠĠĠĠĠĠĠ Ġusage : ĠU Element , ĊĠĠĠĠĠĠĠ Ġannotation : ĠU Element , ĊĠĠĠĠĠĠĠ Ġissue : ĠIssue , ĊĠĠĠĠĠĠĠ Ġatomic Group List : ĠList < String >, ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġevaluator Ġ= Ġcontext . evaluator ĊĠĠĠĠĠĠĠ Ġval Ġusage Coordinates Ġ= Ġevaluator . get Library ( usage ) Ġ?: Ġcontext . project . maven Coordinate ĊĠĠĠĠĠĠĠ Ġval Ġusage GroupId Ġ= Ġusage Coordinates ?. groupId ĊĠĠĠĠĠĠĠ Ġval Ġannotation GroupId Ġ= Ġevaluator . get Library ( annotation )?. groupId ĊĠĠĠĠĠĠĠ Ġif Ġ( annotation GroupId Ġ!= Ġusage GroupId Ġ&& Ġannotation GroupId Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( DEBUG ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ context . driver . mode }: Ġreport Ġusage Ġof Ġ$ annotation GroupId Ġin Ġ$ usage GroupId " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠInc ident ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. issue ( issue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. at ( usage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. message ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"` Experimental ` Ġand Ġ` Requires Opt In ` ĠAPIs Ġmay Ġonly Ġbe Ġused Ġwithin Ġthe Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" same - version Ġgroup Ġwhere Ġthey Ġwere Ġdefined ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. report () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDEBUG Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠThis Ġstring Ġmust Ġmatch Ġthe Ġvalue Ġdefined Ġin Ġbuild Src / lint . xml ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* ĠThis Ġis Ġneeded Ġas Ġwe Ġneed Ġto Ġdefine Ġthe Ġlocation Ġof Ġthe Ġatomic Ġlibrary Ġgroup Ġfile Ġfor ĊĠĠĠĠĠĠĠĠ Ġ* Ġnon - test Ġusage . Ġ ĠFor Ġtests , Ġwe Ġcan Ġdirectly Ġuse Ġthe Ġvalue Ġdefined Ġin Ġtest Ġlint . xml Ġfiles . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠOUT _ DIR _ PLACE HOLDER Ġ= Ġ" USE _ SYSTEM _ OUT _ DIR " ĊĊĠĠĠĠĠĠĠ Ġ// ĠThis Ġmust Ġmatch Ġthe Ġsetting Ġin Ġbuild Src / lint . xml ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA TO MIC _ LIB GROUP _ FILE _ PROPERTY Ġ= Ġ" atomic Library Group Filename " ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠEven Ġthough ĠKotlin 's Ġ[ Experimental ] Ġannotation Ġis Ġdeprecated Ġin Ġfavor Ġof Ġ[ Requires Opt In ], ĊĠĠĠĠĠĠĠĠ Ġ* Ġwe Ġstill Ġwant Ġto Ġcheck Ġfor Ġits Ġuse Ġin ĠL int . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠK OT LIN _ EXPERIMENT AL _ AN NOT ATION Ġ= Ġ" kotlin . Experimental " ĊĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠK OT LIN _ REQ UIRES _ OPT _ IN _ AN NOT ATION Ġ= Ġ" kotlin . Requires Opt In " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠJAVA _ EXPERIMENT AL _ AN NOT ATION Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" android x . annotation . experimental . Experimental " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠJAVA _ REQ UIRES _ OPT _ IN _ AN NOT ATION Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" android x . annotation . Requires Opt In " ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠAP PL IC ABLE _ AN NOT ATIONS Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠJAVA _ EXPERIMENT AL _ AN NOT ATION , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠK OT LIN _ EXPERIMENT AL _ AN NOT ATION , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠJAVA _ REQ UIRES _ OPT _ IN _ AN NOT ATION , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠK OT LIN _ REQ UIRES _ OPT _ IN _ AN NOT ATION , ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġval ĠISS UE Ġ= ĠIssue . create ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġ" Illegal Experimental Api Usage ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbrief Description Ġ= Ġ" Using Ġexperimental ĠAPI Ġfrom Ġseparately Ġversion ed Ġlibrary ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexplanation Ġ= Ġ" Annotations Ġmeta - annotated Ġwith Ġ`@ Requires Opt In ` Ġor Ġ`@ Experimental ` Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" may Ġonly Ġbe Ġreferenced Ġfrom Ġwithin Ġthe Ġsame - version Ġgroup Ġin Ġwhich Ġthey Ġwere Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" defined .", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcategory Ġ= ĠCategory . CORRECT NESS , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpriority Ġ= Ġ 5 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġseverity Ġ= ĠSeverity . ERROR , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġimplementation Ġ= ĠImplementation ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB an In appro priate Experimental Usage :: class . java , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠScope . JAVA _ FILE _ SCOPE , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ }