kernel-doc: check for extra kernel-doc notations
Add functionality to check for function parameters or structure (or union/typedef/enum) field members that are described in kernel-doc but are not part of the expected (declared) parameters or structure. These generate warnings that are called "Excess" descriptions. Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
Родитель
179efcb47d
Коммит
a1d94aa556
|
@ -289,6 +289,8 @@ my %parameterdescs;
|
||||||
my @parameterlist;
|
my @parameterlist;
|
||||||
my %sections;
|
my %sections;
|
||||||
my @sectionlist;
|
my @sectionlist;
|
||||||
|
my $sectcheck;
|
||||||
|
my $struct_actual;
|
||||||
|
|
||||||
my $contents = "";
|
my $contents = "";
|
||||||
my $section_default = "Description"; # default section
|
my $section_default = "Description"; # default section
|
||||||
|
@ -378,10 +380,12 @@ sub dump_section {
|
||||||
# print STDERR "parameter def '$1' = '$contents'\n";
|
# print STDERR "parameter def '$1' = '$contents'\n";
|
||||||
$name = $1;
|
$name = $1;
|
||||||
$parameterdescs{$name} = $contents;
|
$parameterdescs{$name} = $contents;
|
||||||
|
$sectcheck = $sectcheck . $name . " ";
|
||||||
} elsif ($name eq "@\.\.\.") {
|
} elsif ($name eq "@\.\.\.") {
|
||||||
# print STDERR "parameter def '...' = '$contents'\n";
|
# print STDERR "parameter def '...' = '$contents'\n";
|
||||||
$name = "...";
|
$name = "...";
|
||||||
$parameterdescs{$name} = $contents;
|
$parameterdescs{$name} = $contents;
|
||||||
|
$sectcheck = $sectcheck . $name . " ";
|
||||||
} else {
|
} else {
|
||||||
# print STDERR "other section '$name' = '$contents'\n";
|
# print STDERR "other section '$name' = '$contents'\n";
|
||||||
if (defined($sections{$name}) && ($sections{$name} ne "")) {
|
if (defined($sections{$name}) && ($sections{$name} ne "")) {
|
||||||
|
@ -1405,21 +1409,25 @@ sub dump_union($$) {
|
||||||
sub dump_struct($$) {
|
sub dump_struct($$) {
|
||||||
my $x = shift;
|
my $x = shift;
|
||||||
my $file = shift;
|
my $file = shift;
|
||||||
|
my $nested;
|
||||||
|
|
||||||
if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
|
if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
|
||||||
$declaration_name = $2;
|
$declaration_name = $2;
|
||||||
my $members = $3;
|
my $members = $3;
|
||||||
|
|
||||||
# ignore embedded structs or unions
|
# ignore embedded structs or unions
|
||||||
$members =~ s/{.*}//g;
|
$members =~ s/({.*})//g;
|
||||||
|
$nested = $1;
|
||||||
|
|
||||||
# ignore members marked private:
|
# ignore members marked private:
|
||||||
$members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
|
$members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
|
||||||
$members =~ s/\/\*.*?private:.*//gos;
|
$members =~ s/\/\*.*?private:.*//gos;
|
||||||
# strip comments:
|
# strip comments:
|
||||||
$members =~ s/\/\*.*?\*\///gos;
|
$members =~ s/\/\*.*?\*\///gos;
|
||||||
|
$nested =~ s/\/\*.*?\*\///gos;
|
||||||
|
|
||||||
create_parameterlist($members, ';', $file);
|
create_parameterlist($members, ';', $file);
|
||||||
|
check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
|
||||||
|
|
||||||
output_declaration($declaration_name,
|
output_declaration($declaration_name,
|
||||||
'struct',
|
'struct',
|
||||||
|
@ -1505,6 +1513,14 @@ sub dump_typedef($$) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub save_struct_actual($) {
|
||||||
|
my $actual = shift;
|
||||||
|
|
||||||
|
# strip all spaces from the actual param so that it looks like one string item
|
||||||
|
$actual =~ s/\s*//g;
|
||||||
|
$struct_actual = $struct_actual . $actual . " ";
|
||||||
|
}
|
||||||
|
|
||||||
sub create_parameterlist($$$) {
|
sub create_parameterlist($$$) {
|
||||||
my $args = shift;
|
my $args = shift;
|
||||||
my $splitter = shift;
|
my $splitter = shift;
|
||||||
|
@ -1537,6 +1553,7 @@ sub create_parameterlist($$$) {
|
||||||
$param = $1;
|
$param = $1;
|
||||||
$type = $arg;
|
$type = $arg;
|
||||||
$type =~ s/([^\(]+\(\*?)\s*$param/$1/;
|
$type =~ s/([^\(]+\(\*?)\s*$param/$1/;
|
||||||
|
save_struct_actual($param);
|
||||||
push_parameter($param, $type, $file);
|
push_parameter($param, $type, $file);
|
||||||
} elsif ($arg) {
|
} elsif ($arg) {
|
||||||
$arg =~ s/\s*:\s*/:/g;
|
$arg =~ s/\s*:\s*/:/g;
|
||||||
|
@ -1561,14 +1578,17 @@ sub create_parameterlist($$$) {
|
||||||
|
|
||||||
foreach $param (@args) {
|
foreach $param (@args) {
|
||||||
if ($param =~ m/^(\*+)\s*(.*)/) {
|
if ($param =~ m/^(\*+)\s*(.*)/) {
|
||||||
|
save_struct_actual($2);
|
||||||
push_parameter($2, "$type $1", $file);
|
push_parameter($2, "$type $1", $file);
|
||||||
}
|
}
|
||||||
elsif ($param =~ m/(.*?):(\d+)/) {
|
elsif ($param =~ m/(.*?):(\d+)/) {
|
||||||
if ($type ne "") { # skip unnamed bit-fields
|
if ($type ne "") { # skip unnamed bit-fields
|
||||||
|
save_struct_actual($1);
|
||||||
push_parameter($1, "$type:$2", $file)
|
push_parameter($1, "$type:$2", $file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
save_struct_actual($param);
|
||||||
push_parameter($param, $type, $file);
|
push_parameter($param, $type, $file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1634,6 +1654,46 @@ sub push_parameter($$$) {
|
||||||
$parametertypes{$param} = $type;
|
$parametertypes{$param} = $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub check_sections($$$$$$) {
|
||||||
|
my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
|
||||||
|
my @sects = split ' ', $sectcheck;
|
||||||
|
my @prms = split ' ', $prmscheck;
|
||||||
|
my $err;
|
||||||
|
my ($px, $sx);
|
||||||
|
my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
|
||||||
|
|
||||||
|
foreach $sx (0 .. $#sects) {
|
||||||
|
$err = 1;
|
||||||
|
foreach $px (0 .. $#prms) {
|
||||||
|
$prm_clean = $prms[$px];
|
||||||
|
$prm_clean =~ s/\[.*\]//;
|
||||||
|
$prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
|
||||||
|
##$prm_clean =~ s/^\**//;
|
||||||
|
if ($prm_clean eq $sects[$sx]) {
|
||||||
|
$err = 0;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($err) {
|
||||||
|
if ($decl_type eq "function") {
|
||||||
|
print STDERR "Warning(${file}:$.): " .
|
||||||
|
"Excess function parameter " .
|
||||||
|
"'$sects[$sx]' " .
|
||||||
|
"description in '$decl_name'\n";
|
||||||
|
++$warnings;
|
||||||
|
} else {
|
||||||
|
if ($nested !~ m/\Q$sects[$sx]\E/) {
|
||||||
|
print STDERR "Warning(${file}:$.): " .
|
||||||
|
"Excess struct/union/enum/typedef member " .
|
||||||
|
"'$sects[$sx]' " .
|
||||||
|
"description in '$decl_name'\n";
|
||||||
|
++$warnings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
##
|
##
|
||||||
# takes a function prototype and the name of the current file being
|
# takes a function prototype and the name of the current file being
|
||||||
# processed and spits out all the details stored in the global
|
# processed and spits out all the details stored in the global
|
||||||
|
@ -1699,6 +1759,9 @@ sub dump_function($$) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $prms = join " ", @parameterlist;
|
||||||
|
check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
|
||||||
|
|
||||||
output_declaration($declaration_name,
|
output_declaration($declaration_name,
|
||||||
'function',
|
'function',
|
||||||
{'function' => $declaration_name,
|
{'function' => $declaration_name,
|
||||||
|
@ -1757,6 +1820,8 @@ sub reset_state {
|
||||||
@parameterlist = ();
|
@parameterlist = ();
|
||||||
%sections = ();
|
%sections = ();
|
||||||
@sectionlist = ();
|
@sectionlist = ();
|
||||||
|
$sectcheck = "";
|
||||||
|
$struct_actual = "";
|
||||||
$prototype = "";
|
$prototype = "";
|
||||||
|
|
||||||
$state = 0;
|
$state = 0;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче