9
9
"""
10
10
11
11
import re
12
- from typing import (Any , Callable , Dict , Generator , Iterator , List , Tuple , Type , TypeVar ,
13
- Union , cast )
12
+ from typing import (Any , Callable , Dict , Generator , Iterator , List , Optional , Tuple , Type ,
13
+ TypeVar , Union , cast )
14
14
15
15
from docutils import nodes
16
16
from docutils .nodes import Element , Node , TextElement , system_message
38
38
octal_literal_re , verify_description_mode )
39
39
from sphinx .util .docfields import Field , TypedField
40
40
from sphinx .util .docutils import SphinxDirective
41
+ from sphinx .util .inventory import InventoryItemSet
41
42
from sphinx .util .nodes import make_refnode
42
43
43
44
logger = logging .getLogger (__name__ )
46
47
DeclarationType = Union [
47
48
"ASTStruct" , "ASTUnion" , "ASTEnum" , "ASTEnumerator" ,
48
49
"ASTType" , "ASTTypeWithInit" , "ASTMacro" ,
50
+ "ASTIntersphinx_v2" ,
49
51
]
50
52
51
53
# https://en.cppreference.com/w/c/keyword
@@ -1341,6 +1343,28 @@ def describe_signature(self, signode: TextElement, mode: str,
1341
1343
self .init .describe_signature (signode , 'markType' , env , symbol )
1342
1344
1343
1345
1346
+ class ASTIntersphinx_v2 (ASTBaseBase ):
1347
+ def __init__ (self , name : ASTNestedName , data : InventoryItemSet ):
1348
+ self .name = name
1349
+ self .data = data
1350
+
1351
+ def _stringify (self , transform : StringifyTransform ) -> str :
1352
+ return transform (self .name ) + " (has data)"
1353
+
1354
+ def get_id (self , version : int , objectType : str , symbol : "Symbol" ) -> str :
1355
+ return symbol .get_full_nested_name ().get_id (version )
1356
+
1357
+ def describe_signature (self , signode : TextElement , mode : str ,
1358
+ env : "BuildEnvironment" , symbol : "Symbol" ) -> None :
1359
+ assert False # Should not happen
1360
+
1361
+ @property
1362
+ def function_params (self ):
1363
+ # the v2 data does not contain actual declarations, but just names
1364
+ # so return nothing here
1365
+ return None
1366
+
1367
+
1344
1368
class ASTDeclaration (ASTBaseBase ):
1345
1369
def __init__ (self , objectType : str , directiveType : str ,
1346
1370
declaration : Union [DeclarationType , ASTFunctionParameter ],
@@ -3726,6 +3750,10 @@ class CDomain(Domain):
3726
3750
'objects' : {}, # fullname -> docname, node_id, objtype
3727
3751
} # type: Dict[str, Union[Symbol, Dict[str, Tuple[str, str, str]]]]
3728
3752
3753
+ initial_intersphinx_inventory = {
3754
+ 'root_symbol' : Symbol (None , None , None , None , None ),
3755
+ }
3756
+
3729
3757
def clear_doc (self , docname : str ) -> None :
3730
3758
if Symbol .debug_show_tree :
3731
3759
print ("clear_doc:" , docname )
@@ -3772,9 +3800,10 @@ def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
3772
3800
ourObjects [fullname ] = (fn , id_ , objtype )
3773
3801
# no need to warn on duplicates, the symbol merge already does that
3774
3802
3775
- def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3776
- typ : str , target : str , node : pending_xref ,
3777
- contnode : Element ) -> Tuple [Element , str ]:
3803
+ def _resolve_xref_in_tree (self , env : BuildEnvironment , root : Symbol ,
3804
+ softParent : bool ,
3805
+ typ : str , target : str , node : pending_xref ,
3806
+ contnode : Element ) -> Tuple [Symbol , ASTNestedName ]:
3778
3807
parser = DefinitionParser (target , location = node , config = env .config )
3779
3808
try :
3780
3809
name = parser .parse_xref_object ()
@@ -3783,20 +3812,34 @@ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder:
3783
3812
location = node )
3784
3813
return None , None
3785
3814
parentKey = node .get ("c:parent_key" , None ) # type: LookupKey
3786
- rootSymbol = self .data ['root_symbol' ]
3787
3815
if parentKey :
3788
- parentSymbol = rootSymbol .direct_lookup (parentKey ) # type: Symbol
3816
+ parentSymbol = root .direct_lookup (parentKey ) # type: Symbol
3789
3817
if not parentSymbol :
3790
- print ("Target: " , target )
3791
- print ("ParentKey: " , parentKey )
3792
- print (rootSymbol .dump (1 ))
3793
- assert parentSymbol # should be there
3818
+ if softParent :
3819
+ parentSymbol = root
3820
+ else :
3821
+ print ("Target: " , target )
3822
+ print ("ParentKey: " , parentKey )
3823
+ print (root .dump (1 ))
3824
+ assert False
3794
3825
else :
3795
- parentSymbol = rootSymbol
3826
+ parentSymbol = root
3796
3827
s = parentSymbol .find_declaration (name , typ ,
3797
3828
matchSelf = True , recurseInAnon = True )
3798
3829
if s is None or s .declaration is None :
3799
3830
return None , None
3831
+ # TODO: conditionally warn about xrefs with incorrect tagging?
3832
+ return s , name
3833
+
3834
+ def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3835
+ typ : str , target : str , node : pending_xref ,
3836
+ contnode : Element ) -> Tuple [Element , str ]:
3837
+ if Symbol .debug_lookup :
3838
+ print ("C._resolve_xref_inner(type={}, target={})" .format (typ , target ))
3839
+ s , name = self ._resolve_xref_in_tree (env , self .data ['root_symbol' ],
3840
+ False , typ , target , node , contnode )
3841
+ if s is None :
3842
+ return None , None
3800
3843
3801
3844
# TODO: check role type vs. object type
3802
3845
@@ -3839,6 +3882,47 @@ def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
3839
3882
newestId = symbol .declaration .get_newest_id ()
3840
3883
yield (name , dispname , objectType , docname , newestId , 1 )
3841
3884
3885
+ def intersphinx_add_entries_v2 (self , store : Dict ,
3886
+ data : Dict [Tuple [str , str ], InventoryItemSet ]) -> None :
3887
+ root = store ['root_symbol' ] # type: Symbol
3888
+ for k , v in data .items ():
3889
+ object_name , object_type = k
3890
+ parser = DefinitionParser (
3891
+ object_name , location = ('intersphinx' , 0 ), config = self .env .config )
3892
+ try :
3893
+ ast = parser ._parse_nested_name ()
3894
+ except DefinitionError as e :
3895
+ logger .warning ("Error in C entry in intersphinx inventory:\n " + str (e ))
3896
+ continue
3897
+ decl = ASTDeclaration (object_type , 'intersphinx' , ASTIntersphinx_v2 (ast , v ))
3898
+ root .add_declaration (decl , docname = "$FakeIntersphinxDoc" , line = 0 )
3899
+
3900
+ def _intersphinx_resolve_xref_inner (self , env : "BuildEnvironment" , store : Dict ,
3901
+ target : str ,
3902
+ node : pending_xref , contnode : TextElement ,
3903
+ typ : str ) -> Optional [Element ]:
3904
+ if Symbol .debug_lookup :
3905
+ print ("C._intersphinx_resolve_xref_inner(type={}, target={})" .format (typ , target ))
3906
+ s , name = self ._resolve_xref_in_tree (env , store ['root_symbol' ],
3907
+ True , typ , target , node , contnode )
3908
+ if s is None :
3909
+ return None
3910
+ assert s .declaration is not None
3911
+ decl = cast (ASTIntersphinx_v2 , s .declaration .declaration )
3912
+ return decl .data .make_refnode (self .name , target , node , contnode )
3913
+
3914
+ def intersphinx_resolve_xref (self , env : "BuildEnvironment" , store : Dict ,
3915
+ typ : str , target : str , node : pending_xref ,
3916
+ contnode : TextElement ) -> Optional [Element ]:
3917
+ return self ._intersphinx_resolve_xref_inner (env , store , target , node , contnode , typ )
3918
+
3919
+ def intersphinx_resolve_any_xref (self , env : "BuildEnvironment" , store : Dict ,
3920
+ target : str , node : pending_xref ,
3921
+ contnode : TextElement ) -> Optional [Element ]:
3922
+ with logging .suppress_logging ():
3923
+ return self ._intersphinx_resolve_xref_inner (
3924
+ env , store , target , node , contnode , 'any' )
3925
+
3842
3926
3843
3927
def setup (app : Sphinx ) -> Dict [str , Any ]:
3844
3928
app .add_domain (CDomain )
0 commit comments