/* Ċ Ġ* ĠMinecraft ĠDev Ġfor ĠIntelliJ Ċ Ġ* Ċ Ġ* Ġhttps :// minecraft dev . org Ċ Ġ* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 1 Ġm inecraft - dev Ċ Ġ* Ċ Ġ* ĠMIT ĠLicense Ċ Ġ*/ Ċ Ċ package Ġcom . de mon wav . mc dev . platform . mixin . util Ċ Ċ import Ġcom . de mon wav . mc dev . util . internal Name Ċ import Ġcom . intellij . openapi . diagnostic . Logger Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . psi . Java Psi Facade Ċ import Ġcom . intellij . psi . Psi ClassType Ċ import Ġcom . intellij . psi . util . Inheritance Util Ċ import Ġorg . object web . asm . Op codes Ċ import Ġorg . object web . asm . Type Ċ import Ġorg . object web . asm . tree . Abstract Insn Node Ċ import Ġorg . object web . asm . tree . Class Node Ċ import Ġorg . object web . asm . tree . Method Node Ċ import Ġorg . object web . asm . tree . analysis . Analyzer Ċ import Ġorg . object web . asm . tree . analysis . Analyzer Exception Ċ import Ġorg . object web . asm . tree . analysis . Basic Value Ċ import Ġorg . object web . asm . tree . analysis . Frame Ċ import Ġorg . object web . asm . tree . analysis . Simple Verifier Ċ Ċ object ĠA sm D fa Util Ġ{ ĊĠĠĠ Ġprivate Ġval ĠLOGGER Ġ= ĠLogger . getInstance ( Asm D fa Util :: class . java ) ĊĊĠĠĠ Ġfun Ġanalyze Method ( project : ĠProject , Ġclazz : ĠClass Node , Ġmethod : ĠMethod Node ): ĠArray < Frame < Basic Value > ?> ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġmethod . cached ( clazz , Ġproject ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠAnalyzer ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPsi Byte code Interpreter ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproject , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠType . get ObjectType ( clazz . name ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclazz . super Name ?. let Ġ{ ĠType . get ObjectType ( it ) Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclazz . interfaces ?. map Ġ{ ĠType . get ObjectType ( it ) Ġ} Ġ?: Ġempty List (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclazz . has Access ( Op codes . ACC _ INTERFACE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ). analyze ( clazz . name , Ġmethod ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠAnalyzer Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLOGGER . warn (" Asm D fa Util . analyze Method Ġfailed ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Local Variable Type ( ĊĠĠĠĠĠĠĠ Ġproject : ĠProject , ĊĠĠĠĠĠĠĠ Ġclazz : ĠClass Node , ĊĠĠĠĠĠĠĠ Ġmethod : ĠMethod Node , ĊĠĠĠĠĠĠĠ Ġinsn : ĠAbstract Insn Node , ĊĠĠĠĠĠĠĠ Ġslot : ĠInt ĊĠĠĠ Ġ): ĠType ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod . instructions Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframes Ġ= Ġanalyze Method ( project , Ġclazz , Ġmethod ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframe Ġ= Ġframes . get OrNull ( ins ns . indexOf ( insn )) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġif Ġ( slot Ġ>= Ġframe . locals ) Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġreturn Ġframe . getLocal ( slot )?. type ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Local Variable Types ( ĊĠĠĠĠĠĠĠ Ġproject : ĠProject , ĊĠĠĠĠĠĠĠ Ġclazz : ĠClass Node , ĊĠĠĠĠĠĠĠ Ġmethod : ĠMethod Node , ĊĠĠĠĠĠĠĠ Ġinsn : ĠAbstract Insn Node ĊĠĠĠ Ġ): ĠArray < Type ?> ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod . instructions Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframes Ġ= Ġanalyze Method ( project , Ġclazz , Ġmethod ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframe Ġ= Ġframes . get OrNull ( ins ns . indexOf ( insn )) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġreturn Ġ( 0 Ġuntil Ġframe . locals ). map Ġ{ Ġi Ġ-> Ġframe . getLocal ( i )?. type Ġ}. to Typed Array () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Stack Type ( ĊĠĠĠĠĠĠĠ Ġproject : ĠProject , ĊĠĠĠĠĠĠĠ Ġclazz : ĠClass Node , ĊĠĠĠĠĠĠĠ Ġmethod : ĠMethod Node , ĊĠĠĠĠĠĠĠ Ġinsn : ĠAbstract Insn Node , ĊĠĠĠĠĠĠĠ Ġdepth : ĠInt ĊĠĠĠ Ġ): ĠType ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod . instructions Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframes Ġ= Ġanalyze Method ( project , Ġclazz , Ġmethod ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframe Ġ= Ġframes . get OrNull ( ins ns . indexOf ( insn )) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġif Ġ( depth Ġ> Ġframe . stack Size ) Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġreturn Ġframe . get Stack ( frame . stack Size Ġ- Ġ 1 Ġ- Ġdepth )?. type ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Stack Types ( ĊĠĠĠĠĠĠĠ Ġproject : ĠProject , ĊĠĠĠĠĠĠĠ Ġclazz : ĠClass Node , ĊĠĠĠĠĠĠĠ Ġmethod : ĠMethod Node , ĊĠĠĠĠĠĠĠ Ġinsn : ĠAbstract Insn Node ĊĠĠĠ Ġ): ĠArray < Type ?> ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod . instructions Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframes Ġ= Ġanalyze Method ( project , Ġclazz , Ġmethod ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġframe Ġ= Ġframes . get OrNull ( ins ns . indexOf ( insn )) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġreturn Ġ( 0 Ġuntil Ġframe . stack Size ). map Ġ{ Ġi Ġ-> Ġframe . get Stack ( i )?. type Ġ}. to Typed Array () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠPsi Byte code Interpreter ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġproject : ĠProject , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcurrent Class : ĠType , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcurrent Super Class : ĠType ?, ĊĠĠĠĠĠĠĠ Ġcurrent Class Interfaces : ĠList < Type >, ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġis Interface : ĠBoolean ĊĠĠĠ Ġ) Ġ: ĠSimple Verifier ( Op codes . ASM 7 , Ġcurrent Class , Ġcurrent Super Class , Ġcurrent Class Interfaces , Ġis Interface ) Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠgetClass ( type : ĠType ?): ĠClass < *> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġshould Ġnever Ġbe Ġcalled Ġgiven Ġwe Ġhave Ġoverridden Ġthe Ġother Ġmethods ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġis Sub TypeOf ( value : ĠBasic Value , Ġexpected : ĠBasic Value ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġis AssignableFrom ( expected . type , Ġvalue . type ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġis Interface ( type : ĠType ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type Ġ== Ġcurrent Class ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġis Interface ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġelement Factory Ġ= ĠJava Psi Facade . getElement Factory ( project ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpsi Type Ġ= Ġtype . to Psi Type ( element Factory ) Ġas ? ĠPsi ClassType Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclazz Ġ= Ġpsi Type . resolve () Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġclazz . is Interface ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġget Super Class ( type : ĠType ): ĠType ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type Ġ== Ġcurrent Class ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcurrent Super Class ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġelement Factory Ġ= ĠJava Psi Facade . getElement Factory ( project ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpsi Type Ġ= Ġtype . to Psi Type ( element Factory ) Ġas ? ĠPsi ClassType Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclazz Ġ= Ġpsi Type . resolve () Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠsuperClass Ġ= Ġclazz . super Class Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsuper ClassName Ġ= ĠsuperClass . internal Name Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠType . get ObjectType ( super ClassName ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġis AssignableFrom ( type 1 : ĠType , Ġtype 2 : ĠType ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 1 . descriptor Ġ== Ġ" Ljava / lang / Object ; ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 2 . descriptor Ġ== Ġ" L null ; ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 1 . sort Ġ== ĠType . ARRAY ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 2 . sort Ġ!= ĠType . ARRAY ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 1 . dimensions Ġ!= Ġtype 2 . dimensions ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġis AssignableFrom ( type 1 . elementType , Ġtype 2 . elementType ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type 1 . sort Ġ== ĠType . OBJECT Ġ&& Ġtype 2 . sort Ġ== ĠType . OBJECT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġelement Factory Ġ= ĠJava Psi Facade . getElement Factory ( project ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpsi Type 1 Ġ= Ġ( type 1 . to Psi Type ( element Factory ) Ġas ? ĠPsi ClassType )?. resolve () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpsi Type 2 Ġ= Ġ( type 2 . to Psi Type ( element Factory ) Ġas ? ĠPsi ClassType )?. resolve () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠInherit ance Util . isIn her itor Or Self ( psi Type 2 , Ġpsi Type 1 , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtype 2 Ġ== Ġtype 1 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ