Merge branch 'kdoc-item2' into docs-mw
The kerneldoc parsing phase gathers all of the information about the declarations of interest, then passes it through to the output phase as a dict that is an unstructured blob of information; this organization has its origins in the Perl version of the program. It results in an interface that is difficult to reason about, dozen-parameter function calls, and other ills. Introduce a new class (KdocItem) to carry this information between the parser and the output modules, and, step by step, modify the system to use this class in a more structured way. This could be taken further by creating a subclass of KdocItem for each declaration type (function, struct, ...), but that is probably more structure than we need. The result is (I hope) clearer code, the removal of a bunch of boilerplate, and no changes to the generated output.
This commit is contained in:
commit
f587722aa5
|
|
@ -275,8 +275,8 @@ class KernelFiles():
|
|||
self.config.log.warning("No kernel-doc for file %s", fname)
|
||||
continue
|
||||
|
||||
for name, arg in self.results[fname]:
|
||||
m = self.out_msg(fname, name, arg)
|
||||
for arg in self.results[fname]:
|
||||
m = self.out_msg(fname, arg.name, arg)
|
||||
|
||||
if m is None:
|
||||
ln = arg.get("ln", 0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# A class that will, eventually, encapsulate all of the parsed data that we
|
||||
# then pass into the output modules.
|
||||
#
|
||||
|
||||
class KdocItem:
|
||||
def __init__(self, name, type, start_line, **other_stuff):
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.declaration_start_line = start_line
|
||||
self.sections = {}
|
||||
self.sections_start_lines = {}
|
||||
self.parameterlist = []
|
||||
self.parameterdesc_start_lines = []
|
||||
self.parameterdescs = {}
|
||||
self.parametertypes = {}
|
||||
#
|
||||
# Just save everything else into our own dict so that the output
|
||||
# side can grab it directly as before. As we move things into more
|
||||
# structured data, this will, hopefully, fade away.
|
||||
#
|
||||
self.other_stuff = other_stuff
|
||||
|
||||
def get(self, key, default = None):
|
||||
return self.other_stuff.get(key, default)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.get(key)
|
||||
|
||||
#
|
||||
# Tracking of section and parameter information.
|
||||
#
|
||||
def set_sections(self, sections, start_lines):
|
||||
self.sections = sections
|
||||
self.section_start_lines = start_lines
|
||||
|
||||
def set_params(self, names, descs, types, starts):
|
||||
self.parameterlist = names
|
||||
self.parameterdescs = descs
|
||||
self.parametertypes = types
|
||||
self.parameterdesc_start_lines = starts
|
||||
|
|
@ -124,9 +124,7 @@ class OutputFormat:
|
|||
Output warnings for identifiers that will be displayed.
|
||||
"""
|
||||
|
||||
warnings = args.get('warnings', [])
|
||||
|
||||
for log_msg in warnings:
|
||||
for log_msg in args.warnings:
|
||||
self.config.warning(log_msg)
|
||||
|
||||
def check_doc(self, name, args):
|
||||
|
|
@ -184,7 +182,7 @@ class OutputFormat:
|
|||
|
||||
self.data = ""
|
||||
|
||||
dtype = args.get('type', "")
|
||||
dtype = args.type
|
||||
|
||||
if dtype == "doc":
|
||||
self.out_doc(fname, name, args)
|
||||
|
|
@ -338,12 +336,7 @@ class RestFormat(OutputFormat):
|
|||
starts by putting out the name of the doc section itself, but that
|
||||
tends to duplicate a header already in the template file.
|
||||
"""
|
||||
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
sections = args.get('sections', {})
|
||||
section_start_lines = args.get('section_start_lines', {})
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
# Skip sections that are in the nosymbol_table
|
||||
if section in self.nosymbol:
|
||||
continue
|
||||
|
|
@ -355,8 +348,8 @@ class RestFormat(OutputFormat):
|
|||
else:
|
||||
self.data += f'{self.lineprefix}**{section}**\n\n'
|
||||
|
||||
self.print_lineno(section_start_lines.get(section, 0))
|
||||
self.output_highlight(sections[section])
|
||||
self.print_lineno(args.section_start_lines.get(section, 0))
|
||||
self.output_highlight(text)
|
||||
self.data += "\n"
|
||||
self.data += "\n"
|
||||
|
||||
|
|
@ -372,24 +365,19 @@ class RestFormat(OutputFormat):
|
|||
|
||||
func_macro = args.get('func_macro', False)
|
||||
if func_macro:
|
||||
signature = args['function']
|
||||
signature = name
|
||||
else:
|
||||
if args.get('functiontype'):
|
||||
signature = args['functiontype'] + " "
|
||||
signature += args['function'] + " ("
|
||||
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
parameterdescs = args.get('parameterdescs', {})
|
||||
parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
|
||||
|
||||
ln = args.get('declaration_start_line', 0)
|
||||
signature += name + " ("
|
||||
|
||||
ln = args.declaration_start_line
|
||||
count = 0
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
if count != 0:
|
||||
signature += ", "
|
||||
count += 1
|
||||
dtype = args['parametertypes'].get(parameter, "")
|
||||
dtype = args.parametertypes.get(parameter, "")
|
||||
|
||||
if function_pointer.search(dtype):
|
||||
signature += function_pointer.group(1) + parameter + function_pointer.group(3)
|
||||
|
|
@ -401,7 +389,7 @@ class RestFormat(OutputFormat):
|
|||
|
||||
self.print_lineno(ln)
|
||||
if args.get('typedef') or not args.get('functiontype'):
|
||||
self.data += f".. c:macro:: {args['function']}\n\n"
|
||||
self.data += f".. c:macro:: {name}\n\n"
|
||||
|
||||
if args.get('typedef'):
|
||||
self.data += " **Typedef**: "
|
||||
|
|
@ -424,26 +412,26 @@ class RestFormat(OutputFormat):
|
|||
# function prototypes apart
|
||||
self.lineprefix = " "
|
||||
|
||||
if parameterlist:
|
||||
if args.parameterlist:
|
||||
self.data += ".. container:: kernelindent\n\n"
|
||||
self.data += f"{self.lineprefix}**Parameters**\n\n"
|
||||
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
parameter_name = KernRe(r'\[.*').sub('', parameter)
|
||||
dtype = args['parametertypes'].get(parameter, "")
|
||||
dtype = args.parametertypes.get(parameter, "")
|
||||
|
||||
if dtype:
|
||||
self.data += f"{self.lineprefix}``{dtype}``\n"
|
||||
else:
|
||||
self.data += f"{self.lineprefix}``{parameter}``\n"
|
||||
|
||||
self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
|
||||
self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0))
|
||||
|
||||
self.lineprefix = " "
|
||||
if parameter_name in parameterdescs and \
|
||||
parameterdescs[parameter_name] != KernelDoc.undescribed:
|
||||
if parameter_name in args.parameterdescs and \
|
||||
args.parameterdescs[parameter_name] != KernelDoc.undescribed:
|
||||
|
||||
self.output_highlight(parameterdescs[parameter_name])
|
||||
self.output_highlight(args.parameterdescs[parameter_name])
|
||||
self.data += "\n"
|
||||
else:
|
||||
self.data += f"{self.lineprefix}*undescribed*\n\n"
|
||||
|
|
@ -455,10 +443,7 @@ class RestFormat(OutputFormat):
|
|||
def out_enum(self, fname, name, args):
|
||||
|
||||
oldprefix = self.lineprefix
|
||||
name = args.get('enum', '')
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
parameterdescs = args.get('parameterdescs', {})
|
||||
ln = args.get('declaration_start_line', 0)
|
||||
ln = args.declaration_start_line
|
||||
|
||||
self.data += f"\n\n.. c:enum:: {name}\n\n"
|
||||
|
||||
|
|
@ -472,11 +457,11 @@ class RestFormat(OutputFormat):
|
|||
self.lineprefix = outer + " "
|
||||
self.data += f"{outer}**Constants**\n\n"
|
||||
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
self.data += f"{outer}``{parameter}``\n"
|
||||
|
||||
if parameterdescs.get(parameter, '') != KernelDoc.undescribed:
|
||||
self.output_highlight(parameterdescs[parameter])
|
||||
if args.parameterdescs.get(parameter, '') != KernelDoc.undescribed:
|
||||
self.output_highlight(args.parameterdescs[parameter])
|
||||
else:
|
||||
self.data += f"{self.lineprefix}*undescribed*\n\n"
|
||||
self.data += "\n"
|
||||
|
|
@ -487,8 +472,7 @@ class RestFormat(OutputFormat):
|
|||
def out_typedef(self, fname, name, args):
|
||||
|
||||
oldprefix = self.lineprefix
|
||||
name = args.get('typedef', '')
|
||||
ln = args.get('declaration_start_line', 0)
|
||||
ln = args.declaration_start_line
|
||||
|
||||
self.data += f"\n\n.. c:type:: {name}\n\n"
|
||||
|
||||
|
|
@ -504,15 +488,10 @@ class RestFormat(OutputFormat):
|
|||
|
||||
def out_struct(self, fname, name, args):
|
||||
|
||||
name = args.get('struct', "")
|
||||
purpose = args.get('purpose', "")
|
||||
declaration = args.get('definition', "")
|
||||
dtype = args.get('type', "struct")
|
||||
ln = args.get('declaration_start_line', 0)
|
||||
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
parameterdescs = args.get('parameterdescs', {})
|
||||
parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
|
||||
dtype = args.type
|
||||
ln = args.declaration_start_line
|
||||
|
||||
self.data += f"\n\n.. c:{dtype}:: {name}\n\n"
|
||||
|
||||
|
|
@ -536,21 +515,21 @@ class RestFormat(OutputFormat):
|
|||
|
||||
self.lineprefix = " "
|
||||
self.data += f"{self.lineprefix}**Members**\n\n"
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
if not parameter or parameter.startswith("#"):
|
||||
continue
|
||||
|
||||
parameter_name = parameter.split("[", maxsplit=1)[0]
|
||||
|
||||
if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
||||
if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
||||
continue
|
||||
|
||||
self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
|
||||
self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0))
|
||||
|
||||
self.data += f"{self.lineprefix}``{parameter}``\n"
|
||||
|
||||
self.lineprefix = " "
|
||||
self.output_highlight(parameterdescs[parameter_name])
|
||||
self.output_highlight(args.parameterdescs[parameter_name])
|
||||
self.lineprefix = " "
|
||||
|
||||
self.data += "\n"
|
||||
|
|
@ -636,46 +615,38 @@ class ManFormat(OutputFormat):
|
|||
self.data += line + "\n"
|
||||
|
||||
def out_doc(self, fname, name, args):
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
sections = args.get('sections', {})
|
||||
|
||||
if not self.check_doc(name, args):
|
||||
return
|
||||
|
||||
self.data += f'.TH "{self.modulename}" 9 "{self.modulename}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
self.data += f'.SH "{section}"' + "\n"
|
||||
self.output_highlight(sections.get(section))
|
||||
self.output_highlight(text)
|
||||
|
||||
def out_function(self, fname, name, args):
|
||||
"""output function in man"""
|
||||
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
parameterdescs = args.get('parameterdescs', {})
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
sections = args.get('sections', {})
|
||||
|
||||
self.data += f'.TH "{args["function"]}" 9 "{args["function"]}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n"
|
||||
self.data += f'.TH "{name}" 9 "{name}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n"
|
||||
|
||||
self.data += ".SH NAME\n"
|
||||
self.data += f"{args['function']} \\- {args['purpose']}\n"
|
||||
self.data += f"{name} \\- {args['purpose']}\n"
|
||||
|
||||
self.data += ".SH SYNOPSIS\n"
|
||||
if args.get('functiontype', ''):
|
||||
self.data += f'.B "{args["functiontype"]}" {args["function"]}' + "\n"
|
||||
self.data += f'.B "{args["functiontype"]}" {name}' + "\n"
|
||||
else:
|
||||
self.data += f'.B "{args["function"]}' + "\n"
|
||||
self.data += f'.B "{name}' + "\n"
|
||||
|
||||
count = 0
|
||||
parenth = "("
|
||||
post = ","
|
||||
|
||||
for parameter in parameterlist:
|
||||
if count == len(parameterlist) - 1:
|
||||
for parameter in args.parameterlist:
|
||||
if count == len(args.parameterlist) - 1:
|
||||
post = ");"
|
||||
|
||||
dtype = args['parametertypes'].get(parameter, "")
|
||||
dtype = args.parametertypes.get(parameter, "")
|
||||
if function_pointer.match(dtype):
|
||||
# Pointer-to-function
|
||||
self.data += f'".BI "{parenth}{function_pointer.group(1)}" " ") ({function_pointer.group(2)}){post}"' + "\n"
|
||||
|
|
@ -686,38 +657,32 @@ class ManFormat(OutputFormat):
|
|||
count += 1
|
||||
parenth = ""
|
||||
|
||||
if parameterlist:
|
||||
if args.parameterlist:
|
||||
self.data += ".SH ARGUMENTS\n"
|
||||
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
parameter_name = re.sub(r'\[.*', '', parameter)
|
||||
|
||||
self.data += f'.IP "{parameter}" 12' + "\n"
|
||||
self.output_highlight(parameterdescs.get(parameter_name, ""))
|
||||
self.output_highlight(args.parameterdescs.get(parameter_name, ""))
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
self.data += f'.SH "{section.upper()}"' + "\n"
|
||||
self.output_highlight(sections[section])
|
||||
self.output_highlight(text)
|
||||
|
||||
def out_enum(self, fname, name, args):
|
||||
|
||||
name = args.get('enum', '')
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
sections = args.get('sections', {})
|
||||
|
||||
self.data += f'.TH "{self.modulename}" 9 "enum {args["enum"]}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
self.data += f'.TH "{self.modulename}" 9 "enum {name}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
|
||||
self.data += ".SH NAME\n"
|
||||
self.data += f"enum {args['enum']} \\- {args['purpose']}\n"
|
||||
self.data += f"enum {name} \\- {args['purpose']}\n"
|
||||
|
||||
self.data += ".SH SYNOPSIS\n"
|
||||
self.data += f"enum {args['enum']}" + " {\n"
|
||||
self.data += f"enum {name}" + " {\n"
|
||||
|
||||
count = 0
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
self.data += f'.br\n.BI " {parameter}"' + "\n"
|
||||
if count == len(parameterlist) - 1:
|
||||
if count == len(args.parameterlist) - 1:
|
||||
self.data += "\n};\n"
|
||||
else:
|
||||
self.data += ", \n.br\n"
|
||||
|
|
@ -726,68 +691,59 @@ class ManFormat(OutputFormat):
|
|||
|
||||
self.data += ".SH Constants\n"
|
||||
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
parameter_name = KernRe(r'\[.*').sub('', parameter)
|
||||
self.data += f'.IP "{parameter}" 12' + "\n"
|
||||
self.output_highlight(args['parameterdescs'].get(parameter_name, ""))
|
||||
self.output_highlight(args.parameterdescs.get(parameter_name, ""))
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
self.data += f'.SH "{section}"' + "\n"
|
||||
self.output_highlight(sections[section])
|
||||
self.output_highlight(text)
|
||||
|
||||
def out_typedef(self, fname, name, args):
|
||||
module = self.modulename
|
||||
typedef = args.get('typedef')
|
||||
purpose = args.get('purpose')
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
sections = args.get('sections', {})
|
||||
|
||||
self.data += f'.TH "{module}" 9 "{typedef}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
self.data += f'.TH "{module}" 9 "{name}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
|
||||
self.data += ".SH NAME\n"
|
||||
self.data += f"typedef {typedef} \\- {purpose}\n"
|
||||
self.data += f"typedef {name} \\- {purpose}\n"
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
self.data += f'.SH "{section}"' + "\n"
|
||||
self.output_highlight(sections.get(section))
|
||||
self.output_highlight(text)
|
||||
|
||||
def out_struct(self, fname, name, args):
|
||||
module = self.modulename
|
||||
struct_type = args.get('type')
|
||||
struct_name = args.get('struct')
|
||||
purpose = args.get('purpose')
|
||||
definition = args.get('definition')
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
parameterlist = args.get('parameterlist', [])
|
||||
sections = args.get('sections', {})
|
||||
parameterdescs = args.get('parameterdescs', {})
|
||||
|
||||
self.data += f'.TH "{module}" 9 "{struct_type} {struct_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
self.data += f'.TH "{module}" 9 "{args.type} {name}" "{self.man_date}" "API Manual" LINUX' + "\n"
|
||||
|
||||
self.data += ".SH NAME\n"
|
||||
self.data += f"{struct_type} {struct_name} \\- {purpose}\n"
|
||||
self.data += f"{args.type} {name} \\- {purpose}\n"
|
||||
|
||||
# Replace tabs with two spaces and handle newlines
|
||||
declaration = definition.replace("\t", " ")
|
||||
declaration = KernRe(r"\n").sub('"\n.br\n.BI "', declaration)
|
||||
|
||||
self.data += ".SH SYNOPSIS\n"
|
||||
self.data += f"{struct_type} {struct_name} " + "{" + "\n.br\n"
|
||||
self.data += f"{args.type} {name} " + "{" + "\n.br\n"
|
||||
self.data += f'.BI "{declaration}\n' + "};\n.br\n\n"
|
||||
|
||||
self.data += ".SH Members\n"
|
||||
for parameter in parameterlist:
|
||||
for parameter in args.parameterlist:
|
||||
if parameter.startswith("#"):
|
||||
continue
|
||||
|
||||
parameter_name = re.sub(r"\[.*", "", parameter)
|
||||
|
||||
if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
||||
if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
||||
continue
|
||||
|
||||
self.data += f'.IP "{parameter}" 12' + "\n"
|
||||
self.output_highlight(parameterdescs.get(parameter_name))
|
||||
self.output_highlight(args.parameterdescs.get(parameter_name))
|
||||
|
||||
for section in sectionlist:
|
||||
for section, text in args.sections.items():
|
||||
self.data += f'.SH "{section}"' + "\n"
|
||||
self.output_highlight(sections.get(section))
|
||||
self.output_highlight(text)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@ Read a C language source or header FILE and extract embedded
|
|||
documentation comments
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pprint import pformat
|
||||
|
||||
from kdoc_re import NestedMatch, KernRe
|
||||
|
||||
from kdoc_item import KdocItem
|
||||
|
||||
#
|
||||
# Regular expressions used to parse kernel-doc markups at KernelDoc class.
|
||||
|
|
@ -42,9 +43,11 @@ doc_decl = doc_com + KernRe(r'(\w+)', cache=False)
|
|||
# @{section-name}:
|
||||
# while trying to not match literal block starts like "example::"
|
||||
#
|
||||
known_section_names = 'description|context|returns?|notes?|examples?'
|
||||
known_sections = KernRe(known_section_names, flags = re.I)
|
||||
doc_sect = doc_com + \
|
||||
KernRe(r'\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$',
|
||||
flags=re.I, cache=False)
|
||||
KernRe(r'\s*(\@[.\w]+|\@\.\.\.|' + known_section_names + r')\s*:([^:].*)?$',
|
||||
flags=re.I, cache=False)
|
||||
|
||||
doc_content = doc_com_body + KernRe(r'(.*)', cache=False)
|
||||
doc_inline_start = KernRe(r'^\s*/\*\*\s*$', cache=False)
|
||||
|
|
@ -115,8 +118,6 @@ class KernelEntry:
|
|||
self.config = config
|
||||
|
||||
self._contents = []
|
||||
self.sectcheck = ""
|
||||
self.struct_actual = ""
|
||||
self.prototype = ""
|
||||
|
||||
self.warnings = []
|
||||
|
|
@ -127,7 +128,6 @@ class KernelEntry:
|
|||
self.parameterdesc_start_lines = {}
|
||||
|
||||
self.section_start_lines = {}
|
||||
self.sectionlist = []
|
||||
self.sections = {}
|
||||
|
||||
self.anon_struct_union = False
|
||||
|
|
@ -189,7 +189,6 @@ class KernelEntry:
|
|||
self.parameterdescs[name] = contents
|
||||
self.parameterdesc_start_lines[name] = self.new_start_line
|
||||
|
||||
self.sectcheck += name + " "
|
||||
self.new_start_line = 0
|
||||
|
||||
else:
|
||||
|
|
@ -202,7 +201,6 @@ class KernelEntry:
|
|||
self.sections[name] += '\n' + contents
|
||||
else:
|
||||
self.sections[name] = contents
|
||||
self.sectionlist.append(name)
|
||||
self.section_start_lines[name] = self.new_start_line
|
||||
self.new_start_line = 0
|
||||
|
||||
|
|
@ -241,6 +239,14 @@ class KernelDoc:
|
|||
# Place all potential outputs into an array
|
||||
self.entries = []
|
||||
|
||||
#
|
||||
# We need Python 3.7 for its "dicts remember the insertion
|
||||
# order" guarantee
|
||||
#
|
||||
if sys.version_info.major == 3 and sys.version_info.minor < 7:
|
||||
self.emit_msg(0,
|
||||
'Python 3.7 or later is required for correct results')
|
||||
|
||||
def emit_msg(self, ln, msg, warning=True):
|
||||
"""Emit a message"""
|
||||
|
||||
|
|
@ -271,32 +277,20 @@ class KernelDoc:
|
|||
The actual output and output filters will be handled elsewhere
|
||||
"""
|
||||
|
||||
# The implementation here is different than the original kernel-doc:
|
||||
# instead of checking for output filters or actually output anything,
|
||||
# it just stores the declaration content at self.entries, as the
|
||||
# output will happen on a separate class.
|
||||
#
|
||||
# For now, we're keeping the same name of the function just to make
|
||||
# easier to compare the source code of both scripts
|
||||
|
||||
args["declaration_start_line"] = self.entry.declaration_start_line
|
||||
args["type"] = dtype
|
||||
args["warnings"] = self.entry.warnings
|
||||
|
||||
# TODO: use colletions.OrderedDict to remove sectionlist
|
||||
|
||||
sections = args.get('sections', {})
|
||||
sectionlist = args.get('sectionlist', [])
|
||||
item = KdocItem(name, dtype, self.entry.declaration_start_line, **args)
|
||||
item.warnings = self.entry.warnings
|
||||
|
||||
# Drop empty sections
|
||||
# TODO: improve empty sections logic to emit warnings
|
||||
sections = self.entry.sections
|
||||
for section in ["Description", "Return"]:
|
||||
if section in sectionlist:
|
||||
if not sections[section].rstrip():
|
||||
del sections[section]
|
||||
sectionlist.remove(section)
|
||||
|
||||
self.entries.append((name, args))
|
||||
if section in sections and not sections[section].rstrip():
|
||||
del sections[section]
|
||||
item.set_sections(sections, self.entry.section_start_lines)
|
||||
item.set_params(self.entry.parameterlist, self.entry.parameterdescs,
|
||||
self.entry.parametertypes,
|
||||
self.entry.parameterdesc_start_lines)
|
||||
self.entries.append(item)
|
||||
|
||||
self.config.log.debug("Output: %s:%s = %s", dtype, name, pformat(args))
|
||||
|
||||
|
|
@ -382,15 +376,6 @@ class KernelDoc:
|
|||
org_arg = KernRe(r'\s\s+').sub(' ', org_arg)
|
||||
self.entry.parametertypes[param] = org_arg
|
||||
|
||||
def save_struct_actual(self, actual):
|
||||
"""
|
||||
Strip all spaces from the actual param so that it looks like
|
||||
one string item.
|
||||
"""
|
||||
|
||||
actual = KernRe(r'\s*').sub("", actual, count=1)
|
||||
|
||||
self.entry.struct_actual += actual + " "
|
||||
|
||||
def create_parameter_list(self, ln, decl_type, args,
|
||||
splitter, declaration_name):
|
||||
|
|
@ -436,7 +421,6 @@ class KernelDoc:
|
|||
param = arg
|
||||
|
||||
dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg)
|
||||
self.save_struct_actual(param)
|
||||
self.push_parameter(ln, decl_type, param, dtype,
|
||||
arg, declaration_name)
|
||||
|
||||
|
|
@ -453,7 +437,6 @@ class KernelDoc:
|
|||
|
||||
dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg)
|
||||
|
||||
self.save_struct_actual(param)
|
||||
self.push_parameter(ln, decl_type, param, dtype,
|
||||
arg, declaration_name)
|
||||
|
||||
|
|
@ -486,7 +469,6 @@ class KernelDoc:
|
|||
|
||||
param = r.group(1)
|
||||
|
||||
self.save_struct_actual(r.group(2))
|
||||
self.push_parameter(ln, decl_type, r.group(2),
|
||||
f"{dtype} {r.group(1)}",
|
||||
arg, declaration_name)
|
||||
|
|
@ -498,52 +480,27 @@ class KernelDoc:
|
|||
continue
|
||||
|
||||
if dtype != "": # Skip unnamed bit-fields
|
||||
self.save_struct_actual(r.group(1))
|
||||
self.push_parameter(ln, decl_type, r.group(1),
|
||||
f"{dtype}:{r.group(2)}",
|
||||
arg, declaration_name)
|
||||
else:
|
||||
self.save_struct_actual(param)
|
||||
self.push_parameter(ln, decl_type, param, dtype,
|
||||
arg, declaration_name)
|
||||
|
||||
def check_sections(self, ln, decl_name, decl_type, sectcheck, prmscheck):
|
||||
def check_sections(self, ln, decl_name, decl_type):
|
||||
"""
|
||||
Check for errors inside sections, emitting warnings if not found
|
||||
parameters are described.
|
||||
"""
|
||||
|
||||
sects = sectcheck.split()
|
||||
prms = prmscheck.split()
|
||||
err = False
|
||||
|
||||
for sx in range(len(sects)): # pylint: disable=C0200
|
||||
err = True
|
||||
for px in range(len(prms)): # pylint: disable=C0200
|
||||
prm_clean = prms[px]
|
||||
prm_clean = KernRe(r'\[.*\]').sub('', prm_clean)
|
||||
prm_clean = attribute.sub('', prm_clean)
|
||||
|
||||
# ignore array size in a parameter string;
|
||||
# however, the original param string may contain
|
||||
# spaces, e.g.: addr[6 + 2]
|
||||
# and this appears in @prms as "addr[6" since the
|
||||
# parameter list is split at spaces;
|
||||
# hence just ignore "[..." for the sections check;
|
||||
prm_clean = KernRe(r'\[.*').sub('', prm_clean)
|
||||
|
||||
if prm_clean == sects[sx]:
|
||||
err = False
|
||||
break
|
||||
|
||||
if err:
|
||||
for section in self.entry.sections:
|
||||
if section not in self.entry.parameterlist and \
|
||||
not known_sections.search(section):
|
||||
if decl_type == 'function':
|
||||
dname = f"{decl_type} parameter"
|
||||
else:
|
||||
dname = f"{decl_type} member"
|
||||
|
||||
self.emit_msg(ln,
|
||||
f"Excess {dname} '{sects[sx]}' description in '{decl_name}'")
|
||||
f"Excess {dname} '{section}' description in '{decl_name}'")
|
||||
|
||||
def check_return_section(self, ln, declaration_name, return_type):
|
||||
"""
|
||||
|
|
@ -797,8 +754,7 @@ class KernelDoc:
|
|||
|
||||
self.create_parameter_list(ln, decl_type, members, ';',
|
||||
declaration_name)
|
||||
self.check_sections(ln, declaration_name, decl_type,
|
||||
self.entry.sectcheck, self.entry.struct_actual)
|
||||
self.check_sections(ln, declaration_name, decl_type)
|
||||
|
||||
# Adjust declaration for better display
|
||||
declaration = KernRe(r'([\{;])').sub(r'\1\n', declaration)
|
||||
|
|
@ -834,15 +790,7 @@ class KernelDoc:
|
|||
level += 1
|
||||
|
||||
self.output_declaration(decl_type, declaration_name,
|
||||
struct=declaration_name,
|
||||
definition=declaration,
|
||||
parameterlist=self.entry.parameterlist,
|
||||
parameterdescs=self.entry.parameterdescs,
|
||||
parametertypes=self.entry.parametertypes,
|
||||
parameterdesc_start_lines=self.entry.parameterdesc_start_lines,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose)
|
||||
|
||||
def dump_enum(self, ln, proto):
|
||||
|
|
@ -921,13 +869,6 @@ class KernelDoc:
|
|||
f"Excess enum value '%{k}' description in '{declaration_name}'")
|
||||
|
||||
self.output_declaration('enum', declaration_name,
|
||||
enum=declaration_name,
|
||||
parameterlist=self.entry.parameterlist,
|
||||
parameterdescs=self.entry.parameterdescs,
|
||||
parameterdesc_start_lines=self.entry.parameterdesc_start_lines,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose)
|
||||
|
||||
def dump_declaration(self, ln, prototype):
|
||||
|
|
@ -937,18 +878,13 @@ class KernelDoc:
|
|||
|
||||
if self.entry.decl_type == "enum":
|
||||
self.dump_enum(ln, prototype)
|
||||
return
|
||||
|
||||
if self.entry.decl_type == "typedef":
|
||||
elif self.entry.decl_type == "typedef":
|
||||
self.dump_typedef(ln, prototype)
|
||||
return
|
||||
|
||||
if self.entry.decl_type in ["union", "struct"]:
|
||||
elif self.entry.decl_type in ["union", "struct"]:
|
||||
self.dump_struct(ln, prototype)
|
||||
return
|
||||
|
||||
self.output_declaration(self.entry.decl_type, prototype,
|
||||
entry=self.entry)
|
||||
else:
|
||||
# This would be a bug
|
||||
self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')
|
||||
|
||||
def dump_function(self, ln, prototype):
|
||||
"""
|
||||
|
|
@ -1082,38 +1018,20 @@ class KernelDoc:
|
|||
f"expecting prototype for {self.entry.identifier}(). Prototype was for {declaration_name}() instead")
|
||||
return
|
||||
|
||||
prms = " ".join(self.entry.parameterlist)
|
||||
self.check_sections(ln, declaration_name, "function",
|
||||
self.entry.sectcheck, prms)
|
||||
self.check_sections(ln, declaration_name, "function")
|
||||
|
||||
self.check_return_section(ln, declaration_name, return_type)
|
||||
|
||||
if 'typedef' in return_type:
|
||||
self.output_declaration(decl_type, declaration_name,
|
||||
function=declaration_name,
|
||||
typedef=True,
|
||||
functiontype=return_type,
|
||||
parameterlist=self.entry.parameterlist,
|
||||
parameterdescs=self.entry.parameterdescs,
|
||||
parametertypes=self.entry.parametertypes,
|
||||
parameterdesc_start_lines=self.entry.parameterdesc_start_lines,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose,
|
||||
func_macro=func_macro)
|
||||
else:
|
||||
self.output_declaration(decl_type, declaration_name,
|
||||
function=declaration_name,
|
||||
typedef=False,
|
||||
functiontype=return_type,
|
||||
parameterlist=self.entry.parameterlist,
|
||||
parameterdescs=self.entry.parameterdescs,
|
||||
parametertypes=self.entry.parametertypes,
|
||||
parameterdesc_start_lines=self.entry.parameterdesc_start_lines,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose,
|
||||
func_macro=func_macro)
|
||||
|
||||
|
|
@ -1150,16 +1068,8 @@ class KernelDoc:
|
|||
self.create_parameter_list(ln, decl_type, args, ',', declaration_name)
|
||||
|
||||
self.output_declaration(decl_type, declaration_name,
|
||||
function=declaration_name,
|
||||
typedef=True,
|
||||
functiontype=return_type,
|
||||
parameterlist=self.entry.parameterlist,
|
||||
parameterdescs=self.entry.parameterdescs,
|
||||
parametertypes=self.entry.parametertypes,
|
||||
parameterdesc_start_lines=self.entry.parameterdesc_start_lines,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose)
|
||||
return
|
||||
|
||||
|
|
@ -1179,10 +1089,6 @@ class KernelDoc:
|
|||
return
|
||||
|
||||
self.output_declaration('typedef', declaration_name,
|
||||
typedef=declaration_name,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines,
|
||||
purpose=self.entry.declaration_purpose)
|
||||
return
|
||||
|
||||
|
|
@ -1664,10 +1570,7 @@ class KernelDoc:
|
|||
|
||||
if doc_end.search(line):
|
||||
self.dump_section()
|
||||
self.output_declaration("doc", self.entry.identifier,
|
||||
sectionlist=self.entry.sectionlist,
|
||||
sections=self.entry.sections,
|
||||
section_start_lines=self.entry.section_start_lines)
|
||||
self.output_declaration("doc", self.entry.identifier)
|
||||
self.reset_state(ln)
|
||||
|
||||
elif doc_content.search(line):
|
||||
|
|
|
|||
Loading…
Reference in New Issue