.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Perl::Metrics::Simple::Analysis::File 3pm" .TH Perl::Metrics::Simple::Analysis::File 3pm "2021-03-24" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Perl::Metrics::Simple::Analysis::File \- Methods analyzing a single file. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use Perl::Metrics::Simple::Analysis::File; \& my $object = Perl::Metrics::Simple::Analysis::File\->new(file => \*(Aqpath/to/file\*(Aq); .Ve .SH "VERSION" .IX Header "VERSION" This is \s-1VERSION 0.1\s0 .SH "DESCRIPTION" .IX Header "DESCRIPTION" A \fBPerl::Metrics::Simple::Analysis::File\fR object is created by \&\fBPerl::Metrics::Simple\fR for each file analyzed. These objects are aggregated into a \fBPerl::Metrics::Simple::Analysis\fR object by \fBPerl::Metrics::Simple\fR. .PP In general you will not use this class directly, instead you will use \&\fBPerl::Metrics::Simple\fR, but there's no harm in exposing the various methods this class provides. .SH "CLASS METHODS" .IX Header "CLASS METHODS" .SS "new" .IX Subsection "new" Takes named parameters, current only the \fIpath\fR parameter is recognized: .PP .Vb 1 \& my $file_results = BPerl::Metrics::Simple::Analysis::File\->new( path => $path ); .Ve .PP Returns a new \fBPerl::Metrics::Simple::Analysis::File\fR object which has been populated with the results of analyzing the file at \fIpath\fR. .PP Throws an exception if the \fIpath\fR is missing or unreadable. .SH "OBJECT METHODS" .IX Header "OBJECT METHODS" Call on an object. .SS "all_counts" .IX Subsection "all_counts" Convenience method. Takes no arguments and returns a hashref of all counts: { path => \f(CW$self\fR\->path, lines => \f(CW$self\fR\->lines, main_stats => \f(CW$self\fR\->main_stats, subs => \f(CW$self\fR\->subs, packages => \f(CW$self\fR\->packages, } .SS "analyze_main" .IX Subsection "analyze_main" Takes a \fB\s-1PPI\s0\fR document and an arrayref of \fBPPI::Statement::Sub\fR objects and returns a hashref with information about the 'main' (non-subroutine) portions of the document: .PP .Vb 6 \& { \& lines => $lines, # Line count outside subs. Skips comments and pod. \& mccabe_complexity => $complexity, # Cyclomatic complexity of all non\-sub areas \& path => \*(Aq/path/to/file\*(Aq, \& name => \*(Aq{code not in named subroutines}\*(Aq, # always the same name \& }; .Ve .SS "get_node_length" .IX Subsection "get_node_length" Takes a \fB\s-1PPI\s0\fR node and returns a count of the newlines it contains. \fB\s-1PPI\s0\fR normalizes line endings to newlines so \&\s-1CR/LF, CR\s0 and \s-1LF\s0 all come out the same. The line counts reported by the various methods in this class all \fBexclude\fR blank lines, comment lines and pod (the \fB\s-1PPI\s0\fR document is pruned before counting.) .SS "lines" .IX Subsection "lines" Total non-blank, non-comment, non-pod lines. .SS "main_stats" .IX Subsection "main_stats" Returns the hashref generated by \fIanalyze_main\fR without re-analyzing document. .SS "logic_keywords" .IX Subsection "logic_keywords" Returns an array (in array context) or ref-to-ARRAY of the keywords used in calculating complexity. See \fILogic Keywords\fR section below. .SS "logic_operators" .IX Subsection "logic_operators" Returns an array (in array context) or ref-to-ARRAY of the operators used in calculating complexity. See \fILogic Operators\fR section below. .SS "method_modifiers" .IX Subsection "method_modifiers" Returns an array (in array context) or ref-to-ARRAY of the method modifiers considered to return methods during calculating complexity. See \fIMethod modifiers\fR section below. .SS "measure_complexity" .IX Subsection "measure_complexity" Takes a \fB\s-1PPI\s0\fR element and measures an approximation of the McCabe Complexity (aka Cyclomatic Complexity) of the code. .PP McCabe Complexity is basically a count of how many paths there are through the code. .PP We use a simplified method for counting this, which ignores things like the possibility that a 'use' statement could throw an exception. .PP The actual measurement we use for a chunk of code is 1 plus 1 each logic keyword or operator: .PP \fILogic operators:\fR .IX Subsection "Logic operators:" .PP The default list is: .PP \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::DEFAULT_LOGIC_OPERATORS\fI\fR .PP .Vb 10 \& ! \& !~ \& && \& &&= \& // \& < \& <<= \& <=> \& == \& =~ \& > \& >>= \& ? \& and \& cmp \& eq \& gt \& lt \& ne \& not \& or \& xor \& || \& ||= \& ~~ .Ve .PP You can supply your own list by setting: \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::LOGIC_OPERATORS\fI\fR before creating a new object. .PP \fILogic keywords:\fR .IX Subsection "Logic keywords:" .PP \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::DEFAULT_LOGIC_KEYWORDS\fI\fR .PP .Vb 10 \& else \& elsif \& for \& foreach \& goto \& grep \& if \& last \& map \& next \& unless \& until \& while .Ve .PP You can supply your own list by setting: \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::LOGIC_KEYWORDS\fI\fR before creating a new object. .PP \fIMethod modifiers:\fR .IX Subsection "Method modifiers:" .PP \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::DEFAULT_METHOD_MODIFIERS\fI\fR .PP .Vb 3 \& before \& after \& around .Ve .PP You can supply your own list by setting: \&\fI\f(CI@Perl::Metrics::Simple::Analysis::File::METHOD_MODIFIERS\fI\fR before creating a new object. .PP \fIExamples of Complexity\fR .IX Subsection "Examples of Complexity" .PP Here are a couple of examples of how we count complexity: .PP Example of complexity count of 1: .PP .Vb 3 \& use Foo; \& print "Hello world.\en"; \& exit; .Ve .PP Example of complexity count of 2: .PP .Vb 3 \& if ( $a ) { # The "if" adds 1. \& # do something \& } .Ve .PP Example of complexity count of 6: .PP .Vb 10 \& sub foo { # 1: for non\-empty code \& if ( @list ) { # 1: "if" \& foreach my $x ( @list ) { # 1: "foreach" \& if ( ! $x ) { # 2: 1 for "if" and 1 for "!" \& do_something($x); \& } \& else { # 1 for "else" \& do_something_else($x); \& } \& } \& } \& return; \& } .Ve .SS "packages" .IX Subsection "packages" Arrayref of unique packages found in the file. .SS "path" .IX Subsection "path" Either the path to the file, or a scalar ref if that was supplied instaed of a path. .SS "subs" .IX Subsection "subs" Count of subroutines found. .SH "STATIC PACKAGE SUBROUTINES" .IX Header "STATIC PACKAGE SUBROUTINES" Utility subs used internally, but no harm in exposing them for now. .SS "hashify" .IX Subsection "hashify" .Vb 1 \& %hash = Perl::Metrics::Simple::Analysis::File::hashify(@list); .Ve .PP Takes an array and returns a hash using the array values as the keys and with the values all set to 1. .SS "is_hash_key" .IX Subsection "is_hash_key" .Vb 1 \& $boolean = Perl::Metrics::Simple::Analysis::File::is_hash_key($ppi_element); .Ve .PP Takes a \fBPPI::Element\fR and returns true if the element is a hash key, for example \f(CW\*(C`foo\*(C'\fR and \f(CW\*(C`bar\*(C'\fR are hash keys in the following: .PP .Vb 1 \& { foo => 123, bar => $a } .Ve .PP Copied and somehwat simplified from http://search.cpan.org/src/THALJEF/Perl\-Critic\-0.19/lib/Perl/Critic/Utils.pm See Perl::Critic::Utils. .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" None reported yet ;\-) .SH "DEPENDENCIES" .IX Header "DEPENDENCIES" .IP "Readonly" 4 .IX Item "Readonly" .PD 0 .IP "Perl::Metrics::Simple::Analysis" 4 .IX Item "Perl::Metrics::Simple::Analysis" .PD .SH "SUPPORT" .IX Header "SUPPORT" Via \s-1CPAN:\s0 .SS "Disussion Forum" .IX Subsection "Disussion Forum" http://www.cpanforum.com/dist/Perl\-Metrics\-Simple .SS "Bug Reports" .IX Subsection "Bug Reports" http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl\-Metrics\-Simple .SH "AUTHOR" .IX Header "AUTHOR" .Vb 5 \& Matisse Enzer \& CPAN ID: MATISSE \& Eigenstate Consulting, LLC \& matisse@eigenstate.net \& http://www.eigenstate.net/ .Ve .SH "LICENSE AND COPYRIGHT" .IX Header "LICENSE AND COPYRIGHT" Copyright (c) 2006\-2009 by Eigenstate Consulting, \s-1LLC.\s0 .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP The full text of the license can be found in the \&\s-1LICENSE\s0 file included with this module.