fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / t / codingstd / pmc_docs.t
blob08b314bcddba2a723d61fefa79153539c510883e
1 #! perl
2 # Copyright (C) 2006-2010, Parrot Foundation.
3 # $Id$
5 use strict;
6 use warnings;
8 use lib qw( . lib ../lib ../../lib );
9 use Test::More;
10 use Parrot::Config qw(%PConfig);
11 use Parrot::Distribution;
12 use Parrot::Headerizer;
14 =head1 NAME
16 t/codingstd/pmc_docs.t - checks for missing function documentation
18 =head1 SYNOPSIS
20     # test all files
21     % prove t/codingstd/pmc_docs.t
23     # test specific files
24     % perl t/codingstd/pmc_docs.t src/foo.pmc src/bar.pmc
26 =head1 DESCRIPTION
28 Checks that all PMC source files have documentation for each function
29 declared.
31 =cut
33 my $DIST = Parrot::Distribution->new;
34 my $headerizer = Parrot::Headerizer->new;
36 my @files = @ARGV ? @ARGV :
37     map {s/^$PConfig{build_dir}\///; $_}
38     map {s/\\/\//g; $_}
39     map {$_->path} $DIST->pmc_source_files();
41 plan tests => scalar @files;
43 my %todos;
44 while (<DATA>) {
45     next if /^#/;
46     next if /^\s*$/;
47     chomp;
48     $todos{$_} = 1;
51 my %all_files = ();
53 # Traverse each file, analyzing each function declaration therein, then
54 # post results in %all_files.
56 foreach my $path (@files) {
57     my $buf = $DIST->slurp($path);
58     my @function_decls = $headerizer->extract_function_declarations($buf);
60     # We start out asserting that every file will have documentation for each
61     # of its function declarations.  We then seek to contradict this
62     # assertion.
64     my %this_file = ( overall => 1 );
66     for my $function_decl (@function_decls) {
67         my $escaped_decl
68             = $headerizer->generate_documentation_signature($function_decl);
69         $this_file{$function_decl}{esc} = $escaped_decl;
71         if ( $buf =~ m/^\Q$escaped_decl\E$(.*?)^=cut/sm ) {
72             my $docs = $1;
73             $docs =~ s/\s//g;
74             if ($docs eq '') { # boilerplate only
75                 $this_file{$function_decl}{status} = 0;
76                 $this_file{overall} = 0;
77             }
78             else { # documentation found
79                 $this_file{$function_decl}{status} = 1;
80             }
81         }
82         else { # no documentation found
83             $this_file{$function_decl}{status} = undef;
84             $this_file{overall} = 0;
85         }
86     }
87     $all_files{$path} = \%this_file;
90 foreach my $path (sort keys %all_files) {
91     TODO: {
92         local $TODO = 'Missing function docs' if $todos{$path};
93         ok( $all_files{$path}{overall}, $path )
94             or diag( diagnosis( \%all_files, $path ) );
95     }
98 sub diagnosis {
99     my ($all_files_ref, $path) = @_;
100     my $missing = '';
101     my $boilerplate = '';
102     my %this_file = %{ $all_files_ref->{$path} };
103     delete $this_file{overall};
104     foreach my $decl ( sort keys %this_file ) {
105         if ( ! defined $this_file{$decl}{status} ) {
106             $missing .= "$decl\n";
107             $missing .= "Need:\n";
108             $missing .= "$this_file{$decl}{esc}\n\n";
109         }
110         elsif ( ! $this_file{$decl}{status} ) {
111             $boilerplate .= "$this_file{$decl}{esc}\n\n";
112         }
113         else {
114             # docs!
115         }
116     }
117     my $diagnosis = "$path\n";
118     $diagnosis .= "Undocumented functions:\n\n$missing" if $missing;
119     $diagnosis .= "Boilerplate only:\n$boilerplate" if $boilerplate;
120     return "$diagnosis";
123 __DATA__
124 src/pmc/bigint.pmc
125 src/pmc/callcontext.pmc
126 src/pmc/class.pmc
127 src/pmc/complex.pmc
128 src/pmc/coroutine.pmc
129 src/pmc/eval.pmc
130 src/pmc/imageio.pmc
131 src/pmc/namespace.pmc
132 src/pmc/nci.pmc
133 src/pmc/object.pmc
134 src/pmc/sub.pmc
135 src/pmc/threadinterpreter.pmc
136 src/pmc/unmanagedstruct.pmc
138 # Local Variables:
139 #   mode: cperl
140 #   cperl-indent-level: 4
141 #   fill-column: 100
142 # End:
143 # vim: expandtab shiftwidth=4: