summaryrefslogtreecommitdiff
path: root/sphinx/domains/c.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/domains/c.py')
-rw-r--r--sphinx/domains/c.py68
1 files changed, 38 insertions, 30 deletions
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index 539a52e59..22d6ea82f 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -27,7 +27,7 @@ from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docfields import Field, TypedField
-from sphinx.util.nodes import make_refnode
+from sphinx.util.nodes import make_id, make_refnode
logger = logging.getLogger(__name__)
@@ -197,21 +197,23 @@ class CObject(ObjectDescription):
return ''
def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
- # for C API items we add a prefix since names are usually not qualified
- # by a module name and so easily clash with e.g. section titles
- targetname = 'c.' + name
- if targetname not in self.state.document.ids:
- signode['names'].append(targetname)
- signode['ids'].append(targetname)
- self.state.document.note_explicit_target(signode)
+ node_id = make_id(self.env, self.state.document, 'c', name)
+ signode['ids'].append(node_id)
- domain = cast(CDomain, self.env.get_domain('c'))
- domain.note_object(name, self.objtype)
+ # Assign old styled node_id not to break old hyperlinks (if possible)
+ # Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
+ old_node_id = self.make_old_id(name)
+ if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']:
+ signode['ids'].append(old_node_id)
+
+ self.state.document.note_explicit_target(signode)
+
+ domain = cast(CDomain, self.env.get_domain('c'))
+ domain.note_object(name, self.objtype, node_id)
indextext = self.get_index_text(name)
if indextext:
- self.indexnode['entries'].append(('single', indextext,
- targetname, '', None))
+ self.indexnode['entries'].append(('single', indextext, node_id, '', None))
def before_content(self) -> None:
self.typename_set = False
@@ -224,6 +226,14 @@ class CObject(ObjectDescription):
if self.typename_set:
self.env.ref_context.pop('c:type', None)
+ def make_old_id(self, name: str) -> str:
+ """Generate old styled node_id for C objects.
+
+ .. note:: Old Styled node_id was used until Sphinx-3.0.
+ This will be removed in Sphinx-5.0.
+ """
+ return 'c.' + name
+
class CXRefRole(XRefRole):
def process_link(self, env: BuildEnvironment, refnode: Element,
@@ -267,31 +277,31 @@ class CDomain(Domain):
'type': CXRefRole(),
}
initial_data = {
- 'objects': {}, # fullname -> docname, objtype
- } # type: Dict[str, Dict[str, Tuple[str, Any]]]
+ 'objects': {}, # fullname -> docname, node_id, objtype
+ } # type: Dict[str, Dict[str, Tuple[str, str, str]]]
@property
- def objects(self) -> Dict[str, Tuple[str, str]]:
- return self.data.setdefault('objects', {}) # fullname -> docname, objtype
+ def objects(self) -> Dict[str, Tuple[str, str, str]]:
+ return self.data.setdefault('objects', {}) # fullname -> docname, node_id, objtype
- def note_object(self, name: str, objtype: str, location: Any = None) -> None:
+ def note_object(self, name: str, objtype: str, node_id: str, location: Any = None) -> None:
if name in self.objects:
docname = self.objects[name][0]
logger.warning(__('duplicate C object description of %s, '
'other instance in %s, use :noindex: for one of them'),
name, docname, location=location)
- self.objects[name] = (self.env.docname, objtype)
+ self.objects[name] = (self.env.docname, node_id, objtype)
def clear_doc(self, docname: str) -> None:
- for fullname, (fn, _l) in list(self.objects.items()):
+ for fullname, (fn, node_id, _l) in list(self.objects.items()):
if fn == docname:
del self.objects[fullname]
def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
# XXX check duplicates
- for fullname, (fn, objtype) in otherdata['objects'].items():
+ for fullname, (fn, node_id, objtype) in otherdata['objects'].items():
if fn in docnames:
- self.data['objects'][fullname] = (fn, objtype)
+ self.data['objects'][fullname] = (fn, node_id, objtype)
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, contnode: Element
@@ -303,9 +313,8 @@ class CDomain(Domain):
return contnode
if target not in self.objects:
return None
- obj = self.objects[target]
- return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
- contnode, target)
+ docname, node_id, objtype = self.objects[target]
+ return make_refnode(builder, fromdocname, docname, node_id, contnode, target)
def resolve_any_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
target: str, node: pending_xref, contnode: Element
@@ -314,14 +323,13 @@ class CDomain(Domain):
target = target.rstrip(' *')
if target not in self.objects:
return []
- obj = self.objects[target]
- return [('c:' + self.role_for_objtype(obj[1]),
- make_refnode(builder, fromdocname, obj[0], 'c.' + target,
- contnode, target))]
+ docname, node_id, objtype = self.objects[target]
+ return [('c:' + self.role_for_objtype(objtype),
+ make_refnode(builder, fromdocname, docname, node_id, contnode, target))]
def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
- for refname, (docname, type) in list(self.objects.items()):
- yield (refname, refname, type, docname, 'c.' + refname, 1)
+ for refname, (docname, node_id, objtype) in list(self.objects.items()):
+ yield (refname, refname, objtype, docname, node_id, 1)
def setup(app: Sphinx) -> Dict[str, Any]: