Skip to content

Commit 8471596

Browse files
committed
Add lcovrc options 'truncate_owner_table' and 'owner_table_entries' to
truncate header table when number of authors is large. Signed-off-by: Henry Cox <[email protected]>
1 parent 1453a3e commit 8471596

File tree

6 files changed

+252
-33
lines changed

6 files changed

+252
-33
lines changed

bin/genhtml

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,12 @@ sub write_html(*$);
258258
sub write_html_prolog(*$$);
259259
sub write_html_epilog(*$;$);
260260

261-
sub write_header(*$$$$$);
261+
sub write_header(*$$$$$$);
262262
sub write_header_prolog(*$);
263263
sub write_header_line(*@);
264264
sub write_header_epilog(*$);
265265

266-
sub write_file_table(*$$$$$);
266+
sub write_file_table(*$$$$$$);
267267
sub write_file_table_prolog(*$$$@);
268268
sub write_file_table_entry(*$$@);
269269
sub write_file_table_detail_entry(*$$$$@);
@@ -359,6 +359,9 @@ our @cutpoints;
359359
our @ageGroupHeader;
360360
our %ageHeaderToBin;
361361

362+
our @truncateOwnerTableLevels; # default: truncate everywhere if enabled
363+
our $ownerTableElements; # default: do not truncate
364+
362365
use constant {
363366
TYPE => 0,
364367
NAME => 1,
@@ -824,7 +827,7 @@ sub findOwnerList
824827
# branchCovData = [missed, total] or undef if not enabled
825828
# functionCov = [missed, total] or undef if not enabled
826829
# - sorted in descending order number of missed lines
827-
my ($self, $all) = @_;
830+
my ($self, $callback_type, $truncate_me, $all) = @_;
828831

829832
my @owners;
830833
foreach my $owner (keys(%{$self->[LINE_DATA]->[OWNERS]})) {
@@ -867,7 +870,22 @@ sub findOwnerList
867870
$b->[1]->[1] <=> $a->[1]->[1] || # then total
868871
$a->[0] cmp $b->[0]
869872
} @owners); # then by name
870-
return scalar(@owners) ? \@owners : undef;
873+
my $truncated;
874+
if ($truncate_me &&
875+
defined($ownerTableElements) &&
876+
$ownerTableElements < scalar(@owners) &&
877+
(0 == scalar(@truncateOwnerTableLevels) ||
878+
grep(/$callback_type/, @truncateOwnerTableLevels))
879+
) {
880+
# don't truncate the 'primary' key owner table
881+
882+
$truncated = (scalar(@owners) - $ownerTableElements);
883+
#lcovutil::info("truncating $truncated elements in header table\n");
884+
splice(@owners, $ownerTableElements);
885+
} else {
886+
$truncated = 0;
887+
}
888+
return (scalar(@owners) ? \@owners : undef, $truncated);
871889
}
872890

873891
sub append
@@ -1481,12 +1499,12 @@ sub summary
14811499

14821500
sub findOwnerList
14831501
{
1484-
my ($self, $all) = @_;
1502+
my $self = shift;
14851503
# return [ [owner, lineCovData, branchCovData]] for each owner
14861504
# where lineCovData = [missedCount, totalCount, callback]
14871505
# branchCovData = [missed, total, callback] or undef if not enabled
14881506
# - sorted in descending order number of missed lines
1489-
return $self->summary()->findOwnerList($all);
1507+
return $self->summary()->findOwnerList(@_);
14901508
}
14911509

14921510
sub dateDetailCallback
@@ -6288,6 +6306,8 @@ my %genhtml_rc_opts = (
62886306
"select_script" => \@rc_select_script,
62896307
'num_context_lines' => \$InInterestingRegion::num_context_lines,
62906308
'genhtml_date_bins' => \@rc_date_bins,
6309+
'truncate_owner_table' => \@truncateOwnerTableLevels,
6310+
'owner_table_entries' => \$ownerTableElements,
62916311
'genhtml_synthesize_missing' => \$synthesizeMissingFile,
62926312
'scope_regexp' => \$verboseScopeRegexp,);
62936313

@@ -6424,6 +6444,24 @@ if (@SourceFile::annotateScript) {
64246444
@datebins = sort(keys %uniqify);
64256445
}
64266446
SummaryInfo::setAgeGroups(@datebins);
6447+
6448+
if (defined($show_ownerBins)) {
6449+
@truncateOwnerTableLevels =
6450+
split($lcovutil::split_char,
6451+
join($lcovutil::split_char, @truncateOwnerTableLevels));
6452+
foreach my $l (@truncateOwnerTableLevels) {
6453+
lcovutil::ignorable_error($lcovutil::ERROR_USAGE,
6454+
"Unknown 'truncate_owner_table' level '$l': should be 'top', 'directory', or 'file'."
6455+
) unless grep(/^$l$/, ('top', 'directory', 'file'));
6456+
}
6457+
6458+
lcovutil::ignorable_error($lcovutil::ERROR_USAGE,
6459+
"Unsupported value 'owner_table_entries = $ownerTableElements': expected positive integer."
6460+
)
6461+
unless (!defined($ownerTableElements) ||
6462+
(Scalar::Util::looks_like_number($ownerTableElements) &&
6463+
0 < $ownerTableElements));
6464+
}
64276465
} else {
64286466
$treatNewFileAsBaseline = undef;
64296467
die("\"--show-owners\" option requires \"--annotate-script\" for revision control integration"
@@ -7028,9 +7066,9 @@ sub html_create($$)
70287066
#sub write_dir_page($$$$$$$;$)
70297067
sub write_dir_page
70307068
{
7031-
my ($ctrls, $page_suffix, $title, $rel_dir, $base_dir, $trunc_dir,
7032-
$summary, $perTestcaseResult)
7033-
= @_;
7069+
my ($callback_type, $ctrls, $page_suffix,
7070+
$title, $rel_dir, $base_dir,
7071+
$trunc_dir, $summary, $perTestcaseResult) = @_;
70347072

70357073
my $bin_prefix = $ctrls->[3];
70367074
# Generate directory overview page including details
@@ -7044,10 +7082,11 @@ sub write_dir_page
70447082
$title .= " - " if ($trunc_dir ne "");
70457083
write_html_prolog(*HTML_HANDLE, $base_dir, "LCOV - $title$trunc_dir");
70467084
my $activeTlaColsForType =
7047-
write_header(*HTML_HANDLE, $ctrls, $trunc_dir, $rel_dir, $summary,
7048-
undef);
7085+
write_header(*HTML_HANDLE, $callback_type, $ctrls, $trunc_dir,
7086+
$rel_dir, $summary, undef);
70497087
if (0 != $summary->sources()) {
7050-
write_file_table(*HTML_HANDLE, $base_dir, $perTestcaseResult,
7088+
write_file_table(*HTML_HANDLE, $callback_type, $base_dir,
7089+
$perTestcaseResult,
70517090
$summary, $ctrls, $activeTlaColsForType);
70527091
} else {
70537092
my $msg =
@@ -7069,6 +7108,7 @@ sub write_summary_pages($$$$$$$$)
70697108
my ($name, $summaryType, $summary, $show_details,
70707109
$rel_dir, $base_dir, $trunc_dir, $testhashes) = @_;
70717110

7111+
my $callback_type = $summaryType == 1 ? 'directory' : 'top';
70727112
foreach my $c ($summary->sources()) {
70737113
my $child = $summary->get_source($c);
70747114
# filter this one out if no data
@@ -7143,7 +7183,7 @@ sub write_summary_pages($$$$$$$$)
71437183
}
71447184

71457185
foreach my $params (@dirPageCalls) {
7146-
write_dir_page(@$params);
7186+
write_dir_page($callback_type, @$params);
71477187
last # only write 'index.html' - not the sorted versions
71487188
if ($summary->is_empty());
71497189
}
@@ -7182,6 +7222,7 @@ sub write_function_page($$$$$$$$$$$$$)
71827222
File::Spec->catfile($trunc_dir, $base_name) . " - functions";
71837223
write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle);
71847224
write_header(*HTML_HANDLE,
7225+
'file', # function table always written from 'file' level
71857226
[4, 'name', $sort_type,],
71867227
File::Spec->catfile($trunc_dir, $base_name),
71877228
File::Spec->catfile($rel_dir, $base_name),
@@ -7317,6 +7358,7 @@ sub process_file($$$$$)
73177358
File::Spec->catfile($trunc_dir, $base_name);
73187359
write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle);
73197360
write_header(*HTML_HANDLE,
7361+
'file',
73207362
[2, 'name', 0],
73217363
File::Spec->catfile($trunc_dir, $base_name),
73227364
File::Spec->catfile($rel_dir, $base_name),
@@ -7707,7 +7749,7 @@ sub write_description_file($$)
77077749
html_create(*HTML_HANDLE, "descriptions.$html_ext");
77087750

77097751
write_html_prolog(*HTML_HANDLE, "", "LCOV - test case descriptions");
7710-
write_header(*HTML_HANDLE, [3, 'name', 0], "", "", $summary, undef);
7752+
write_header(*HTML_HANDLE, 'top', [3, 'name', 0], "", "", $summary, undef);
77117753

77127754
write_test_table_prolog(*HTML_HANDLE,
77137755
"Test case descriptions - alphabetical list");
@@ -10518,14 +10560,19 @@ sub buildDateSummaryTable($$$$$$$$$)
1051810560
return \@table;
1051910561
}
1052010562

10521-
sub buildOwnerSummaryTable($$$$$$$$$)
10563+
sub buildOwnerSummaryTable($$$$$$$$$$)
1052210564
{
10523-
my ($ownerList, $summary, $covType,
10524-
$fileDetail, $nextLocationCallback, $title,
10525-
$detailLink, $numRows, $activeTlaList) = @_;
10565+
my ($ownerList, $num_truncated, $summary,
10566+
$covType, $fileDetail, $nextLocationCallback,
10567+
$title, $detailLink, $numRows,
10568+
$activeTlaList) = @_;
1052610569

1052710570
$title .= " (containing " .
1052810571
($main::show_ownerBins ? "" : "un-exercised ") . "code)";
10572+
$title .=
10573+
": $num_truncated author" .
10574+
($num_truncated == 1 ? '' : 's') . ' truncated'
10575+
if $num_truncated;
1052910576

1053010577
$title =
1053110578
"<a href=\"$detailLink\" title=\"Click to include ownership details in file table\">$title</a>"
@@ -10731,10 +10778,12 @@ sub build_html_path($$$$$)
1073110778
# list of all TLA types if user has asked not to suppress all-zero
1073210779
# columns)
1073310780

10734-
sub write_header(*$$$$$)
10781+
sub write_header(*$$$$$$)
1073510782
{
1073610783
local *HTML_HANDLE = shift;
10737-
my ($ctrl, $trunc_name, $rel_filename, $summary, $fileDetail) = @_;
10784+
my ($callback_type, $ctrl, $trunc_name, $rel_filename, $summary,
10785+
$fileDetail)
10786+
= @_;
1073810787
my ($type, $primary_key, $sort_type, $bin_type) = @$ctrl;
1073910788
my $base_dir;
1074010789
my $view;
@@ -11174,14 +11223,18 @@ END_OF_HTML
1117411223
# first, make sure there is owner data here (ie., owner data
1117511224
# was collected, or both that there is owner data and some
1117611225
# owners have uncovered code)
11177-
my $ownerList = $summary->findOwnerList($main::show_ownerBins &&
11178-
$main::show_ownerBins eq 'all');
11226+
# This it the header table - so we want to truncate the owner
11227+
# list if it is too long (and the user asked us to)
11228+
my ($ownerList, $truncated) =
11229+
$summary->findOwnerList($callback_type, 1,
11230+
$main::show_ownerBins && $main::show_ownerBins eq 'all');
1117911231
if (defined($ownerList)) {
1118011232
my $ownerBinDetailPage = "index-owner.$html_ext"
1118111233
if $type != $HDR_SOURCE;
1118211234

1118311235
my $table =
1118411236
buildOwnerSummaryTable($ownerList,
11237+
$truncated,
1118511238
$summary,
1118611239
SummaryInfo::LINE_DATA,
1118711240
$fileDetail,
@@ -11196,6 +11249,7 @@ END_OF_HTML
1119611249
if ($lcovutil::br_coverage) {
1119711250
my $br_table =
1119811251
buildOwnerSummaryTable($ownerList,
11252+
$truncated,
1119911253
$summary,
1120011254
SummaryInfo::BRANCH_DATA,
1120111255
$fileDetail,
@@ -11348,7 +11402,7 @@ sub get_br_code($$$$$$)
1134811402
}
1134911403

1135011404
#
11351-
# write_file_table(filehandle, base_dir, perTestcaseData,
11405+
# write_file_table(filehandle, callback_type, base_dir, perTestcaseData,
1135211406
# parentSummary, ctrlSettings, activeTlaCols)
1135311407
# ctrlSettings = [fileview, sort_type, details_type, sort_name]
1135411408
# perTestcaseData = [testhash, testfnchash, testbrhash]
@@ -11370,14 +11424,15 @@ sub get_br_code($$$$$$)
1137011424
# otherwise.
1137111425
#
1137211426

11373-
sub write_file_table(*$$$$$)
11427+
sub write_file_table(*$$$$$$)
1137411428
{
1137511429
local *HTML_HANDLE = $_[0];
11376-
my $base_dir = $_[1];
11377-
my $perTestcaseData = $_[2]; # undef or [lineCov, funcCov, branchCov]
11378-
my $dirSummary = $_[3]; # SummaryInfo object
11379-
my ($fileview, $primary_key, $sort_type, $bin_type) = @{$_[4]};
11380-
my $activeTlaCols = $_[5];
11430+
my $callback_type = $_[1];
11431+
my $base_dir = $_[2];
11432+
my $perTestcaseData = $_[3]; # undef or [lineCov, funcCov, branchCov]
11433+
my $dirSummary = $_[4]; # SummaryInfo object
11434+
my ($fileview, $primary_key, $sort_type, $bin_type) = @{$_[5]};
11435+
my $activeTlaCols = $_[6];
1138111436
# $fileview == 0 if listing directories, 1 if listing files
1138211437
# $primary_key in ("name", "owner", "date"). If $primary_key is:
1138311438
# - 'name': leftmost column is file/directory name -
@@ -11570,6 +11625,17 @@ sub write_file_table(*$$$$$)
1157011625
} else {
1157111626
@sorted = sort(keys(%owners));
1157211627
}
11628+
# don't truncate the 'owner detail table'
11629+
# if user asked to see the page, then they want to be able to navigate
11630+
# to all users
11631+
#if (defined($ownderTableElements) &&
11632+
# $ownerTableElements < scalar(@sorted)) &&
11633+
# (0 == scalar(@truncateOwnerTableLevels) ||
11634+
# grep(/$callback_type/, @truncateOwnerTableLevels)))) {
11635+
# # truncate owner list in header table
11636+
# splice(@sorted, $ownerTableElements);
11637+
#}
11638+
1157311639
foreach my $owner (@sorted) {
1157411640
push(@tableRows,
1157511641
FileOrDirectoryOwnerCallback->new($owner, $dirSummary));
@@ -11623,7 +11689,12 @@ sub write_file_table(*$$$$$)
1162311689
# do I need an option to suppress the list of owners?
1162411690
# maybe too much information, in some circumstances?
1162511691
# are there any non-empty owner tables here?
11626-
my $ownerList = $primaryCb->findOwnerList($all);
11692+
# If user explicitly asks to see the 'owner detail' page,
11693+
# then they must be interested in which code is written by
11694+
# each author - so we should not truncate the list
11695+
my ($ownerList, $runcated) =
11696+
$primaryCb->findOwnerList($callback_type, 0, $all);
11697+
die("unexpected truncate count") unless $runcated == 0;
1162711698
push(@secondaryRows, @$ownerList)
1162811699
if defined($ownerList);
1162911700
}

lcovrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,15 @@ branch_coverage = 0
371371
# which are not hit
372372
#genhtml_show_owner_table = 0 | 1 | all
373373

374+
# truncate owner table to show at most this many authors -
375+
# subset will be those with the highest count of un-exercised code
376+
# owner_table_entries = 5
377+
378+
# truncate the owner table at this level/these levels only
379+
# possible values are 'file', 'directory', 'top' (without quotes)
380+
# option may be specified multiple times and/or as a comma-separated list
381+
# truncate_owner_table = top,directory,file
382+
374383
# if enabled, show author of non-code source lines (e.g., comments)
375384
# in 'source' detail column
376385
#genhtml_show_noncode_owners = 0 | 1

man/genhtml.1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,27 @@ parameter; see man
19391939
.B lcovrc(5)
19401940
for details.
19411941

1942+
The lcovrc controls
1943+
.I owner_table_entries
1944+
and
1945+
.I truncate_owner_table
1946+
can be used to improve readability by limiting the number of authors who are displayed in the table
1947+
when the author number is large.
1948+
For example, if your configuration is:
1949+
.RS
1950+
.PP
1951+
.I owner_table_entries = 5
1952+
.IP
1953+
.PP
1954+
.I truncate_owner_table = top,directory
1955+
.PP
1956+
.RE
1957+
then the owner table displayed at the top- and directory-levels will be truncated while the table shown at the 'file' level will display the full list.
1958+
1959+
See man
1960+
.B lcovrc(5)
1961+
for details.
1962+
19421963

19431964
.RE
19441965
.BI "\-\-show\-noncode "

0 commit comments

Comments
 (0)