From fb568273c0555097e8955643fa5d054b4e01bfc7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 17 Nov 2020 02:12:01 +0000 Subject: [PATCH] docs: automarkup.py: Allow automatic cross-reference inside C namespace MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Sphinx 3.1 introduced namespaces for C cross-references. With this, each C domain type/function declaration is put inside the namespace that was active at the time of its declaration. Add support for automatic cross-referencing inside C namespaces by checking whether the corresponding source file had a C namespace Sphinx directive, and if so, try cross-referencing inside of it before going to the global scope. This assumes there's only one namespace (if any) per rst file. Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/20201117021107.214704-1-nfraprado@protonmail.com Signed-off-by: Jonathan Corbet --- Documentation/sphinx/automarkup.py | 122 +++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 47 deletions(-) diff --git a/Documentation/sphinx/automarkup.py b/Documentation/sphinx/automarkup.py index 3e81eba..953b24b 100644 --- a/Documentation/sphinx/automarkup.py +++ b/Documentation/sphinx/automarkup.py @@ -53,6 +53,8 @@ RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=ascii_p3) # RE_doc = re.compile(r'\bDocumentation(/[\w\-_/]+)(\.\w+)*') +RE_namespace = re.compile(r'^\s*..\s*c:namespace::\s*(\S+)\s*$') + # # Reserved C words that we should skip when cross-referencing # @@ -70,6 +72,8 @@ Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap', 'select', 'poll', 'fork', 'execve', 'clone', 'ioctl', 'socket' ] +c_namespace = '' + def markup_refs(docname, app, node): t = node.astext() done = 0 @@ -128,30 +132,38 @@ def markup_func_ref_sphinx3(docname, app, match): # # Go through the dance of getting an xref out of the C domain # - target = match.group(2) + base_target = match.group(2) target_text = nodes.Text(match.group(0)) xref = None - if not (target in Skipfuncs or target in Skipnames): - for class_s, reftype_s in zip(class_str, reftype_str): - lit_text = nodes.literal(classes=['xref', 'c', class_s]) - lit_text += target_text - pxref = addnodes.pending_xref('', refdomain = 'c', - reftype = reftype_s, - reftarget = target, modname = None, - classname = None) - # - # XXX The Latex builder will throw NoUri exceptions here, - # work around that by ignoring them. - # - try: - xref = cdom.resolve_xref(app.env, docname, app.builder, - reftype_s, target, pxref, - lit_text) - except NoUri: - xref = None + possible_targets = [base_target] + # Check if this document has a namespace, and if so, try + # cross-referencing inside it first. + if c_namespace: + possible_targets.insert(0, c_namespace + "." + base_target) - if xref: - return xref + if base_target not in Skipnames: + for target in possible_targets: + if target not in Skipfuncs: + for class_s, reftype_s in zip(class_str, reftype_str): + lit_text = nodes.literal(classes=['xref', 'c', class_s]) + lit_text += target_text + pxref = addnodes.pending_xref('', refdomain = 'c', + reftype = reftype_s, + reftarget = target, modname = None, + classname = None) + # + # XXX The Latex builder will throw NoUri exceptions here, + # work around that by ignoring them. + # + try: + xref = cdom.resolve_xref(app.env, docname, app.builder, + reftype_s, target, pxref, + lit_text) + except NoUri: + xref = None + + if xref: + return xref return target_text @@ -179,34 +191,39 @@ def markup_c_ref(docname, app, match): # # Go through the dance of getting an xref out of the C domain # - target = match.group(2) + base_target = match.group(2) target_text = nodes.Text(match.group(0)) xref = None - if not ((match.re == RE_function and target in Skipfuncs) - or (target in Skipnames)): - lit_text = nodes.literal(classes=['xref', 'c', class_str[match.re]]) - lit_text += target_text - pxref = addnodes.pending_xref('', refdomain = 'c', - reftype = reftype_str[match.re], - reftarget = target, modname = None, - classname = None) - # - # XXX The Latex builder will throw NoUri exceptions here, - # work around that by ignoring them. - # - try: - xref = cdom.resolve_xref(app.env, docname, app.builder, - reftype_str[match.re], target, pxref, - lit_text) - except NoUri: - xref = None - # - # Return the xref if we got it; otherwise just return the plain text. - # - if xref: - return xref - else: - return target_text + possible_targets = [base_target] + # Check if this document has a namespace, and if so, try + # cross-referencing inside it first. + if c_namespace: + possible_targets.insert(0, c_namespace + "." + base_target) + + if base_target not in Skipnames: + for target in possible_targets: + if not (match.re == RE_function and target in Skipfuncs): + lit_text = nodes.literal(classes=['xref', 'c', class_str[match.re]]) + lit_text += target_text + pxref = addnodes.pending_xref('', refdomain = 'c', + reftype = reftype_str[match.re], + reftarget = target, modname = None, + classname = None) + # + # XXX The Latex builder will throw NoUri exceptions here, + # work around that by ignoring them. + # + try: + xref = cdom.resolve_xref(app.env, docname, app.builder, + reftype_str[match.re], target, pxref, + lit_text) + except NoUri: + xref = None + + if xref: + return xref + + return target_text # # Try to replace a documentation reference of the form Documentation/... with a @@ -239,7 +256,18 @@ def markup_doc_ref(docname, app, match): else: return nodes.Text(match.group(0)) +def get_c_namespace(app, docname): + source = app.env.doc2path(docname) + with open(source) as f: + for l in f: + match = RE_namespace.search(l) + if match: + return match.group(1) + return '' + def auto_markup(app, doctree, name): + global c_namespace + c_namespace = get_c_namespace(app, name) # # This loop could eventually be improved on. Someday maybe we # want a proper tree traversal with a lot of awareness of which -- 2.7.4