109 lines
3.4 KiB
Perl
Executable File
109 lines
3.4 KiB
Perl
Executable File
#!/usr/bin/perl
|
||
use strict;
|
||
use warnings;
|
||
use utf8;
|
||
binmode(STDOUT, ":utf8");
|
||
|
||
# Если аргументы переданы — берем их, иначе ищем все .go файлы в текущей папке
|
||
my @files = @ARGV ? @ARGV : grep { !/_test\.go$/ } glob "*.go";
|
||
|
||
if (!@files) {
|
||
print "No files to check.\n";
|
||
exit;
|
||
}
|
||
|
||
foreach my $file (@files) {
|
||
if (!-e $file) {
|
||
warn "File not found: $file\n";
|
||
next;
|
||
}
|
||
process_file($file);
|
||
}
|
||
|
||
sub process_file {
|
||
my ($filename) = @_;
|
||
|
||
open my $fh, '<:utf8', $filename or die "Could not open $filename: $!";
|
||
my @lines = <$fh>;
|
||
close $fh;
|
||
|
||
my $total_public = 0;
|
||
my $covered_count = 0;
|
||
my @uncovered;
|
||
|
||
my $current_comment = "";
|
||
|
||
for (my $i = 0; $i < scalar @lines; $i++) {
|
||
my $line = $lines[$i];
|
||
|
||
if ($line =~ /^\s*\/\/\s*(.*)/) {
|
||
$current_comment .= $1 . "\n";
|
||
next;
|
||
}
|
||
|
||
# 1. Обработка функций и методов
|
||
if ($line =~ /^\s*func\s+(?:\([^\)]+\)\s+)?([A-Z]\w*)(\s*\(.*?\))?(\s+[^({\s][^{]*)?/) {
|
||
my ($name, $params_sig, $return_sig) = ($1, $2, $3);
|
||
|
||
if ($name ne "String") {
|
||
$total_public++;
|
||
my $has_params = ($params_sig && $params_sig =~ /\(\s*[^)]+\s*\)/) ? 1 : 0;
|
||
my $has_returns = 0;
|
||
if ($return_sig) {
|
||
$return_sig =~ s/^\s+|\s+$//g;
|
||
$has_returns = 1 if $return_sig ne "" && $return_sig ne "error";
|
||
}
|
||
|
||
my ($is_ok, $reason) = check_documentation($name, $current_comment, $has_params, $has_returns);
|
||
if ($is_ok) { $covered_count++; }
|
||
else { push @uncovered, "$name ($reason)"; }
|
||
}
|
||
}
|
||
# 2. Обработка типов и структур
|
||
elsif ($line =~ /^\s*type\s+([A-Z]\w*)/) {
|
||
my $name = $1;
|
||
$total_public++;
|
||
|
||
my ($is_ok, $reason) = check_documentation($name, $current_comment, 0, 0);
|
||
if ($is_ok) { $covered_count++; }
|
||
else { push @uncovered, "$name ($reason)"; }
|
||
}
|
||
|
||
$current_comment = "" if $line =~ /\S/ && $line !~ /^\s*\/\//;
|
||
}
|
||
|
||
render_report($filename, $total_public, $covered_count, \@uncovered);
|
||
}
|
||
|
||
sub check_documentation {
|
||
my ($name, $comment, $needs_params, $needs_returns) = @_;
|
||
|
||
return (0, "no doc") if !$comment || length($comment) < 10;
|
||
return (0, "not GoDoc format") if $comment !~ /^\s*\Q$name\E\b/i;
|
||
return (0, "no latin characters") if $comment !~ /[a-zA-Z]/;
|
||
return (0, "contains Cyrillic") if $comment =~ /[а-яА-ЯёЁ]/;
|
||
|
||
if ($needs_params && $comment !~ /Parameters\s*:/i) {
|
||
return (0, "missing Parameters section");
|
||
}
|
||
if ($needs_returns && $comment !~ /Returns\b/i) {
|
||
return (0, "missing Returns section");
|
||
}
|
||
|
||
return (1, "");
|
||
}
|
||
|
||
sub render_report {
|
||
my ($file, $total, $covered, $uncovered_ref) = @_;
|
||
my $percent = $total > 0 ? sprintf("%.0f", ($covered / $total) * 100) : 100;
|
||
my $status = $percent == 100 ? "[+]" : "[-]";
|
||
|
||
print "Файл: $file\n";
|
||
print " $status Покрытие $percent% ($covered/$total).\n";
|
||
if (@$uncovered_ref) {
|
||
print " Проблемы:\n";
|
||
print " - $_\n" for @$uncovered_ref;
|
||
}
|
||
print "-" x 50 . "\n";
|
||
}
|