/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . Ġand ĠKotlin ĠProgramming ĠLanguage Ġcontributors . Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe Ġlicense / LICENSE . txt Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . idea . completion Ċ Ċ import Ġcom . intellij . openapi . diagnostic . Logger Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . psi . Psi Comment Ċ import Ġcom . intellij . psi . Psi Element Ċ import Ġcom . intellij . psi . Psi Error Element Ċ import Ġcom . intellij . psi . Psi WhiteSpace Ċ import Ġcom . intellij . psi . util . Cached Value Ċ import Ġcom . intellij . psi . util . Cached Value Provider Ċ import Ġcom . intellij . psi . util . Cached Values Manager Ċ import Ġorg . jetbrains . annotations . Test Only Ċ import Ġorg . jetbrains . kotlin . descriptors . Module Descriptor Ċ import Ġorg . jetbrains . kotlin . idea . analysis . analyze In Context Ċ import Ġorg . jetbrains . kotlin . idea . cache s . track ers . Kotlin Code Block Modification Listener Ċ import Ġorg . jetbrains . kotlin . idea . resolve . Resolution Facade Ċ import Ġorg . jetbrains . kotlin . idea . util . application . getService Safe Ċ import Ġorg . jetbrains . kotlin . idea . util . get Resolution Scope Ċ import Ġorg . jetbrains . kotlin . psi . Kt Block Expression Ċ import Ġorg . jetbrains . kotlin . psi . Kt Element Ċ import Ġorg . jetbrains . kotlin . psi . Kt Expression Ċ import Ġorg . jetbrains . kotlin . psi . psi Util . any Desc endant OfType Ċ import Ġorg . jetbrains . kotlin . psi . psi Util . parents Ċ import Ġorg . jetbrains . kotlin . psi . psi Util . parent sWith Self Ċ import Ġorg . jetbrains . kotlin . psi . psi Util . siblings Ċ import Ġorg . jetbrains . kotlin . resolve . Binding Context Ċ import Ġorg . jetbrains . kotlin . resolve . Composite Binding Context Ċ import Ġorg . jetbrains . kotlin . resolve . binding Context Util . getData Flow Info Before Ċ import Ġorg . jetbrains . kotlin . resolve . calls . smart casts . Data Flow Info Ċ import Ġorg . jetbrains . kotlin . resolve . lazy . Body Resolve Mode Ċ import Ġorg . jetbrains . kotlin . resolve . scopes . Lex ical Scope Ċ import Ġorg . jetbrains . kotlin . utils . addTo Std lib . first Is Instance Ċ import Ġorg . jetbrains . kotlin . utils . addTo Std lib . first Is Instance OrNull Ċ import Ġjava . lang . ref . Soft Reference Ċ import Ġjava . util .* Ċ Ċ class ĠCompletion Binding Context Provider ( project : ĠProject ) Ġ{ ĊĠĠĠ Ġprivate Ġval ĠLOG Ġ= ĠLogger . getInstance ( Completion Binding Context Provider :: class . java ) ĊĊĠĠĠ Ġ@ get : Test Only ĊĠĠĠ Ġinternal Ġvar ĠTEST _ LOG : ĠStringBuilder ? Ġ= Ġnull ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġfun ĠgetInstance ( project : ĠProject ): ĠCompletion Binding Context Provider Ġ= Ġproject . getService Safe () ĊĊĠĠĠĠĠĠĠ Ġvar ĠENABLE D Ġ= Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠCompletion Data ( ĊĠĠĠĠĠĠĠ Ġval Ġblock : ĠK t Block Expression , ĊĠĠĠĠĠĠĠ Ġval Ġprev Statement : ĠK t Expression ?, ĊĠĠĠĠĠĠĠ Ġval Ġpsi Elements Before And After : ĠList < Psi Element Data >, ĊĠĠĠĠĠĠĠ Ġval Ġbinding Context : ĠBinding Context , ĊĠĠĠĠĠĠĠ Ġval Ġmodule Descriptor : ĠModule Descriptor , ĊĠĠĠĠĠĠĠ Ġval Ġstatement Resolution Scope : ĠLex ical Scope , ĊĠĠĠĠĠĠĠ Ġval Ġstatement Data Flow Info : ĠData Flow Info , ĊĠĠĠĠĠĠĠ Ġval Ġdebug Text : ĠString ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġprivate Ġdata Ġclass ĠPsi Element Data ( val Ġelement : ĠPsi Element , Ġval Ġlevel : ĠInt ) ĊĊĠĠĠ Ġprivate Ġclass ĠData Holder Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġreference : ĠSoft Reference < Completion Data >? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġvar Ġdata : ĠCompletion Data ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġreference ?. get () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreference Ġ= Ġvalue ?. let Ġ{ ĠSoft Reference ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġprev Completion Data Cache : ĠCached Value < Data Holder > Ġ= ĠCached Values Manager . getManager ( project ). create Cached Value ( ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCached Value Provider . Result . create ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠData Holder (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKotlin Code Block Modification Listener . getInstance ( project ). kotlin OutOf Code Block Tracker ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠ Ġ) ĊĊĊĠĠĠ Ġfun Ġget Binding Context ( position : ĠPsi Element , Ġresolution Facade : ĠResolution Facade ): ĠBinding Context Ġ= Ġif Ġ( ENABLED ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ_ get Binding Context ( position , Ġresolution Facade ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġresolution Facade . analyze ( position . parent sWith Self . first Is Instance < Kt Element >(), ĠBody Resolve Mode . PAR TIAL _ FOR _ COMP LE TION ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġ_ get Binding Context ( position : ĠPsi Element , Ġresolution Facade : ĠResolution Facade ): ĠBinding Context Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġin Statement Ġ= Ġposition . find Statement In Block () ĊĠĠĠĠĠĠĠ Ġval Ġblock Ġ= Ġin Statement ?. parent Ġas ĠK t Block Expression ? ĊĠĠĠĠĠĠĠ Ġval Ġprev Statement Ġ= Ġin Statement ?. siblings ( forward Ġ= Ġfalse , Ġwith It self Ġ= Ġfalse )?. first Is Instance OrNull < Kt Expression >() ĊĠĠĠĠĠĠĠ Ġval Ġmodification Scope Ġ= Ġin Statement ?. let Ġ{ ĠKotlin Code Block Modification Listener . get Inside Code Block Modification Scope ( it )?. element Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġpsi Elements Before And After Ġ= Ġmodification Scope ?. let Ġ{ Ġcollect Psi Elements Before And After ( modification Scope , Ġin Statement ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġprev Completion Data Ġ= Ġprev Completion Data Cache . value . data ĊĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprev Completion Data Ġ== Ġnull Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" No Ġup - to - date Ġdata Ġfrom Ġprevious Ġcompletion \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock Ġ!= Ġprev Completion Data . block Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" Not Ġin Ġthe Ġsame Ġblock \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprev Statement Ġ!= Ġprev Completion Data . prev Statement Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" Previous Ġstatement Ġis Ġnot Ġthe Ġsame \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpsi Elements Before And After Ġ!= Ġprev Completion Data . psi Elements Before And After Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" P SI - tree Ġhas Ġchanged Ġinside Ġcurrent Ġscope \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprev Completion Data . module Descriptor Ġ!= Ġresolution Facade . module Descriptor Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" Module Descriptor Ġhas Ġbeen Ġreset ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġin Statement . is Too Complex () Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" Current Ġstatement Ġis Ġtoo Ġcomplex Ġto Ġuse Ġoptimization \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" Statement Ġposition Ġis Ġthe Ġsame Ġ- Ġanaly zing Ġonly Ġone Ġstatement :\ n ${ in Statement . text . prepend Indent (" ĠĠĠ Ġ") }\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLOG . debug (" Re using Ġdata Ġfrom Ġcompletion Ġof Ġ\" ${ prev Completion Data . debug Text }\" ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// TODO : Ġexpected Ġtype ? ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstatement Context Ġ= Ġin Statement . analyze In Context ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġscope Ġ= Ġprev Completion Data . statement Resolution Scope , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext Expression Ġ= Ġblock , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdata Flow Info Ġ= Ġprev Completion Data . statement Data Flow Info , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Statement Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwe Ġdo Ġnot Ġupdate Ġprev Completion Data Cache Ġbecause Ġthe Ġsame Ġdata Ġshould Ġwork ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠComposite Binding Context . create ( listOf ( statement Context , Ġprev Completion Data . binding Context )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbinding Context Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresolution Facade . analyze ( position . parent sWith Self . first Is Instance < Kt Element >(), ĠBody Resolve Mode . PAR TIAL _ FOR _ COMP LE TION ) ĊĠĠĠĠĠĠĠ Ġprev Completion Data Cache . value . data Ġ= Ġif Ġ( block Ġ!= Ġnull Ġ&& Ġmodification Scope Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresolution Scope Ġ= Ġin Statement . get Resolution Scope ( binding Context , Ġresolution Facade ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Flow Info Ġ= Ġbinding Context . getData Flow Info Before ( in Statement ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCompletion Data ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprev Statement , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpsi Elements Before And After !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbinding Context , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresolution Facade . module Descriptor , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresolution Scope , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdata Flow Info , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug Text Ġ= Ġposition . text ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġbinding Context ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġlog ( message : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ ĠTEST _ LOG ?. append ( message ) ĊĠĠĠĠĠĠĠ ĠLOG . debug ( message ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcollect Psi Elements Before And After ( scope : ĠPsi Element , Ġstatement : ĠK t Expression ): ĠList < Psi Element Data > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠArrayList < Psi Element Data >(). apply Ġ{ Ġadd Elements In Tree ( scope , Ġ 0 , Ġstatement ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠMutable List < Psi Element Data >. add Elements In Tree ( root : ĠPsi Element , Ġinitial Level : ĠInt , Ġskip Sub tree : ĠPsi Element ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( root Ġ== Ġskip Sub tree ) Ġreturn ĊĠĠĠĠĠĠĠ Ġadd ( Psi Element Data ( root , Ġinitial Level )) ĊĠĠĠĠĠĠĠ Ġvar Ġchild Ġ= Ġroot . firstChild ĊĠĠĠĠĠĠĠ Ġwhile Ġ( child Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( child Ġ! is ĠPsi WhiteSpace Ġ&& Ġchild Ġ! is ĠPsi Comment Ġ&& Ġchild Ġ! is ĠPsi Error Element ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Elements In Tree ( child , Ġinitial Level Ġ+ Ġ 1 , Ġskip Sub tree ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchild Ġ= Ġchild . next Sibling ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠPsi Element . find Statement In Block (): ĠK t Expression ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġparents . filter Is Instance < Kt Expression >(). first OrNull Ġ{ Ġit . parent Ġis ĠK t Block Expression Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠK t Expression . is Too Complex (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġany Desc endant OfType < Kt Block Expression > Ġ{ Ġit . statements . size Ġ> Ġ 1 Ġ} ĊĠĠĠ Ġ} Ċ }