JD2022-TU1/main/tools/qa/Understand/Metrics/c_highestMetrics_files.pl

247 lines
7.1 KiB
Perl

# Synopsis: generate a list of highest metrics for files. (C/C++)
#
# Requires one existing Understand for C++ databases
#
# Categories: Project Report
#
# Languages: C
#
# Usage:
sub usage($)
{
return << "END_USAGE";
${ \( shift @_ ) }
Usage: c_highestmetrics_files.pl -db database -root_path path -maxcount maxcount -min_line line -min_linecode linecode -min_classes classes -output_file file
-db database Specify Understand database (required for uperl, inherited from Understand)
-root_path path Specify a path for files to into account ()
-maxcount maxcount Specify the max number of functions per categories (default=10)
-min_line linecode Specify the min number of lines (default=750)
-min_linecode line Specify the min number of lines of code (default=1000)
-min_classes classes Specify the min number of declared classes (default=20)
-output_file file Specify the name of the output file
END_USAGE
}
# For the latest Understand perl API documentation, see
# http://www.scitools.com/perl.html
#
use Understand;
use Tie::RefHash;
use Getopt::Long;
use strict;
my $dbPath;
my $help;
my $maxcount = 10;
my $root_path = "";
my $countLine_Threshold = 1000;
my $countLineCode_Threshold = 750;
my $countDeclClass_Threshold = 20;
my $output_file = "";
# if option is not found in the command line, corresponding variable is not changed, and use the initialized value.
GetOptions(
"db=s" => \$dbPath,
"maxcount=s" => \$maxcount,
"root_path=s" => \$root_path,
"min_line=s" => \$countLine_Threshold,
"min_linecode=s" => \$countLineCode_Threshold,
"min_classes=s" => \$countDeclClass_Threshold,
"output_file=s" => \$output_file,
"help" => \$help,
);
# open the database
my $db=openDatabase($dbPath);
my $title = "Files";
my $kindFiles = "File";
my $kindCodeFiles = "Code File";
my $kindHeaderFiles = "Header File";
my $fh;
my $writeInFile = 0;
prepareOutput();
display("-------------------------------------------------------\n");
display("Highest metrics for files\n\n");
display("Database : ".$dbPath."\n");
display("maxcount : ".$maxcount."\n");
display("root_path : ".$root_path."\n");
display("min_line : ".$countLine_Threshold."\n");
display("min_linecode : ".$countLineCode_Threshold."\n");
display("min_classes : ".$countDeclClass_Threshold."\n");
display("output_file : ".$output_file."\n");
display("\n");
generateHighestMetrics($db, $title, $kindFiles, lc $root_path, "CountLine", $countLine_Threshold, $maxcount);
generateHighestMetrics($db, $title, $kindCodeFiles, lc $root_path, "CountLineCode", $countLineCode_Threshold, $maxcount);
generateHighestMetrics($db, $title, $kindHeaderFiles, lc $root_path, "CountDeclClass", $countDeclClass_Threshold, $maxcount);
display("-------------------------------------------------------\n");
closeDatabase($db);
closeOutput();
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
# subroutines
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
sub openDatabase($)
{
my ($dbPath) = @_;
my $db = Understand::Gui::db();
# path not allowed if opened by understand
if ($db && $dbPath) {
die "database already opened by GUI, don't use -db option\n";
}
# open database if not already open
if (!$db) {
my $status;
die usage("Error, database not specified\n\n") unless ($dbPath);
($db,$status)=Understand::open($dbPath);
die "Error opening database: ",$status,"\n" if $status;
}
return($db);
}
sub closeDatabase($)
{
my ($db)=@_;
# close database only if we opened it
$db->close() if ($dbPath);
}
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
sub prepareOutput {
if($output_file eq "") {
$writeInFile = 0;
} else {
if(open($fh, '>', $output_file)) {
$writeInFile = 1;
}
}
}
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
sub closeOutput {
if($writeInFile) {
close $fh;
}
}
# ------------------------------------------------------------------------------------------
# Parameters
# - db
# - title
# - kind
# - threshold name
# - metrics name
# - max result count
# ------------------------------------------------------------------------------------------
sub generateHighestMetrics {
my ($db, $title, $kind, $root_path, $metrics, $threshold, $maxcount) = @_;
# retrieve threshold option value
$threshold = 1 if ($threshold < 1);
# build hash of matching entities
tie my %ents, 'Tie::RefHash';
my $ents;
foreach my $file ($db->ents($kind)) {
# keep file if not in excluded path and if metrics > threshold
my $val = $file->metric($metrics);
if ($val >= $threshold) {
if(index(lc $file->longname(), $root_path) != -1) {
$ents{$file} = $val;
}
}
}
printTitleMetric($title, $metrics, $threshold);
# output, sorted by value, then by name
my $cur = 1;
foreach my $file (sort {
$ents{$b} <=> $ents{$a}
|| lc($b->longname()) cmp lc($a->longname());
} keys %ents) {
if($cur <= $maxcount) {
printOneResult($file, $ents{$file});
}
$cur++;
}
display("\n");
}
# ------------------------------------------------------------------------------------------
# Parameters
# - report
# - title
# - metrics name
# - threshold
# ------------------------------------------------------------------------------------------
sub printTitleMetric {
my ($title, $metrics, $threshold) = @_;
display("-------------------------------------------------------\n");
display($title);
display(" with highest metric ");
display($metrics);
display(" ( > ");
display($threshold);
display(" ) :\n");
display("-------------------------------------------------------\n");
}
# ------------------------------------------------------------------------------------------
# Parameters
# - report
# - entity
# - metric value
# ------------------------------------------------------------------------------------------
sub printOneResult {
my ($entity, $value) = @_;
#value in red
my $str = sprintf("%5d " ,$value);
display($str);
# entity
my $length = length($entity->longname());
$str = $entity->longname();
# if entity is not a file, print its kind
if($entity->kindname() eq "File")
{}
else {
$str .= sprintf("%*s" , 60 - $length , "(");
$str .= $entity->kindname();
$str .= ")";
}
display($str);
display("\n");
}
# ------------------------------------------------------------------------------------------
# Parameters
# - text
# ------------------------------------------------------------------------------------------
sub display {
my ($text) = @_;
if($writeInFile) {
print $fh $text;
} else {
print $text;
}
}