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
4243from sphinx .util .typing import OptionSpec
4344
4748DeclarationType = Union [
4849 "ASTStruct" , "ASTUnion" , "ASTEnum" , "ASTEnumerator" ,
4950 "ASTType" , "ASTTypeWithInit" , "ASTMacro" ,
51+ "ASTIntersphinx_v2" ,
5052]
5153
5254# https://en.cppreference.com/w/c/keyword
@@ -1360,6 +1362,28 @@ def describe_signature(self, signode: TextElement, mode: str,
13601362 self .init .describe_signature (signode , 'markType' , env , symbol )
13611363
13621364
1365+ class ASTIntersphinx_v2 (ASTBaseBase ):
1366+ def __init__ (self , name : ASTNestedName , data : InventoryItemSet ):
1367+ self .name = name
1368+ self .data = data
1369+
1370+ def _stringify (self , transform : StringifyTransform ) -> str :
1371+ return transform (self .name ) + " (has data)"
1372+
1373+ def get_id (self , version : int , objectType : str , symbol : "Symbol" ) -> str :
1374+ return symbol .get_full_nested_name ().get_id (version )
1375+
1376+ def describe_signature (self , signode : TextElement , mode : str ,
1377+ env : "BuildEnvironment" , symbol : "Symbol" ) -> None :
1378+ assert False # Should not happen
1379+
1380+ @property
1381+ def function_params (self ):
1382+ # the v2 data does not contain actual declarations, but just names
1383+ # so return nothing here
1384+ return None
1385+
1386+
13631387class ASTDeclaration (ASTBaseBase ):
13641388 def __init__ (self , objectType : str , directiveType : str ,
13651389 declaration : Union [DeclarationType , ASTFunctionParameter ],
@@ -3745,6 +3769,10 @@ class CDomain(Domain):
37453769 'objects' : {}, # fullname -> docname, node_id, objtype
37463770 }
37473771
3772+ initial_intersphinx_inventory = {
3773+ 'root_symbol' : Symbol (None , None , None , None , None ),
3774+ }
3775+
37483776 def clear_doc (self , docname : str ) -> None :
37493777 if Symbol .debug_show_tree :
37503778 print ("clear_doc:" , docname )
@@ -3791,9 +3819,10 @@ def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
37913819 ourObjects [fullname ] = (fn , id_ , objtype )
37923820 # no need to warn on duplicates, the symbol merge already does that
37933821
3794- def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3795- typ : str , target : str , node : pending_xref ,
3796- contnode : Element ) -> Tuple [Element , str ]:
3822+ def _resolve_xref_in_tree (self , env : BuildEnvironment , root : Symbol ,
3823+ softParent : bool ,
3824+ typ : str , target : str , node : pending_xref ,
3825+ contnode : Element ) -> Tuple [Symbol , ASTNestedName ]:
37973826 parser = DefinitionParser (target , location = node , config = env .config )
37983827 try :
37993828 name = parser .parse_xref_object ()
@@ -3802,20 +3831,34 @@ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder:
38023831 location = node )
38033832 return None , None
38043833 parentKey : LookupKey = node .get ("c:parent_key" , None )
3805- rootSymbol = self .data ['root_symbol' ]
38063834 if parentKey :
3807- parentSymbol : Symbol = rootSymbol .direct_lookup (parentKey )
3835+ parentSymbol : Symbol = root .direct_lookup (parentKey )
38083836 if not parentSymbol :
3809- print ("Target: " , target )
3810- print ("ParentKey: " , parentKey )
3811- print (rootSymbol .dump (1 ))
3812- assert parentSymbol # should be there
3837+ if softParent :
3838+ parentSymbol = root
3839+ else :
3840+ print ("Target: " , target )
3841+ print ("ParentKey: " , parentKey )
3842+ print (root .dump (1 ))
3843+ assert False
38133844 else :
3814- parentSymbol = rootSymbol
3845+ parentSymbol = root
38153846 s = parentSymbol .find_declaration (name , typ ,
38163847 matchSelf = True , recurseInAnon = True )
38173848 if s is None or s .declaration is None :
38183849 return None , None
3850+ # TODO: conditionally warn about xrefs with incorrect tagging?
3851+ return s , name
3852+
3853+ def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
3854+ typ : str , target : str , node : pending_xref ,
3855+ contnode : Element ) -> Tuple [Element , str ]:
3856+ if Symbol .debug_lookup :
3857+ print ("C._resolve_xref_inner(type={}, target={})" .format (typ , target ))
3858+ s , name = self ._resolve_xref_in_tree (env , self .data ['root_symbol' ],
3859+ False , typ , target , node , contnode )
3860+ if s is None :
3861+ return None , None
38193862
38203863 # TODO: check role type vs. object type
38213864
@@ -3858,6 +3901,47 @@ def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
38583901 newestId = symbol .declaration .get_newest_id ()
38593902 yield (name , dispname , objectType , docname , newestId , 1 )
38603903
3904+ def intersphinx_add_entries_v2 (self , store : Dict ,
3905+ data : Dict [Tuple [str , str ], InventoryItemSet ]) -> None :
3906+ root = store ['root_symbol' ] # type: Symbol
3907+ for k , v in data .items ():
3908+ object_name , object_type = k
3909+ parser = DefinitionParser (
3910+ object_name , location = ('intersphinx' , 0 ), config = self .env .config )
3911+ try :
3912+ ast = parser ._parse_nested_name ()
3913+ except DefinitionError as e :
3914+ logger .warning ("Error in C entry in intersphinx inventory:\n " + str (e ))
3915+ continue
3916+ decl = ASTDeclaration (object_type , 'intersphinx' , ASTIntersphinx_v2 (ast , v ))
3917+ root .add_declaration (decl , docname = "$FakeIntersphinxDoc" , line = 0 )
3918+
3919+ def _intersphinx_resolve_xref_inner (self , env : "BuildEnvironment" , store : Dict ,
3920+ target : str ,
3921+ node : pending_xref , contnode : TextElement ,
3922+ typ : str ) -> Optional [Element ]:
3923+ if Symbol .debug_lookup :
3924+ print ("C._intersphinx_resolve_xref_inner(type={}, target={})" .format (typ , target ))
3925+ s , name = self ._resolve_xref_in_tree (env , store ['root_symbol' ],
3926+ True , typ , target , node , contnode )
3927+ if s is None :
3928+ return None
3929+ assert s .declaration is not None
3930+ decl = cast (ASTIntersphinx_v2 , s .declaration .declaration )
3931+ return decl .data .make_refnode (self .name , target , node , contnode )
3932+
3933+ def intersphinx_resolve_xref (self , env : "BuildEnvironment" , store : Dict ,
3934+ typ : str , target : str , node : pending_xref ,
3935+ contnode : TextElement ) -> Optional [Element ]:
3936+ return self ._intersphinx_resolve_xref_inner (env , store , target , node , contnode , typ )
3937+
3938+ def intersphinx_resolve_any_xref (self , env : "BuildEnvironment" , store : Dict ,
3939+ target : str , node : pending_xref ,
3940+ contnode : TextElement ) -> Optional [Element ]:
3941+ with logging .suppress_logging ():
3942+ return self ._intersphinx_resolve_xref_inner (
3943+ env , store , target , node , contnode , 'any' )
3944+
38613945
38623946def setup (app : Sphinx ) -> Dict [str , Any ]:
38633947 app .add_domain (CDomain )
0 commit comments