7
7
import typing
8
8
from collections .abc import Iterable , Iterator , Sequence
9
9
from errno import ENOENT
10
- from functools import cache
10
+ from functools import cache , wraps
11
11
from inspect import isclass
12
12
from json import load
13
13
from operator import attrgetter
28
28
MIN_TYPEDOC_VERSION = (0 , 25 , 0 )
29
29
30
30
31
+ T = typing .TypeVar ("T" )
32
+ P = typing .ParamSpec ("P" )
33
+
34
+
35
+ def post_convert (f : typing .Callable [P , T ]) -> typing .Callable [P , T ]:
36
+ """Wrap to_ir with a call to post_convert if it returned a result.
37
+
38
+ I treid to be more specific about the type of the decorator but it caused
39
+ mypy to change the type of the decorated function. This signature ensures
40
+ that the inferred type of the decorated method is identical to the type of
41
+ the original method and then uses a couple of carefully placed casts.
42
+ """
43
+
44
+ @wraps (f )
45
+ def wrapper (* args : P .args , ** kwargs : P .kwargs ) -> T :
46
+ result = f (* args , ** kwargs )
47
+ converted , * _ = typing .cast (tuple [ir .TopLevel | None , ...], result )
48
+ if converted :
49
+ self , converter = typing .cast (tuple [Node | Signature , Converter ], args )
50
+ converter ._post_convert (converter , self , converted )
51
+ return result
52
+
53
+ return wrapper
54
+
55
+
31
56
@cache
32
57
def typedoc_version_info (typedoc : str ) -> tuple [tuple [int , ...], tuple [int , ...]]:
33
58
result = subprocess .run (
@@ -494,6 +519,7 @@ def _top_level_properties(self) -> TopLevelPropertiesDict:
494
519
exported_from = ir .Pathname (self .filepath ),
495
520
)
496
521
522
+ @post_convert
497
523
def to_ir (
498
524
self , converter : Converter
499
525
) -> tuple [ir .TopLevel | None , Sequence ["Node" ]]:
@@ -528,6 +554,7 @@ def comment(self) -> Comment:
528
554
return self .setSignature .comment
529
555
return self .comment_
530
556
557
+ @post_convert
531
558
def to_ir (self , converter : Converter ) -> tuple [ir .Attribute , Sequence ["Node" ]]:
532
559
if self .getSignature :
533
560
# There's no signature to speak of for a getter: only a return type.
@@ -578,6 +605,7 @@ def comment(self) -> Comment:
578
605
def _path_segments (self , base_dir : str ) -> list [str ]:
579
606
return [self .name ]
580
607
608
+ @post_convert
581
609
def to_ir (
582
610
self , converter : Converter
583
611
) -> tuple [ir .Function | None , Sequence ["Node" ]]:
@@ -675,6 +703,7 @@ def _constructor_and_members(
675
703
class Class (ClassOrInterface ):
676
704
kindString : Literal ["Class" ]
677
705
706
+ @post_convert
678
707
def to_ir (self , converter : Converter ) -> tuple [ir .Class | None , Sequence ["Node" ]]:
679
708
constructor , members = self ._constructor_and_members (converter )
680
709
result = ir .Class (
@@ -694,6 +723,7 @@ def to_ir(self, converter: Converter) -> tuple[ir.Class | None, Sequence["Node"]
694
723
class Interface (ClassOrInterface ):
695
724
kindString : Literal ["Interface" ]
696
725
726
+ @post_convert
697
727
def to_ir (self , converter : Converter ) -> tuple [ir .Interface , Sequence ["Node" ]]:
698
728
_ , members = self ._constructor_and_members (converter )
699
729
result = ir .Interface (
@@ -718,6 +748,7 @@ def children_with_ids(self) -> Iterator["IndexType"]:
718
748
if isinstance (self .type , ReflectionType ):
719
749
yield self .type .declaration
720
750
751
+ @post_convert
721
752
def to_ir (
722
753
self , converter : Converter
723
754
) -> tuple [ir .Attribute | ir .Function | None , Sequence ["Node" ]]:
@@ -793,6 +824,7 @@ def render(self, converter: Converter) -> Iterator[str | ir.TypeXRef]:
793
824
yield "; "
794
825
yield "}"
795
826
827
+ @post_convert
796
828
def to_ir (
797
829
self , converter : Converter
798
830
) -> tuple [ir .Function | None , Sequence ["Node" ]]:
@@ -1024,9 +1056,13 @@ def inner(param: Param) -> Iterator[str | ir.TypeXRef]:
1024
1056
else :
1025
1057
yield ir .TypeXRefIntrinsic ("void" )
1026
1058
1059
+ # Don't wrap this in @post_convert since it'll always be covered by the
1060
+ # owner of the signature.
1027
1061
def to_ir (
1028
1062
self , converter : Converter
1029
1063
) -> tuple [ir .Function | None , Sequence ["Node" ]]:
1064
+ # TODO: The following shouldn't happen in to_ir since it mutates the
1065
+ # Node
1030
1066
SYMBOL_PREFIX = "[Symbol\u2024 "
1031
1067
if self .name .startswith ("[" ) and not self .name .startswith (SYMBOL_PREFIX ):
1032
1068
# a symbol.
0 commit comments