// ĠCopyright Ġ 2 0 0 0 - 2 0 2 1 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ package Ġorg . jetbrains . protocol Reader Ċ Ċ import Ġorg . jetbrains . io . Json Reader Ex Ċ import Ġorg . jetbrains . json Protocol . Json Field Ċ import Ġorg . jetbrains . json Protocol . Json Subtype Ċ import Ġorg . jetbrains . json Protocol . Optional Ċ import Ġorg . jetbrains . json Protocol . String Int Pair Ċ import Ġjava . lang . reflect . Method Ċ import Ġjava . lang . reflect . Parameterized Type Ċ import Ġjava . lang . reflect . Type Ċ import Ġjava . lang . reflect . Wildcard Type Ċ import Ġkotlin . reflect . K Callable Ċ Ċ internal Ġfun ĠInterface Reader ( protocol Interfaces : ĠList < Class <* >> ): ĠInterface Reader Ġ{ ĊĠ Ġval Ġmap Ġ= ĠLinkedHashMap < Class <* >, ĠType Writer < *> ? >( protocol Interfaces . size ) ĊĠ Ġfor Ġ( type Class Ġin Ġprotocol Interfaces ) Ġ{ ĊĠĠĠ Ġmap . put ( type Class , Ġnull ) ĊĠ Ġ} ĊĠ Ġreturn ĠInterface Reader ( map ) Ċ } Ċ Ċ private Ġval ĠLONG _ PARSER Ġ= ĠPrimitive Value Reader (" Long ", Ġ"- 1 L ") Ċ Ċ private Ġval ĠINTEGER _ PARSER Ġ= ĠPrimitive Value Reader (" Int ", Ġ"- 1 ") Ċ Ċ private Ġval ĠBOOLEAN _ PARSER Ġ= ĠPrimitive Value Reader (" Boolean ", Ġ" false ") Ċ private Ġval ĠFLOAT _ PARSER Ġ= ĠPrimitive Value Reader (" Float ") Ċ Ċ private Ġval ĠNUMBER _ PARSER Ġ= ĠPrimitive Value Reader (" Double ", Ġ" Double . NaN ") Ċ Ċ private Ġval ĠSTRING _ PARSER Ġ= ĠPrimitive Value Reader (" String ") Ċ private Ġval ĠNULL ABLE _ STRING _ PARSER Ġ= ĠPrimitive Value Reader ( className Ġ= Ġ" String ", Ġnullable Ġ= Ġtrue ) Ċ Ċ private Ġval ĠRAW _ STRING _ PARSER Ġ= ĠPrimitive Value Reader (" String ", Ġnull , Ġtrue ) Ċ private Ġval ĠRAW _ STRING _ OR _ MAP _ PARSER Ġ= Ġobject Ġ: ĠPrimitive Value Reader (" Any ", Ġnull , Ġtrue ) Ġ{ ĊĠ Ġoverride Ġfun Ġwrite Read Code ( scope : ĠClass Scope , Ġsub typing : ĠBoolean , Ġout : ĠText Output ) Ġ{ ĊĠĠĠ Ġout . append (" read Raw String Or Map (" ) ĊĠĠĠ Ġadd Reader Parameter ( sub typing , Ġout ) ĊĠĠĠ Ġout . append (' )') ĊĠ Ġ} Ċ } Ċ Ċ private Ġval ĠJSON _ PARSER Ġ= ĠRaw Value Reader () Ċ Ċ private Ġval ĠSTRING _ INT _ PAIR _ PARSER Ġ= ĠString Int Pair Value Reader () Ċ Ċ internal Ġval ĠVOID _ PARSER : ĠValue Reader Ġ= Ġobject Ġ: ĠValue Reader () Ġ{ ĊĠ Ġoverride Ġfun Ġappend Finished Value TypeName ( out : ĠText Output ) Ġ{ ĊĠĠĠ Ġout . append (" void ") ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġwrite Read Code ( scope : ĠClass Scope , Ġsub typing : ĠBoolean , Ġout : ĠText Output ) Ġ{ ĊĠĠĠ Ġout . append (" null ") ĊĠ Ġ} Ċ } Ċ Ċ internal Ġfun Ġcreate Handler ( type To Type Handler : ĠLinkedHashMap < Class <* >, ĠType Writer < *> ? >, Ġa Class : ĠClass < *> ): ĠType Writer < *> Ġ{ ĊĠ Ġval Ġreader Ġ= ĠInterface Reader ( type To Type Handler ) ĊĠ Ġreader . processed . addAll ( type To Type Handler . keys ) ĊĠ Ġreader . go ( array Of ( aClass )) ĊĠ Ġreturn Ġtype To Type Handler . get ( aClass ) !! Ċ } Ċ Ċ internal Ġclass ĠInterface Reader ( val Ġtype To Type Handler : ĠLinkedHashMap < Class <* >, ĠType Writer < *> ?> ) Ġ{ ĊĠ Ġval Ġprocessed Ġ= ĠHashSet < Class <* >>() ĊĠ Ġprivate Ġval Ġrefs Ġ= ĠArrayList < Type Ref <* >>() ĊĠ Ġval Ġsubtype Cast ers Ġ= ĠArrayList < Subtype C aster >() ĊĊĠ Ġfun Ġgo ( classes : ĠArray < Class <* >> Ġ= Ġtype To Type Handler . keys . to Typed Array ()): ĠLinkedHashMap < Class <* >, ĠType Writer < *> ?> Ġ{ ĊĠĠĠ Ġfor Ġ( type Class Ġin Ġclasses ) Ġ{ ĊĠĠĠĠĠ Ġcreate IfNot Exists ( type Class ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġhas Un resolved Ġ= Ġtrue ĊĠĠĠ Ġwhile Ġ( has Un resolved ) Ġ{ ĊĠĠĠĠĠ Ġhas Un resolved Ġ= Ġfalse ĊĠĠĠĠĠ Ġ// Ġrefs Ġcan Ġbe Ġmodified Ġ- Ġnew Ġitems Ġcan Ġbe Ġadded ĊĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. refs . size Ġ- Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġref : ĠType Ref < out ĠAny ?> Ġ= Ġrefs . get ( i ) ĊĠĠĠĠĠĠĠ Ġval Ġtype Class : ĠClass < out ĠAny ?> Ġ= Ġref . type Class ĊĠĠĠĠĠĠĠ Ġ( ref Ġas ĠType Ref < Any ?> ). type Ġ= Ġtype To Type Handler . get ( type Class ) Ġas ĠType Writer < Any ?> ? ĊĠĠĠĠĠĠĠ Ġif Ġ( ref . type Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcreate IfNot Exists ( type Class ) ĊĠĠĠĠĠĠĠĠĠ Ġhas Un resolved Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠ Ġ( ref Ġas ĠType Ref < Any ?> ). type Ġ= Ġtype To Type Handler . get ( type Class ) Ġas ĠType Writer < Any ?> ? Ġ?: Ġthrow ĠIllegalStateException () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfor Ġ( subtype C aster Ġin Ġsubtype Cast ers ) Ġ{ ĊĠĠĠĠĠ Ġsubtype C aster . getSub type Handler (). subtype Aspect ?. set Subtype C aster ( subtype C aster ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġtype To Type Handler ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcreate IfNot Exists ( type Class : ĠClass <* >) Ġ{ ĊĠĠĠ Ġif Ġ( type Class Ġ== ĠMap :: class . java Ġ|| Ġtype Class Ġ== ĠList :: class . java Ġ|| Ġ! type Class . is Interface ) Ġ{ ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ(! processed . add ( type Class )) Ġ{ ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġtype To Type Handler . put ( type Class , Ġnull ) ĊĊĠĠĠ Ġfor Ġ( aClass Ġin Ġtype Class . declared Classes ) Ġ{ ĊĠĠĠĠĠ Ġcreate IfNot Exists ( aClass ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ(! type Class . is Interface ) Ġ{ ĊĠĠĠĠĠ Ġthrow ĠJson Protocol Model ParseException (" Json Ġmodel Ġtype Ġshould Ġbe Ġinterface : Ġ${ type Class . name }") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġfields Ġ= ĠField Processor ( this , Ġtype Class ) ĊĠĠĠ Ġfor Ġ( method Ġin Ġfields . method Handler Map . keys ) Ġ{ ĊĠĠĠĠĠ Ġval ĠreturnType Ġ= Ġmethod . returnType ĊĠĠĠĠĠ Ġif Ġ( returnType Ġ!= Ġtype Class ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate IfNot Exists ( returnType ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġtype Writer Ġ= ĠType Writer ( type Class , Ġget Super class Ref ( type Class ), Ġfields . volatile Fields , Ġfields . method Handler Map , Ġfields . field Lo aders , Ġfields . lazy Read ) ĊĠĠĠ Ġfor Ġ( ref Ġin Ġrefs ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( ref . type Class Ġ== Ġtype Class ) Ġ{ ĊĠĠĠĠĠĠĠ Ġassert ( ref . type Ġ== Ġnull ) ĊĠĠĠĠĠĠĠ Ġ( ref Ġas ĠType Ref < Any ?> ). type Ġ= Ġtype Writer Ġas ĠType Writer < Any ?> ĊĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġtype To Type Handler . put ( type Class , Ġtype Writer ) ĊĠ Ġ} ĊĊĠ Ġfun Ġget FieldType Parser ( member : ĠK Callable < *> ?, Ġtype : ĠType , Ġis Sub typing : ĠBoolean , Ġmethod : ĠMethod ?): ĠValue Reader Ġ{ ĊĠĠĠ Ġif Ġ( type Ġis ĠClass <* >) Ġ{ ĊĠĠĠĠĠ Ġ@ Suppress (" PLATFORM _ CLASS _ MAP PED _ TO _ K OT LIN ") ĊĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġtype Ġ== Ġjava . lang . Long . TYPE Ġ-> ĠLONG _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠInteger . TYPE Ġ|| Ġtype Ġ== ĠInteger :: class . java Ġ-> ĠINTEGER _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== Ġjava . lang . Boolean . TYPE Ġ-> ĠBOOLEAN _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== Ġjava . lang . Float . TYPE Ġ-> ĠFLOAT _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠNumber :: class . java Ġ|| Ġtype Ġ== Ġjava . lang . Double . TYPE Ġ|| Ġtype Ġ== Ġjava . lang . Double :: class . java Ġ-> ĠNUMBER _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠVoid . TYPE Ġ-> ĠVOID _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠString :: class . java Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( method Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjson Field Ġ= Ġmember ?. annotation < Json Field >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( json Field Ġ!= Ġnull Ġ&& Ġjson Field . allow Any Primitive Value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠRAW _ STRING _ PARSER ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġif Ġ(( member ?. returnType ?. is Marked Nullable Ġ?: Ġfalse ) Ġ|| Ġmethod . getAnnotation < Optional >( Optional :: class . java ) Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠNULL ABLE _ STRING _ PARSER ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġreturn ĠSTRING _ PARSER ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠAny :: class . java Ġ-> ĠRAW _ STRING _ OR _ MAP _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠJson Reader Ex :: class . java Ġ-> ĠJSON _ PARSER ĊĠĠĠĠĠĠĠ Ġtype Ġ== ĠString Int Pair :: class . java Ġ-> ĠSTRING _ INT _ PAIR _ PARSER ĊĠĠĠĠĠĠĠ Ġtype . isArray Ġ-> ĠArray Reader ( getField Type Parser ( null , Ġtype . component Type , Ġfalse , Ġnull ), Ġfalse ) ĊĠĠĠĠĠĠĠ Ġtype . is Enum Ġ-> ĠEnum Reader ( type Ġas ĠClass < Enum <* >>) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġref Ġ= ĠgetType Ref ( type ) Ġ?: Ġthrow ĠUnsupportedOperationException (" Method Ġreturn Ġtype Ġ$ type Ġ( simple Ġclass ) Ġnot Ġsupported ") ĊĠĠĠĠĠĠĠĠĠ ĠObject Value Reader ( ref , Ġis Sub typing , Ġmethod ?. getAnnotation < Json Field >( Json Field :: class . java )?. primitive Value , Ġmember ?. returnType ?. is Marked Nullable Ġ?: Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġif Ġ( type Ġis ĠParameter ized Type ) Ġ{ ĊĠĠĠĠĠ Ġval Ġis List Ġ= Ġtype . raw Type Ġ== ĠList :: class . java ĊĠĠĠĠĠ Ġif Ġ( is List Ġ|| Ġtype . raw Type Ġ== ĠMap :: class . java ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġargument Type Ġ= Ġtype . actual Type Arguments [ if Ġ( is List ) Ġ 0 Ġelse Ġ 1 ] ĊĠĠĠĠĠĠĠ Ġif Ġ( argument Type Ġis ĠW ildcard Type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġwildcard Ġ= Ġargument Type ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( wildcard . lower Bounds . size Ġ== Ġ 0 Ġ&& Ġwildcard . upper Bounds . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġargument Type Ġ= Ġwildcard . upper Bounds [ 0 ] ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġcomponent Parser Ġ= Ġget FieldType Parser ( null , Ġargument Type , Ġfalse , Ġmethod ) ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( is List ) ĠArray Reader ( component Parser , Ġtrue ) Ġelse ĠMap Reader ( component Parser ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException (" Method Ġreturn Ġtype Ġ$ type Ġ( generic ) Ġnot Ġsupported ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException (" Method Ġreturn Ġtype Ġ$ type Ġnot Ġsupported ") ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġ< T > ĠgetType Ref ( type Class : ĠClass < T >): ĠType Ref < T >? Ġ{ ĊĠĠĠ Ġval Ġresult Ġ= ĠType Ref ( type Class ) ĊĠĠĠ Ġrefs . add ( result ) ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġget Super class Ref ( type Class : ĠClass < *> ): ĠType Ref < *> ? Ġ{ ĊĠĠĠ Ġvar Ġresult : ĠType Ref < *> ? Ġ= Ġnull ĊĠĠĠ Ġfor Ġ( interface Generic Ġin Ġtype Class . generic Interfaces ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( interface Generic Ġ! is ĠParameter ized Type ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġif Ġ( interface Generic . raw Type Ġ!= ĠJson Subtype :: class . java ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġparam Ġ= Ġinterface Generic . actual Type Arguments [ 0 ] ĊĠĠĠĠĠ Ġif Ġ( param Ġ! is ĠClass <* >) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠJson Protocol Model ParseException (" Unexpected Ġtype Ġof Ġsuperclass Ġ$ param ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġif Ġ( result Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠJson Protocol Model ParseException (" Already Ġhas Ġsuperclass Ġ${ result . type Class . name }") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġresult Ġ= ĠgetType Ref ( param ) ĊĠĠĠĠĠ Ġif Ġ( result Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠJson Protocol Model ParseException (" Unknown Ġbase Ġclass Ġ${ param . name }") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} Ċ }