11use crate :: model:: {
2- Argument , Arguments , Attribute , Class , Function , Module , TypeHint , TypeHintExpr ,
3- VariableLengthArgument ,
2+ Argument , Arguments , Attribute , Class , Function , Module , PythonIdentifier , TypeHint ,
3+ TypeHintExpr , VariableLengthArgument ,
44} ;
55use anyhow:: { anyhow, bail, ensure, Context , Result } ;
66use goblin:: elf:: section_header:: SHN_XINDEX ;
@@ -134,7 +134,7 @@ fn convert_members<'a>(
134134 parent : _,
135135 decorators,
136136 returns,
137- } => functions. push ( convert_function ( name, arguments, decorators, returns) ) ,
137+ } => functions. push ( convert_function ( name, arguments, decorators, returns) ? ) ,
138138 Chunk :: Attribute {
139139 name,
140140 id : _,
@@ -149,14 +149,24 @@ fn convert_members<'a>(
149149 classes. sort_by ( |l, r| l. name . cmp ( & r. name ) ) ;
150150 functions. sort_by ( |l, r| match l. name . cmp ( & r. name ) {
151151 Ordering :: Equal => {
152- // We put the getter before the setter
153- if l. decorators . iter ( ) . any ( |d| d == "property" ) {
152+ // We put the getter before the setter. For that, we put @property before the other ones
153+ if l. decorators
154+ . iter ( )
155+ . any ( |d| d. name == "property" && d. module . as_deref ( ) == Some ( "builtins" ) )
156+ {
154157 Ordering :: Less
155- } else if r. decorators . iter ( ) . any ( |d| d == "property" ) {
158+ } else if r
159+ . decorators
160+ . iter ( )
161+ . any ( |d| d. name == "property" && d. module . as_deref ( ) == Some ( "builtins" ) )
162+ {
156163 Ordering :: Greater
157164 } else {
158165 // We pick an ordering based on decorators
159- l. decorators . cmp ( & r. decorators )
166+ l. decorators
167+ . iter ( )
168+ . map ( |d| & d. name )
169+ . cmp ( r. decorators . iter ( ) . map ( |d| & d. name ) )
160170 }
161171 }
162172 o => o,
@@ -194,12 +204,27 @@ fn convert_class(
194204fn convert_function (
195205 name : & str ,
196206 arguments : & ChunkArguments ,
197- decorators : & [ String ] ,
207+ decorators : & [ ChunkTypeHint ] ,
198208 returns : & Option < ChunkTypeHint > ,
199- ) -> Function {
200- Function {
209+ ) -> Result < Function > {
210+ Ok ( Function {
201211 name : name. into ( ) ,
202- decorators : decorators. to_vec ( ) ,
212+ decorators : decorators
213+ . iter ( )
214+ . map ( |d| match convert_type_hint ( d) {
215+ TypeHint :: Plain ( id) => Ok ( PythonIdentifier {
216+ module : None ,
217+ name : id. clone ( ) ,
218+ } ) ,
219+ TypeHint :: Ast ( expr) => {
220+ if let TypeHintExpr :: Identifier ( i) = expr {
221+ Ok ( i)
222+ } else {
223+ bail ! ( "A decorator must be the identifier of a Python function" )
224+ }
225+ }
226+ } )
227+ . collect :: < Result < _ > > ( ) ?,
203228 arguments : Arguments {
204229 positional_only_arguments : arguments. posonlyargs . iter ( ) . map ( convert_argument) . collect ( ) ,
205230 arguments : arguments. args . iter ( ) . map ( convert_argument) . collect ( ) ,
@@ -214,7 +239,7 @@ fn convert_function(
214239 . map ( convert_variable_length_argument) ,
215240 } ,
216241 returns : returns. as_ref ( ) . map ( convert_type_hint) ,
217- }
242+ } )
218243}
219244
220245fn convert_argument ( arg : & ChunkArgument ) -> Argument {
@@ -253,15 +278,24 @@ fn convert_type_hint(arg: &ChunkTypeHint) -> TypeHint {
253278
254279fn convert_type_hint_expr ( expr : & ChunkTypeHintExpr ) -> TypeHintExpr {
255280 match expr {
256- ChunkTypeHintExpr :: Local { id } => TypeHintExpr :: Local { id : id. clone ( ) } ,
257- ChunkTypeHintExpr :: Builtin { id } => TypeHintExpr :: Builtin { id : id. clone ( ) } ,
258- ChunkTypeHintExpr :: Attribute { module, attr } => TypeHintExpr :: Attribute {
259- module : module. clone ( ) ,
260- attr : attr. clone ( ) ,
261- } ,
262- ChunkTypeHintExpr :: Union { elts } => TypeHintExpr :: Union {
263- elts : elts. iter ( ) . map ( convert_type_hint_expr) . collect ( ) ,
264- } ,
281+ ChunkTypeHintExpr :: Local { id } => PythonIdentifier {
282+ module : None ,
283+ name : id. clone ( ) ,
284+ }
285+ . into ( ) ,
286+ ChunkTypeHintExpr :: Builtin { id } => PythonIdentifier {
287+ module : Some ( "builtins" . into ( ) ) ,
288+ name : id. clone ( ) ,
289+ }
290+ . into ( ) ,
291+ ChunkTypeHintExpr :: Attribute { module, attr } => PythonIdentifier {
292+ module : Some ( module. clone ( ) ) ,
293+ name : attr. clone ( ) ,
294+ }
295+ . into ( ) ,
296+ ChunkTypeHintExpr :: Union { elts } => {
297+ TypeHintExpr :: Union ( elts. iter ( ) . map ( convert_type_hint_expr) . collect ( ) )
298+ }
265299 ChunkTypeHintExpr :: Subscript { value, slice } => TypeHintExpr :: Subscript {
266300 value : Box :: new ( convert_type_hint_expr ( value) ) ,
267301 slice : slice. iter ( ) . map ( convert_type_hint_expr) . collect ( ) ,
@@ -419,8 +453,8 @@ enum Chunk {
419453 #[ serde( default ) ]
420454 parent : Option < String > ,
421455 #[ serde( default ) ]
422- decorators : Vec < String > ,
423- #[ serde( default , deserialize_with = "deserialize_type_hint" ) ]
456+ decorators : Vec < ChunkTypeHint > ,
457+ #[ serde( default ) ]
424458 returns : Option < ChunkTypeHint > ,
425459 } ,
426460 Attribute {
@@ -431,7 +465,7 @@ enum Chunk {
431465 name : String ,
432466 #[ serde( default ) ]
433467 value : Option < String > ,
434- #[ serde( default , deserialize_with = "deserialize_type_hint" ) ]
468+ #[ serde( default ) ]
435469 annotation : Option < ChunkTypeHint > ,
436470 } ,
437471}
@@ -455,7 +489,7 @@ struct ChunkArgument {
455489 name : String ,
456490 #[ serde( default ) ]
457491 default : Option < String > ,
458- #[ serde( default , deserialize_with = "deserialize_type_hint" ) ]
492+ #[ serde( default ) ]
459493 annotation : Option < ChunkTypeHint > ,
460494}
461495
@@ -467,6 +501,45 @@ enum ChunkTypeHint {
467501 Plain ( String ) ,
468502}
469503
504+ impl < ' de > Deserialize < ' de > for ChunkTypeHint {
505+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
506+ where
507+ D : Deserializer < ' de > ,
508+ {
509+ struct AnnotationVisitor ;
510+
511+ impl < ' de > Visitor < ' de > for AnnotationVisitor {
512+ type Value = ChunkTypeHint ;
513+
514+ fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
515+ formatter. write_str ( "annotation" )
516+ }
517+
518+ fn visit_str < E > ( self , v : & str ) -> Result < Self :: Value , E >
519+ where
520+ E : Error ,
521+ {
522+ self . visit_string ( v. into ( ) )
523+ }
524+
525+ fn visit_string < E > ( self , v : String ) -> Result < Self :: Value , E >
526+ where
527+ E : Error ,
528+ {
529+ Ok ( ChunkTypeHint :: Plain ( v) )
530+ }
531+
532+ fn visit_map < M : MapAccess < ' de > > ( self , map : M ) -> Result < ChunkTypeHint , M :: Error > {
533+ Ok ( ChunkTypeHint :: Ast ( Deserialize :: deserialize (
534+ MapAccessDeserializer :: new ( map) ,
535+ ) ?) )
536+ }
537+ }
538+
539+ deserializer. deserialize_any ( AnnotationVisitor )
540+ }
541+ }
542+
470543#[ derive( Deserialize ) ]
471544#[ serde( tag = "type" , rename_all = "lowercase" ) ]
472545enum ChunkTypeHintExpr {
@@ -488,39 +561,3 @@ enum ChunkTypeHintExpr {
488561 slice : Vec < ChunkTypeHintExpr > ,
489562 } ,
490563}
491-
492- fn deserialize_type_hint < ' de , D : Deserializer < ' de > > (
493- deserializer : D ,
494- ) -> Result < Option < ChunkTypeHint > , D :: Error > {
495- struct AnnotationVisitor ;
496-
497- impl < ' de > Visitor < ' de > for AnnotationVisitor {
498- type Value = ChunkTypeHint ;
499-
500- fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
501- formatter. write_str ( "annotation" )
502- }
503-
504- fn visit_str < E > ( self , v : & str ) -> Result < Self :: Value , E >
505- where
506- E : Error ,
507- {
508- self . visit_string ( v. into ( ) )
509- }
510-
511- fn visit_string < E > ( self , v : String ) -> Result < Self :: Value , E >
512- where
513- E : Error ,
514- {
515- Ok ( ChunkTypeHint :: Plain ( v) )
516- }
517-
518- fn visit_map < M : MapAccess < ' de > > ( self , map : M ) -> Result < ChunkTypeHint , M :: Error > {
519- Ok ( ChunkTypeHint :: Ast ( Deserialize :: deserialize (
520- MapAccessDeserializer :: new ( map) ,
521- ) ?) )
522- }
523- }
524-
525- Ok ( Some ( deserializer. deserialize_any ( AnnotationVisitor ) ?) )
526- }
0 commit comments