docs: sphinx: kerneldoc: Use python class if available
Better integrate with the new kernel-doc tool by calling the Python classes directly if KERNELDOC=scripts/kernel-doc.py. This way, warnings won't be duplicated anymore, as files will be parsed only once. Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/1556a6c005d8e0fafa951f74725e984e1c7459bf.1744685912.git.mchehab+huawei@kernel.org
This commit is contained in:
parent
47c2d4168b
commit
9d9bec3d90
|
|
@ -41,7 +41,14 @@ import sphinx
|
|||
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/kdoc"))
|
||||
|
||||
from kdoc_files import KernelFiles
|
||||
from kdoc_output import RestFormat
|
||||
|
||||
__version__ = '1.0'
|
||||
use_kfiles = False
|
||||
|
||||
def cmd_str(cmd):
|
||||
"""
|
||||
|
|
@ -82,11 +89,32 @@ class KernelDocDirective(Directive):
|
|||
logger = logging.getLogger('kerneldoc')
|
||||
verbose = 0
|
||||
|
||||
def run(self):
|
||||
parse_args = {}
|
||||
msg_args = {}
|
||||
|
||||
def handle_args(self):
|
||||
|
||||
env = self.state.document.settings.env
|
||||
cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
|
||||
|
||||
filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
|
||||
|
||||
# Arguments used by KernelFiles.parse() function
|
||||
self.parse_args = {
|
||||
"file_list": [filename],
|
||||
"export_file": []
|
||||
}
|
||||
|
||||
# Arguments used by KernelFiles.msg() function
|
||||
self.msg_args = {
|
||||
"enable_lineno": True,
|
||||
"export": False,
|
||||
"internal": False,
|
||||
"symbol": [],
|
||||
"nosymbol": [],
|
||||
"no_doc_sections": False
|
||||
}
|
||||
|
||||
export_file_patterns = []
|
||||
|
||||
verbose = os.environ.get("V")
|
||||
|
|
@ -99,7 +127,8 @@ class KernelDocDirective(Directive):
|
|||
# Tell sphinx of the dependency
|
||||
env.note_dependency(os.path.abspath(filename))
|
||||
|
||||
tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
|
||||
self.tab_width = self.options.get('tab-width',
|
||||
self.state.document.settings.tab_width)
|
||||
|
||||
# 'function' is an alias of 'identifiers'
|
||||
if 'functions' in self.options:
|
||||
|
|
@ -108,12 +137,16 @@ class KernelDocDirective(Directive):
|
|||
# FIXME: make this nicer and more robust against errors
|
||||
if 'export' in self.options:
|
||||
cmd += ['-export']
|
||||
self.msg_args["export"] = True
|
||||
export_file_patterns = str(self.options.get('export')).split()
|
||||
elif 'internal' in self.options:
|
||||
cmd += ['-internal']
|
||||
self.msg_args["internal"] = True
|
||||
export_file_patterns = str(self.options.get('internal')).split()
|
||||
elif 'doc' in self.options:
|
||||
cmd += ['-function', str(self.options.get('doc'))]
|
||||
func = str(self.options.get('doc'))
|
||||
cmd += ['-function', func]
|
||||
self.msg_args["symbol"].append(func)
|
||||
elif 'identifiers' in self.options:
|
||||
identifiers = self.options.get('identifiers').split()
|
||||
if identifiers:
|
||||
|
|
@ -123,8 +156,10 @@ class KernelDocDirective(Directive):
|
|||
continue
|
||||
|
||||
cmd += ['-function', i]
|
||||
self.msg_args["symbol"].append(i)
|
||||
else:
|
||||
cmd += ['-no-doc-sections']
|
||||
self.msg_args["no_doc_sections"] = True
|
||||
|
||||
if 'no-identifiers' in self.options:
|
||||
no_identifiers = self.options.get('no-identifiers').split()
|
||||
|
|
@ -135,6 +170,7 @@ class KernelDocDirective(Directive):
|
|||
continue
|
||||
|
||||
cmd += ['-nosymbol', i]
|
||||
self.msg_args["nosymbol"].append(i)
|
||||
|
||||
for pattern in export_file_patterns:
|
||||
pattern = pattern.rstrip("\\").strip()
|
||||
|
|
@ -144,12 +180,29 @@ class KernelDocDirective(Directive):
|
|||
for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
|
||||
env.note_dependency(os.path.abspath(f))
|
||||
cmd += ['-export-file', f]
|
||||
self.parse_args["export_file"].append(f)
|
||||
|
||||
# Export file is needed by both parse and msg, as kernel-doc
|
||||
# cache exports.
|
||||
self.msg_args["export_file"] = self.parse_args["export_file"]
|
||||
|
||||
cmd += [filename]
|
||||
|
||||
return cmd
|
||||
|
||||
def run_cmd(self):
|
||||
"""
|
||||
Execute an external kernel-doc command.
|
||||
"""
|
||||
|
||||
env = self.state.document.settings.env
|
||||
cmd = self.handle_args()
|
||||
|
||||
if self.verbose >= 1:
|
||||
print(cmd_str(cmd))
|
||||
|
||||
node = nodes.section()
|
||||
|
||||
try:
|
||||
self.logger.verbose("calling kernel-doc '%s'" % (" ".join(cmd)))
|
||||
|
||||
|
|
@ -167,7 +220,29 @@ class KernelDocDirective(Directive):
|
|||
elif env.config.kerneldoc_verbosity > 0:
|
||||
sys.stderr.write(err)
|
||||
|
||||
lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
|
||||
except Exception as e: # pylint: disable=W0703
|
||||
self.logger.warning("kernel-doc '%s' processing failed with: %s" %
|
||||
(" ".join(cmd), str(e)))
|
||||
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
|
||||
|
||||
filenames = self.parse_args["file_list"]
|
||||
for filename in filenames:
|
||||
ret = self.parse_msg(filename, node, out, cmd)
|
||||
if ret:
|
||||
return ret
|
||||
|
||||
return node.children
|
||||
|
||||
def parse_msg(self, filename, node, out, cmd):
|
||||
"""
|
||||
Handles a kernel-doc output for a given file
|
||||
"""
|
||||
|
||||
env = self.state.document.settings.env
|
||||
|
||||
try:
|
||||
lines = statemachine.string2lines(out, self.tab_width,
|
||||
convert_whitespace=True)
|
||||
result = ViewList()
|
||||
|
||||
lineoffset = 0;
|
||||
|
|
@ -183,20 +258,65 @@ class KernelDocDirective(Directive):
|
|||
result.append(line, doc + ": " + filename, lineoffset)
|
||||
lineoffset += 1
|
||||
|
||||
node = nodes.section()
|
||||
self.do_parse(result, node)
|
||||
|
||||
return node.children
|
||||
|
||||
except Exception as e: # pylint: disable=W0703
|
||||
self.logger.warning("kernel-doc '%s' processing failed with: %s" %
|
||||
(" ".join(cmd), str(e)))
|
||||
(cmd_str(cmd), str(e)))
|
||||
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
|
||||
|
||||
return None
|
||||
|
||||
def run_kdoc(self, kfiles):
|
||||
"""
|
||||
Execute kernel-doc classes directly instead of running as a separate
|
||||
command.
|
||||
"""
|
||||
|
||||
cmd = self.handle_args()
|
||||
env = self.state.document.settings.env
|
||||
|
||||
node = nodes.section()
|
||||
|
||||
kfiles.parse(**self.parse_args)
|
||||
filenames = self.parse_args["file_list"]
|
||||
|
||||
for filename, out in kfiles.msg(**self.msg_args, filenames=filenames):
|
||||
if self.verbose >= 1:
|
||||
print(cmd_str(cmd))
|
||||
|
||||
ret = self.parse_msg(filename, node, out, cmd)
|
||||
if ret:
|
||||
return ret
|
||||
|
||||
return node.children
|
||||
|
||||
def run(self):
|
||||
global use_kfiles
|
||||
|
||||
if use_kfiles:
|
||||
out_style = RestFormat()
|
||||
kfiles = KernelFiles(out_style=out_style, logger=self.logger)
|
||||
return self.run_kdoc(kfiles)
|
||||
else:
|
||||
return self.run_cmd()
|
||||
|
||||
def do_parse(self, result, node):
|
||||
with switch_source_input(self.state, result):
|
||||
self.state.nested_parse(result, 0, node, match_titles=1)
|
||||
|
||||
def setup_kfiles(app):
|
||||
global use_kfiles
|
||||
|
||||
kerneldoc_bin = app.env.config.kerneldoc_bin
|
||||
|
||||
if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
|
||||
print("Using Python kernel-doc")
|
||||
use_kfiles = True
|
||||
else:
|
||||
print(f"Using {kerneldoc_bin}")
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('kerneldoc_bin', None, 'env')
|
||||
app.add_config_value('kerneldoc_srctree', None, 'env')
|
||||
|
|
@ -204,6 +324,8 @@ def setup(app):
|
|||
|
||||
app.add_directive('kernel-doc', KernelDocDirective)
|
||||
|
||||
app.connect('builder-inited', setup_kfiles)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
|
|
|
|||
Loading…
Reference in New Issue