99"""
1010
1111import 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 )
1414
1515from docutils import nodes
1616from docutils .nodes import Element , Node , TextElement , system_message
3838 octal_literal_re , verify_description_mode )
3939from sphinx .util .docfields import Field , TypedField
4040from sphinx .util .docutils import SphinxDirective
41+ from sphinx .util .inventory import InventoryItemSet
4142from sphinx .util .nodes import make_refnode
4243
4344logger = logging .getLogger (__name__ )
4647DeclarationType = Union [
4748 "ASTStruct" , "ASTUnion" , "ASTEnum" , "ASTEnumerator" ,
4849 "ASTType" , "ASTTypeWithInit" , "ASTMacro" ,
50+ "ASTIntersphinx_v2" ,
4951]
5052
5153# https://en.cppreference.com/w/c/keyword
@@ -1350,6 +1352,28 @@ def describe_signature(self, signode: TextElement, mode: str,
13501352 self .init .describe_signature (signode , 'markType' , env , symbol )
13511353
13521354
1355+ class ASTIntersphinx_v2 (ASTBaseBase ):
1356+ def __init__ (self , name : ASTNestedName , data : InventoryItemSet ):
1357+ self .name = name
1358+ self .data = data
1359+
1360+ def _stringify (self , transform : StringifyTransform ) -> str :
1361+ return transform (self .name ) + " (has data)"
1362+
1363+ def get_id (self , version : int , objectType : str , symbol : "Symbol" ) -> str :
1364+ return symbol .get_full_nested_name ().get_id (version )
1365+
1366+ def describe_signature (self , signode : TextElement , mode : str ,
1367+ env : "BuildEnvironment" , symbol : "Symbol" ) -> None :
1368+ assert False # Should not happen
1369+
1370+ @property
1371+ def function_params (self ):
1372+ # the v2 data does not contain actual declarations, but just names
1373+ # so return nothing here
1374+ return None
1375+
1376+
13531377class ASTDeclaration (ASTBaseBase ):
13541378 def __init__ (self , objectType : str , directiveType : str ,
13551379 declaration : Union [DeclarationType , ASTFunctionParameter ],
@@ -3735,6 +3759,10 @@ class CDomain(Domain):
37353759 'objects' : {}, # fullname -> docname, node_id, objtype
37363760 } # type: Dict[str, Union[Symbol, Dict[str, Tuple[str, str, str]]]]
37373761
3762+ initial_intersphinx_inventory = {
3763+ 'root_symbol' : Symbol (None , None , None , None , None ),
3764+ }
3765+
37383766 def clear_doc (self , docname : str ) -> None :
37393767 if Symbol .debug_show_tree :
37403768 print ("clear_doc:" , docname )
@@ -3781,9 +3809,10 @@ def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
37813809 ourObjects [fullname ] = (fn , id_ , objtype )
37823810 # no need to warn on duplicates, the symbol merge already does that
37833811
3784- def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3785- typ : str , target : str , node : pending_xref ,
3786- contnode : Element ) -> Tuple [Element , str ]:
3812+ def _resolve_xref_in_tree (self , env : BuildEnvironment , root : Symbol ,
3813+ softParent : bool ,
3814+ typ : str , target : str , node : pending_xref ,
3815+ contnode : Element ) -> Tuple [Symbol , ASTNestedName ]:
37873816 parser = DefinitionParser (target , location = node , config = env .config )
37883817 try :
37893818 name = parser .parse_xref_object ()
@@ -3792,20 +3821,34 @@ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder:
37923821 location = node )
37933822 return None , None
37943823 parentKey = node .get ("c:parent_key" , None ) # type: LookupKey
3795- rootSymbol = self .data ['root_symbol' ]
37963824 if parentKey :
3797- parentSymbol = rootSymbol .direct_lookup (parentKey ) # type: Symbol
3825+ parentSymbol = root .direct_lookup (parentKey ) # type: Symbol
37983826 if not parentSymbol :
3799- print ("Target: " , target )
3800- print ("ParentKey: " , parentKey )
3801- print (rootSymbol .dump (1 ))
3802- assert parentSymbol # should be there
3827+ if softParent :
3828+ parentSymbol = root
3829+ else :
3830+ print ("Target: " , target )
3831+ print ("ParentKey: " , parentKey )
3832+ print (root .dump (1 ))
3833+ assert False
38033834 else :
3804- parentSymbol = rootSymbol
3835+ parentSymbol = root
38053836 s = parentSymbol .find_declaration (name , typ ,
38063837 matchSelf = True , recurseInAnon = True )
38073838 if s is None or s .declaration is None :
38083839 return None , None
3840+ # TODO: conditionally warn about xrefs with incorrect tagging?
3841+ return s , name
3842+
3843+ def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3844+ typ : str , target : str , node : pending_xref ,
3845+ contnode : Element ) -> Tuple [Element , str ]:
3846+ if Symbol .debug_lookup :
3847+ print ("C._resolve_xref_inner(type={}, target={})" .format (typ , target ))
3848+ s , name = self ._resolve_xref_in_tree (env , self .data ['root_symbol' ],
3849+ False , typ , target , node , contnode )
3850+ if s is None :
3851+ return None , None
38093852
38103853 # TODO: check role type vs. object type
38113854
@@ -3848,6 +3891,47 @@ def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
38483891 newestId = symbol .declaration .get_newest_id ()
38493892 yield (name , dispname , objectType , docname , newestId , 1 )
38503893
3894+ def intersphinx_add_entries_v2 (self , store : Dict ,
3895+ data : Dict [Tuple [str , str ], InventoryItemSet ]) -> None :
3896+ root = store ['root_symbol' ] # type: Symbol
3897+ for k , v in data .items ():
3898+ object_name , object_type = k
3899+ parser = DefinitionParser (
3900+ object_name , location = ('intersphinx' , 0 ), config = self .env .config )
3901+ try :
3902+ ast = parser ._parse_nested_name ()
3903+ except DefinitionError as e :
3904+ logger .warning ("Error in C entry in intersphinx inventory:\n " + str (e ))
3905+ continue
3906+ decl = ASTDeclaration (object_type , 'intersphinx' , ASTIntersphinx_v2 (ast , v ))
3907+ root .add_declaration (decl , docname = "$FakeIntersphinxDoc" , line = 0 )
3908+
3909+ def _intersphinx_resolve_xref_inner (self , env : "BuildEnvironment" , store : Dict ,
3910+ target : str ,
3911+ node : pending_xref , contnode : TextElement ,
3912+ typ : str ) -> Optional [Element ]:
3913+ if Symbol .debug_lookup :
3914+ print ("C._intersphinx_resolve_xref_inner(type={}, target={})" .format (typ , target ))
3915+ s , name = self ._resolve_xref_in_tree (env , store ['root_symbol' ],
3916+ True , typ , target , node , contnode )
3917+ if s is None :
3918+ return None
3919+ assert s .declaration is not None
3920+ decl = cast (ASTIntersphinx_v2 , s .declaration .declaration )
3921+ return decl .data .make_refnode (self .name , target , node , contnode )
3922+
3923+ def intersphinx_resolve_xref (self , env : "BuildEnvironment" , store : Dict ,
3924+ typ : str , target : str , node : pending_xref ,
3925+ contnode : TextElement ) -> Optional [Element ]:
3926+ return self ._intersphinx_resolve_xref_inner (env , store , target , node , contnode , typ )
3927+
3928+ def intersphinx_resolve_any_xref (self , env : "BuildEnvironment" , store : Dict ,
3929+ target : str , node : pending_xref ,
3930+ contnode : TextElement ) -> Optional [Element ]:
3931+ with logging .suppress_logging ():
3932+ return self ._intersphinx_resolve_xref_inner (
3933+ env , store , target , node , contnode , 'any' )
3934+
38513935
38523936def setup (app : Sphinx ) -> Dict [str , Any ]:
38533937 app .add_domain (CDomain )
0 commit comments