22
33from __future__ import annotations
44
5- from typing import TYPE_CHECKING , Any , ClassVar
5+ from typing import TYPE_CHECKING , Any , ClassVar , cast
66
77from docutils import nodes
88from docutils .parsers .rst import directives
1313from sphinx .domains .c ._ast import (
1414 ASTDeclaration ,
1515 ASTIdentifier ,
16+ ASTIntersphinx_v2 ,
1617 ASTNestedName ,
1718)
1819from sphinx .domains .c ._ids import _macroKeywords , _max_id
@@ -666,6 +667,10 @@ class CDomain(Domain):
666667 'objects' : {}, # fullname -> docname, node_id, objtype
667668 }
668669
670+ initial_intersphinx_inventory = {
671+ 'root_symbol' : Symbol (None , None , None , None , None ),
672+ }
673+
669674 def clear_doc (self , docname : str ) -> None :
670675 if Symbol .debug_show_tree :
671676 logger .debug ("clear_doc: %s" , docname )
@@ -712,9 +717,10 @@ def merge_domaindata(self, docnames: list[str], otherdata: dict[str, Any]) -> No
712717 ourObjects [fullname ] = (fn , id_ , objtype )
713718 # no need to warn on duplicates, the symbol merge already does that
714719
715- def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
716- typ : str , target : str , node : pending_xref ,
717- contnode : Element ) -> tuple [Element | None , str | None ]:
720+ def _resolve_xref_in_tree (self , env : BuildEnvironment , root : Symbol ,
721+ softParent : bool ,
722+ typ : str , target : str ,
723+ node : pending_xref ) -> tuple [Symbol , ASTNestedName ]:
718724 parser = DefinitionParser (target , location = node , config = env .config )
719725 try :
720726 name = parser .parse_xref_object ()
@@ -723,20 +729,32 @@ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder:
723729 location = node )
724730 return None , None
725731 parentKey : LookupKey = node .get ("c:parent_key" , None )
726- rootSymbol = self .data ['root_symbol' ]
727732 if parentKey :
728- parentSymbol : Symbol = rootSymbol .direct_lookup (parentKey )
733+ parentSymbol : Symbol = root .direct_lookup (parentKey )
729734 if not parentSymbol :
730- logger .debug ("Target: %s" , target )
731- logger .debug ("ParentKey: %s" , parentKey )
732- logger .debug (rootSymbol .dump (1 ))
733- assert parentSymbol # should be there
735+ if softParent :
736+ parentSymbol = root
737+ else :
738+ msg = f"Target: { target } \n ParentKey: { parentKey } \n { root .dump (1 )} \n "
739+ raise AssertionError (msg )
734740 else :
735- parentSymbol = rootSymbol
741+ parentSymbol = root
736742 s = parentSymbol .find_declaration (name , typ ,
737743 matchSelf = True , recurseInAnon = True )
738744 if s is None or s .declaration is None :
739745 return None , None
746+ # TODO: conditionally warn about xrefs with incorrect tagging?
747+ return s , name
748+
749+ def _resolve_xref_inner (self , env : BuildEnvironment , fromdocname : str , builder : Builder ,
750+ typ : str , target : str , node : pending_xref ,
751+ contnode : Element ) -> tuple [Element , str ]:
752+ if Symbol .debug_lookup :
753+ Symbol .debug_print ("C._resolve_xref_inner(type={}, target={})" .format (typ , target ))
754+ s , name = self ._resolve_xref_in_tree (env , self .data ['root_symbol' ],
755+ False , typ , target , node )
756+ if s is None :
757+ return None , None
740758
741759 # TODO: check role type vs. object type
742760
@@ -779,6 +797,51 @@ def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
779797 newestId = symbol .declaration .get_newest_id ()
780798 yield (name , dispname , objectType , docname , newestId , 1 )
781799
800+ def intersphinx_add_entries_v2 (self , store : dict ,
801+ data : dict [str , dict [str , Any ]]) -> None :
802+ root = store ['root_symbol' ] # type: Symbol
803+ for object_type , per_type_data in data .items ():
804+ for object_name , item_set in per_type_data .items ():
805+ parser = DefinitionParser (
806+ object_name , location = ('intersphinx' , 0 ), config = self .env .config )
807+ try :
808+ ast = parser ._parse_nested_name ()
809+ except DefinitionError as e :
810+ logger .warning ("Error in C entry in intersphinx inventory:\n " + str (e ))
811+ continue
812+ decl = ASTDeclaration (object_type , 'intersphinx' ,
813+ ASTIntersphinx_v2 (ast , item_set ))
814+ root .add_declaration (decl , docname = "$FakeIntersphinxDoc" , line = 0 )
815+
816+ def _intersphinx_resolve_xref_inner (self , env : "BuildEnvironment" , store : dict ,
817+ target : str ,
818+ node : pending_xref ,
819+ typ : str ) -> Any | None :
820+ if Symbol .debug_lookup :
821+ Symbol .debug_print (
822+ f"C._intersphinx_resolve_xref_inner(type={ typ } , target={ target } )" )
823+ s , name = self ._resolve_xref_in_tree (env , store ['root_symbol' ],
824+ True , typ , target , node )
825+ if s is None :
826+ return None
827+ assert s .declaration is not None
828+ decl = cast (ASTIntersphinx_v2 , s .declaration .declaration )
829+ return decl .data
830+
831+ def intersphinx_resolve_xref (self , env : "BuildEnvironment" ,
832+ store : Any ,
833+ typ : str , target : str ,
834+ disabled_object_types : list [str ],
835+ node : pending_xref , contnode : Element
836+ ) -> Any | None :
837+ if typ == 'any' :
838+ with logging .suppress_logging ():
839+ return self ._intersphinx_resolve_xref_inner (
840+ env , store , target , node , typ )
841+ else :
842+ return self ._intersphinx_resolve_xref_inner (
843+ env , store , target , node , typ )
844+
782845
783846def setup (app : Sphinx ) -> ExtensionMetadata :
784847 app .add_domain (CDomain )
0 commit comments