diff options
Diffstat (limited to 'Documentation/sphinx')
| -rw-r--r-- | Documentation/sphinx/kernel_abi.py | 6 | ||||
| -rw-r--r-- | Documentation/sphinx/kernel_feat.py | 26 | ||||
| -rwxr-xr-x | Documentation/sphinx/kernel_include.py | 112 | ||||
| -rw-r--r-- | Documentation/sphinx/kerneldoc-preamble.sty | 2 | ||||
| -rw-r--r-- | Documentation/sphinx/kerneldoc.py | 6 | ||||
| -rw-r--r-- | Documentation/sphinx/load_config.py | 60 | ||||
| -rw-r--r-- | Documentation/sphinx/parallel-wrapper.sh | 33 |
7 files changed, 116 insertions, 129 deletions
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py index 4c4375201b9e..5667f207d175 100644 --- a/Documentation/sphinx/kernel_abi.py +++ b/Documentation/sphinx/kernel_abi.py @@ -14,7 +14,7 @@ :license: GPL Version 2, June 1991 see Linux/COPYING for details. The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the - scripts/get_abi.py script to parse the Kernel ABI files. + AbiParser class to parse the Kernel ABI files. Overview of directive's argument and options. @@ -43,9 +43,9 @@ from sphinx.util.docutils import switch_source_input from sphinx.util import logging srctree = os.path.abspath(os.environ["srctree"]) -sys.path.insert(0, os.path.join(srctree, "scripts/lib/abi")) +sys.path.insert(0, os.path.join(srctree, "tools/lib/python")) -from abi_parser import AbiParser +from abi.abi_parser import AbiParser __version__ = "1.0" diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py index aaac76892ceb..bdc0fef5c87f 100644 --- a/Documentation/sphinx/kernel_feat.py +++ b/Documentation/sphinx/kernel_feat.py @@ -13,7 +13,7 @@ :license: GPL Version 2, June 1991 see Linux/COPYING for details. The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the - scripts/get_feat.pl script to parse the Kernel ABI files. + tools/docs/get_feat.pl script to parse the Kernel ABI files. Overview of directive's argument and options. @@ -34,7 +34,6 @@ import codecs import os import re -import subprocess import sys from docutils import nodes, statemachine @@ -42,6 +41,11 @@ from docutils.statemachine import ViewList from docutils.parsers.rst import directives, Directive from sphinx.util.docutils import switch_source_input +srctree = os.path.abspath(os.environ["srctree"]) +sys.path.insert(0, os.path.join(srctree, "tools/lib/python")) + +from feat.parse_features import ParseFeature # pylint: disable=C0413 + def ErrorString(exc): # Shamelessly stolen from docutils return f'{exc.__class__.__name}: {exc}' @@ -84,18 +88,16 @@ class KernelFeat(Directive): srctree = os.path.abspath(os.environ["srctree"]) - args = [ - os.path.join(srctree, 'scripts/get_feat.pl'), - 'rest', - '--enable-fname', - '--dir', - os.path.join(srctree, 'Documentation', self.arguments[0]), - ] + feature_dir = os.path.join(srctree, 'Documentation', self.arguments[0]) - if len(self.arguments) > 1: - args.extend(['--arch', self.arguments[1]]) + feat = ParseFeature(feature_dir, False, True) + feat.parse() - lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8') + if len(self.arguments) > 1: + arch = self.arguments[1] + lines = feat.output_arch_table(arch) + else: + lines = feat.output_matrix() line_regex = re.compile(r"^\.\. FILE (\S+)$") diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py index f94412cd17c9..626762ff6af3 100755 --- a/Documentation/sphinx/kernel_include.py +++ b/Documentation/sphinx/kernel_include.py @@ -87,6 +87,8 @@ import os.path import re import sys +from difflib import get_close_matches + from docutils import io, nodes, statemachine from docutils.statemachine import ViewList from docutils.parsers.rst import Directive, directives @@ -95,15 +97,17 @@ from docutils.parsers.rst.directives.body import CodeBlock, NumberLines from sphinx.util import logging srctree = os.path.abspath(os.environ["srctree"]) -sys.path.insert(0, os.path.join(srctree, "tools/docs/lib")) +sys.path.insert(0, os.path.join(srctree, "tools/lib/python")) -from parse_data_structs import ParseDataStructs +from kdoc.parse_data_structs import ParseDataStructs __version__ = "1.0" logger = logging.getLogger(__name__) RE_DOMAIN_REF = re.compile(r'\\ :(ref|c:type|c:func):`([^<`]+)(?:<([^>]+)>)?`\\') RE_SIMPLE_REF = re.compile(r'`([^`]+)`') +RE_LINENO_REF = re.compile(r'^\s*-\s+LINENO_(\d+):\s+(.*)') +RE_SPLIT_DOMAIN = re.compile(r"(.*)\.(.*)") def ErrorString(exc): # Shamelessly stolen from docutils return f'{exc.__class__.__name}: {exc}' @@ -212,14 +216,16 @@ class KernelInclude(Directive): - a TOC table containing cross references. """ parser = ParseDataStructs() - parser.parse_file(path) if 'exception-file' in self.options: source_dir = os.path.dirname(os.path.abspath( self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1))) exceptions_file = os.path.join(source_dir, self.options['exception-file']) - parser.process_exceptions(exceptions_file) + else: + exceptions_file = None + + parser.parse_file(path, exceptions_file) # Store references on a symbol dict to be used at check time if 'warn-broken' in self.options: @@ -242,23 +248,32 @@ class KernelInclude(Directive): # TOC output is a ReST file, not a literal. So, we can add line # numbers - rawtext = parser.gen_toc() + startline = self.options.get('start-line', None) + endline = self.options.get('end-line', None) - include_lines = statemachine.string2lines(rawtext, tab_width, - convert_whitespace=True) + relpath = os.path.relpath(path, srctree) - # Append line numbers data + result = ViewList() + for line in parser.gen_toc().split("\n"): + match = RE_LINENO_REF.match(line) + if not match: + result.append(line, path) + continue - startline = self.options.get('start-line', None) + ln, ref = match.groups() + ln = int(ln) - result = ViewList() - if startline and startline > 0: - offset = startline - 1 - else: - offset = 0 + # Filter line range if needed + if startline and (ln < startline): + continue + + if endline and (ln > endline): + continue - for ln, line in enumerate(include_lines, start=offset): - result.append(line, path, ln) + # Sphinx numerates starting with zero, but text editors + # and other tools start from one + realln = ln + 1 + result.append(f"- {ref}: {relpath}#{realln}", path, ln) self.state_machine.insert_input(result, path) @@ -388,6 +403,63 @@ class KernelInclude(Directive): # ============================================================================== reported = set() +DOMAIN_INFO = {} +all_refs = {} + +def fill_domain_info(env): + """ + Get supported reference types for each Sphinx domain and C namespaces + """ + if DOMAIN_INFO: + return + + for domain_name, domain_instance in env.domains.items(): + try: + object_types = list(domain_instance.object_types.keys()) + DOMAIN_INFO[domain_name] = object_types + except AttributeError: + # Ignore domains that we can't retrieve object types, if any + pass + + for domain in DOMAIN_INFO.keys(): + domain_obj = env.get_domain(domain) + for name, dispname, objtype, docname, anchor, priority in domain_obj.get_objects(): + ref_name = name.lower() + + if domain == "c": + if '.' in ref_name: + ref_name = ref_name.split(".")[-1] + + if not ref_name in all_refs: + all_refs[ref_name] = [] + + all_refs[ref_name].append(f"\t{domain}:{objtype}:`{name}` (from {docname})") + +def get_suggestions(app, env, node, + original_target, original_domain, original_reftype): + """Check if target exists in the other domain or with different reftypes.""" + original_target = original_target.lower() + + # Remove namespace if present + if original_domain == "c": + if '.' in original_target: + original_target = original_target.split(".")[-1] + + suggestions = [] + + # If name exists, propose exact name match on different domains + if original_target in all_refs: + return all_refs[original_target] + + # If not found, get a close match, using difflib. + # Such method is based on Ratcliff-Obershelp Algorithm, which seeks + # for a close match within a certain distance. We're using the defaults + # here, e.g. cutoff=0.6, proposing 3 alternatives + matches = get_close_matches(original_target, all_refs.keys()) + for match in matches: + suggestions += all_refs[match] + + return suggestions def check_missing_refs(app, env, node, contnode): """Check broken refs for the files it creates xrefs""" @@ -404,11 +476,13 @@ def check_missing_refs(app, env, node, contnode): if node.source not in xref_files: return None + fill_domain_info(env) + target = node.get('reftarget', '') domain = node.get('refdomain', 'std') reftype = node.get('reftype', '') - msg = f"can't link to: {domain}:{reftype}:: {target}" + msg = f"Invalid xref: {domain}:{reftype}:`{target}`" # Don't duplicate warnings data = (node.source, msg) @@ -416,6 +490,10 @@ def check_missing_refs(app, env, node, contnode): return None reported.add(data) + suggestions = get_suggestions(app, env, node, target, domain, reftype) + if suggestions: + msg += ". Possible alternatives:\n" + '\n'.join(suggestions) + logger.warning(msg, location=node, type='ref', subtype='missing') return None diff --git a/Documentation/sphinx/kerneldoc-preamble.sty b/Documentation/sphinx/kerneldoc-preamble.sty index 5d68395539fe..16d9ff46fdf6 100644 --- a/Documentation/sphinx/kerneldoc-preamble.sty +++ b/Documentation/sphinx/kerneldoc-preamble.sty @@ -220,7 +220,7 @@ If you want them, please install non-variable ``Noto Sans CJK'' font families along with the texlive-xecjk package by following instructions from - \sphinxcode{./scripts/sphinx-pre-install}. + \sphinxcode{./tools/docs/sphinx-pre-install}. Having optional non-variable ``Noto Serif CJK'' font families will improve the looks of those translations. \end{sphinxadmonition}} diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py index 2586b4d4e494..d8cdf068ef35 100644 --- a/Documentation/sphinx/kerneldoc.py +++ b/Documentation/sphinx/kerneldoc.py @@ -42,10 +42,10 @@ from sphinx.util import logging from pprint import pformat srctree = os.path.abspath(os.environ["srctree"]) -sys.path.insert(0, os.path.join(srctree, "scripts/lib/kdoc")) +sys.path.insert(0, os.path.join(srctree, "tools/lib/python")) -from kdoc_files import KernelFiles -from kdoc_output import RestFormat +from kdoc.kdoc_files import KernelFiles +from kdoc.kdoc_output import RestFormat __version__ = '1.0' kfiles = None diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py deleted file mode 100644 index 1afb0c97f06b..000000000000 --- a/Documentation/sphinx/load_config.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8; mode: python -*- -# SPDX-License-Identifier: GPL-2.0 -# pylint: disable=R0903, C0330, R0914, R0912, E0401 - -import os -import sys -from sphinx.util.osutil import fs_encoding - -# ------------------------------------------------------------------------------ -def loadConfig(namespace): -# ------------------------------------------------------------------------------ - - """Load an additional configuration file into *namespace*. - - The name of the configuration file is taken from the environment - ``SPHINX_CONF``. The external configuration file extends (or overwrites) the - configuration values from the origin ``conf.py``. With this you are able to - maintain *build themes*. """ - - config_file = os.environ.get("SPHINX_CONF", None) - if (config_file is not None - and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ): - config_file = os.path.abspath(config_file) - - # Let's avoid one conf.py file just due to latex_documents - start = config_file.find('Documentation/') - if start >= 0: - start = config_file.find('/', start + 1) - - end = config_file.rfind('/') - if start >= 0 and end > 0: - dir = config_file[start + 1:end] - - print("source directory: %s" % dir) - new_latex_docs = [] - latex_documents = namespace['latex_documents'] - - for l in latex_documents: - if l[0].find(dir + '/') == 0: - has = True - fn = l[0][len(dir) + 1:] - new_latex_docs.append((fn, l[1], l[2], l[3], l[4])) - break - - namespace['latex_documents'] = new_latex_docs - - # If there is an extra conf.py file, load it - if os.path.isfile(config_file): - sys.stdout.write("load additional sphinx-config: %s\n" % config_file) - config = namespace.copy() - config['__file__'] = config_file - with open(config_file, 'rb') as f: - code = compile(f.read(), fs_encoding, 'exec') - exec(code, config) - del config['__file__'] - namespace.update(config) - else: - config = namespace.copy() - config['tags'].add("subproject") - namespace.update(config) diff --git a/Documentation/sphinx/parallel-wrapper.sh b/Documentation/sphinx/parallel-wrapper.sh deleted file mode 100644 index e54c44ce117d..000000000000 --- a/Documentation/sphinx/parallel-wrapper.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0+ -# -# Figure out if we should follow a specific parallelism from the make -# environment (as exported by scripts/jobserver-exec), or fall back to -# the "auto" parallelism when "-jN" is not specified at the top-level -# "make" invocation. - -sphinx="$1" -shift || true - -parallel="$PARALLELISM" -if [ -z "$parallel" ] ; then - # If no parallelism is specified at the top-level make, then - # fall back to the expected "-jauto" mode that the "htmldocs" - # target has had. - auto=$(perl -e 'open IN,"'"$sphinx"' --version 2>&1 |"; - while (<IN>) { - if (m/([\d\.]+)/) { - print "auto" if ($1 >= "1.7") - } - } - close IN') - if [ -n "$auto" ] ; then - parallel="$auto" - fi -fi -# Only if some parallelism has been determined do we add the -jN option. -if [ -n "$parallel" ] ; then - parallel="-j$parallel" -fi - -exec "$sphinx" $parallel "$@" |
