Skip to content

Commit aab40ea

Browse files
committed
C, intersphinx delegation
1 parent 1e992d7 commit aab40ea

File tree

2 files changed

+100
-16
lines changed

2 files changed

+100
-16
lines changed

sphinx/domains/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
import copy
1313
from abc import ABC, abstractmethod
14-
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, List, NamedTuple,
15-
Optional, Tuple, Type, Union, cast)
14+
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, List, NamedTuple, Optional,
15+
Tuple, Type, Union, cast)
1616

1717
from docutils import nodes
1818
from docutils.nodes import Element, Node, TextElement, system_message
@@ -409,7 +409,7 @@ def get_full_qualified_name(self, node: Element) -> str:
409409
"""Return full qualified name for given node."""
410410
return None
411411

412-
def intersphinx_add_entries_v2(self, store: Any,
412+
def intersphinx_add_entries_v2(self, store: Dict,
413413
data: Dict[Tuple[str, str], InventoryItemSet]) -> None:
414414
"""Store the given *data* for later intersphinx reference resolution.
415415
@@ -512,7 +512,7 @@ def intersphinx_resolve_xref(self, env: "BuildEnvironment", store: Any,
512512
return None
513513
return self._intersphinx_resolve_xref_1(store, target, node, contnode, objtypes)
514514

515-
def intersphinx_resolve_any_xref(self, env: "BuildEnvironment", store: Any,
515+
def intersphinx_resolve_any_xref(self, env: "BuildEnvironment", store: Dict,
516516
target: str, node: pending_xref,
517517
contnode: TextElement) -> Optional[Element]:
518518
"""Resolve the pending_xref *node* with the given *typ* and *target* via intersphinx.

sphinx/domains/c.py

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
"""
1010

1111
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)
1414

1515
from docutils import nodes
1616
from docutils.nodes import Element, Node, TextElement, system_message
@@ -38,6 +38,7 @@
3838
octal_literal_re, verify_description_mode)
3939
from sphinx.util.docfields import Field, TypedField
4040
from sphinx.util.docutils import SphinxDirective
41+
from sphinx.util.inventory import InventoryItemSet
4142
from sphinx.util.nodes import make_refnode
4243

4344
logger = logging.getLogger(__name__)
@@ -46,6 +47,7 @@
4647
DeclarationType = 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+
13531377
class 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

38523936
def setup(app: Sphinx) -> Dict[str, Any]:
38533937
app.add_domain(CDomain)

0 commit comments

Comments
 (0)