mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
scripts/kernel-doc: Suggest possible names for excess descriptions
Recent check_sections() change added a warning if a documentation tag member name does not match the detected struct/union member names. Since the checker knows all possible names, we can suggest known names, so that it's more obvious how to deal with the warning. Signed-off-by: Ryszard Knop <ryszard.knop@intel.com> Tested-by: Randy Dunlap <rdunlap@infradead.org> Acked-by: Randy Dunlap <rdunlap@infradead.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Message-ID: <20260717125753.634550-1-ryszard.knop@intel.com>
This commit is contained in:
committed by
Jonathan Corbet
parent
9b9c442dda
commit
d7758384cc
@@ -11,6 +11,7 @@ and extract embedded documentation comments from it.
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
import difflib
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
|
||||||
from kdoc.c_lex import CTokenizer, tokenizer_set_log
|
from kdoc.c_lex import CTokenizer, tokenizer_set_log
|
||||||
@@ -558,6 +559,50 @@ class KernelDoc:
|
|||||||
self.push_parameter(ln, decl_type, param, dtype,
|
self.push_parameter(ln, decl_type, param, dtype,
|
||||||
arg, declaration_name)
|
arg, declaration_name)
|
||||||
|
|
||||||
|
def get_suggestions_hint(self, decl_name, possible_names):
|
||||||
|
# For decl name 'flags' or 'flgas', suggests 'substruct.flags'
|
||||||
|
submember_exact = []
|
||||||
|
submember_substrings = []
|
||||||
|
submember_suggestions = []
|
||||||
|
for possible_name in possible_names:
|
||||||
|
parts = possible_name.strip().split('.')
|
||||||
|
if len(parts) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
final_part = parts[-1]
|
||||||
|
if decl_name == final_part:
|
||||||
|
submember_exact.append(possible_name)
|
||||||
|
elif decl_name in final_part:
|
||||||
|
submember_substrings.append(possible_name)
|
||||||
|
elif difflib.get_close_matches(decl_name, [final_part]):
|
||||||
|
submember_suggestions.append(possible_name)
|
||||||
|
|
||||||
|
# For decl name 'flgas', suggests 'flags'
|
||||||
|
full_suggestions = difflib.get_close_matches(decl_name, possible_names)
|
||||||
|
|
||||||
|
# For decl name 'member', suggests 'longer_member'
|
||||||
|
full_substrings = [name for name in possible_names if decl_name in name]
|
||||||
|
|
||||||
|
ordered_lists = [
|
||||||
|
submember_exact,
|
||||||
|
submember_substrings,
|
||||||
|
submember_suggestions,
|
||||||
|
full_suggestions,
|
||||||
|
full_substrings,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Deduplicate but maintain order from most to least likely:
|
||||||
|
unique_suggestions = {}
|
||||||
|
for suggestion_list in ordered_lists:
|
||||||
|
for suggestion in suggestion_list:
|
||||||
|
unique_suggestions[suggestion] = None
|
||||||
|
|
||||||
|
suggestions = list(unique_suggestions.keys())
|
||||||
|
if not suggestions:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return f"(did you mean one of: '{"', '".join(suggestions)}')"
|
||||||
|
|
||||||
def check_sections(self, ln, decl_name, decl_type):
|
def check_sections(self, ln, decl_name, decl_type):
|
||||||
"""
|
"""
|
||||||
Check for errors inside sections, emitting warnings if not found
|
Check for errors inside sections, emitting warnings if not found
|
||||||
@@ -566,12 +611,13 @@ class KernelDoc:
|
|||||||
for section in self.entry.sections:
|
for section in self.entry.sections:
|
||||||
if section not in self.entry.parameterlist and \
|
if section not in self.entry.parameterlist and \
|
||||||
not known_sections.search(section):
|
not known_sections.search(section):
|
||||||
|
hint = self.get_suggestions_hint(section, self.entry.parameterlist)
|
||||||
if decl_type == 'function':
|
if decl_type == 'function':
|
||||||
dname = f"{decl_type} parameter"
|
dname = f"{decl_type} parameter"
|
||||||
else:
|
else:
|
||||||
dname = f"{decl_type} member"
|
dname = f"{decl_type} member"
|
||||||
self.emit_msg(ln,
|
self.emit_msg(ln,
|
||||||
f"Excess {dname} '{section}' description in '{decl_name}'")
|
f"Excess {dname} '{section}' description in '{decl_name}' {hint}".strip())
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check that documented parameter names (from doc comments, including
|
# Check that documented parameter names (from doc comments, including
|
||||||
@@ -591,12 +637,13 @@ class KernelDoc:
|
|||||||
if param_name in self.entry.parameterlist:
|
if param_name in self.entry.parameterlist:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
hint = self.get_suggestions_hint(param_name, self.entry.parameterlist)
|
||||||
if decl_type == 'function':
|
if decl_type == 'function':
|
||||||
dname = f"{decl_type} parameter"
|
dname = f"{decl_type} parameter"
|
||||||
else:
|
else:
|
||||||
dname = f"{decl_type} member"
|
dname = f"{decl_type} member"
|
||||||
self.emit_msg(ln,
|
self.emit_msg(ln,
|
||||||
f"Excess {dname} '{param_name}' description in '{decl_name}'")
|
f"Excess {dname} '{param_name}' description in '{decl_name}' {hint}".strip())
|
||||||
|
|
||||||
def check_return_section(self, ln, declaration_name, return_type):
|
def check_return_section(self, ln, declaration_name, return_type):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user