File Coverage

blib/lib/Devel/PerlySense/Project.pm
Criterion Covered Total %
statement 169 237 71.3
branch 29 64 45.3
condition 11 20 55.0
subroutine 33 38 86.8
pod 17 17 100.0
total 259 376 68.8


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Devel::PerlySense::Project - A Project root
4              
5             =head1 SYNOPSIS
6              
7              
8              
9              
10             =head1 DESCRIPTION
11              
12             A Project describes the root directory of a source tree.
13              
14             A Project has configuration settings.
15              
16             =cut
17              
18              
19              
20              
21              
22 68     68   2958 use strict;
  68         78  
  68         1559  
23 68     68   287 use warnings;
  68         67  
  68         2327  
24 68     68   1901 use utf8;
  68         92  
  68         2550  
25              
26             package Devel::PerlySense::Project;
27             $Devel::PerlySense::Project::VERSION = '0.0218';
28              
29              
30 68     68   3217 use Spiffy -Base;
  68         8302  
  68         301  
31 68     68   135585 use Carp;
  68     68   81  
  68     68   1060  
  68         191  
  68         71  
  68         1261  
  68         193  
  68         69  
  68         2755  
32 68     68   213 use Data::Dumper;
  68         67  
  68         1867  
33 68     68   207 use File::Basename;
  68         68  
  68         2312  
34 68     68   881 use Path::Class;
  68         52876  
  68         2095  
35 68     68   28452 use File::Slurp;
  68         462721  
  68         3835  
36 68     68   27601 use File::chdir;
  68         84538  
  68         5244  
37 68     68   2066 use File::Find::Rule;
  68         21651  
  68         567  
38 68     68   34538 use Perl::Critic 1.105;
  68         40890690  
  68         3233  
39 68     68   504 use List::MoreUtils qw/ uniq /;
  68         93  
  68         599  
40              
41 68     68   25511 use Devel::PerlySense;
  68         100  
  68         676  
42 68     68   15787 use Devel::PerlySense::Util;
  68         96  
  68         3684  
43 68     68   277 use Devel::PerlySense::Util::Log;
  68         88  
  68         2518  
44 68     68   24708 use Devel::PerlySense::Config::Project::Default;
  68         124  
  68         407  
45              
46              
47              
48              
49              
50             =head1 PROPERTIES
51              
52             =head2 dirProject
53              
54             The effective project root dir.
55              
56             Readonly.
57              
58             =cut
59 1995     1995 1 7771 sub dirProject {
60             return
61 1995   66     27386 $self->dirProjectExplicitDir ||
62             $self->dirProjectImplicitUse ||
63             $self->dirProjectImplicitDir;
64             }
65              
66              
67              
68              
69              
70             =head2 dirProjectExplicitDir
71              
72             If known, the root dir made explicit by the existence of a project
73             directory and config, else ""
74              
75             Default: ""
76              
77             =cut
78             field "dirProjectExplicitDir" => "";
79              
80              
81              
82              
83              
84             =head2 dirProjectImplicitUse
85              
86             If known, the root dir indicated by a found used module, else "".
87              
88             Default: ""
89              
90             =cut
91             field "dirProjectImplicitUse" => "";
92              
93              
94              
95              
96              
97             =head2 dirProjectImplicitDir
98              
99             If known, the root dir indicated by the presence of "lib" or "t", else "".
100              
101             Default: ""
102              
103             =cut
104             field "dirProjectImplicitDir" => "";
105              
106              
107              
108              
109              
110             =head2 oConfig
111              
112             A Config::Project object with the current Project Config. This gets
113             loaded if there is a config file available when the Project is
114             identified.
115              
116             Default: An Config::Project::Default object
117              
118             =cut
119             field "oConfig" => Devel::PerlySense::Config::Project::Default->new();
120              
121              
122              
123              
124              
125             =head2 rhConfig
126              
127             The actual hashref with config values.
128              
129             Readonly (that includes the entire data structure).
130              
131             =cut
132 1366     1366 1 7408 sub rhConfig {
133 1366         18145 return $self->oConfig->rhConfig;
134             }
135              
136              
137              
138              
139              
140             =head2 oPerlySense
141              
142             Devel::PerlySense object.
143              
144             =cut
145             field "oPerlySense" => undef;
146              
147              
148              
149              
150              
151             =head2 nameVcs
152              
153             The name of the Version Control system for the project.
154              
155             Readonly. Currently supported:
156              
157             git
158             svn
159             none
160              
161             In that order, so that if there's a Git repo on top of a SVN repo, git
162             is found.
163              
164             =cut
165 1     1 1 9 sub nameVcs {
166              
167             #Git
168 1 50       14 $self->oPerlySense->dirFindLookingAround(
169             ".git",
170             $self->dirProject,
171             ["."],
172             ) and return("git");
173              
174             #Subversion
175 1 50       4 -d dir($self->dirProject, ".svn") and return("svn");
176              
177 1         115 return("none");
178             }
179              
180              
181              
182              
183              
184             =head1 CLASS METHODS
185              
186             =head2 newFromLocation(file => $file, dir => $dir, oPerlySense => $oPs)
187              
188             Create new Project given either $file, or $dir.
189              
190             First, search for an explicit project root directory, then try to find
191             any modules used in $file (if passed), then try to find any "lib" or
192             "t" directory upwards of $file or $dir.
193              
194             $file takes precedence over $dir if both are specified.
195              
196             If none if this works out, no Project can be created and undef is
197             returned.
198              
199             Return the new object, or undef if no project could be found.
200              
201             =cut
202             sub newFromLocation(@) {
203 61     61 1 2555 my $pkg = shift;
204 61         237 my ($oPerlySense) = Devel::PerlySense::Util::aNamedArg(["oPerlySense"], @_);
205 61         150 my %p = @_;
206 61         126 my $file = $p{file};
207 61         107 my $dir = $p{dir};
208 61 100       677 $file and $dir = dirname($file);
209 61 50       465 $dir and $dir = dir($dir)->absolute;
210              
211 61         11565 my $oProject;
212              
213 61 100 66     193 $dir and $oProject = $pkg->newFindExplicit(
214             dir => $dir,
215             oPerlySense => $oPerlySense,
216             ) and return $oProject;
217              
218              
219             #If file, look for the dir from where any package in the file can
220             #be used
221 53 100 66     291 if($file and my $oDocument = $oPerlySense->oDocumentParseFile($file)) {
222 5         24 for my $package ($oDocument->aNamePackage) {
223 2         66 my $filePackage = $oPerlySense->fileFromModule($package);
224 2         346 my $dirFound = $oPerlySense->dirFindLookingAround($filePackage, $dir);
225              
226 2 50       67 if($dirFound) {
227 2         6 my $dirProject = dir($dirFound)->parent . ""; ###TODO: if lib or bin
228 2         176 return $pkg->new(
229             oPerlySense => $oPerlySense,
230             dirProjectImplicitUse => $dirProject,
231             );
232             }
233             }
234             }
235              
236             #If dir, look for dirs
237 51 50       192 if($dir) {
238 51   33     373 my $dirFound =
239             $oPerlySense->fileFindLookingAround("lib", $dir) ||
240             $oPerlySense->fileFindLookingAround("t", $dir);
241              
242 51 50       5117 if($dirFound) {
243 51         150 my $dirProject = dir($dirFound)->parent . ""; ###TODO: if lib or bin
244              
245             #Special case the Unix style root dir. It's never a
246             #Project dir, but if often contains a lib dir and so will
247             #get identified as a Project.
248             #
249             #If it _is_ a root dir, this can be overriden with an
250             #explicit .PerlySenseProject dir.
251             #
252             #On Windows, the root looks like X:\, and it's not
253             #entirely unlikely that a secondary drive or a SUBST drive
254             #letter contains the project root.
255 51 100       3833 $dirProject eq "/" and return undef;
256              
257 49         831 return $pkg->new(
258             oPerlySense => $oPerlySense,
259             dirProjectImplicitDir => $dirProject,
260             );
261             }
262             }
263              
264 0         0 return(undef);
265             }
266              
267              
268              
269              
270              
271             =head2 newFindExplicit(dir => $dir, oPerlySense => $oPs)
272              
273             Create new Project if there is an explicit .PerlySenseProject
274             directory in the path above $dir.
275              
276             Return the new object, or undef if no project could be found.
277              
278             =cut
279             sub newFindExplicit(@) {
280 56     56 1 512 my $pkg = shift;
281 56         234 my ($oPerlySense, $dir) = Devel::PerlySense::Util::aNamedArg(["oPerlySense", "dir"], @_);
282              
283 56 100       324 if(my $dirProject = $oPerlySense->dirFindLookingAround(
284             ".PerlySenseProject",
285             $dir,
286             ["."],
287             )) {
288 8         280 return $pkg->new(
289             oPerlySense => $oPerlySense,
290             dirProjectExplicitDir => $dirProject,
291             oConfig => Devel::PerlySense::Config::Project->new(dirRoot => $dirProject),
292             );
293             }
294              
295 48         400 return undef;
296             }
297              
298              
299              
300              
301              
302             =head1 MEHTODS
303              
304             =head2 rhRunFile(file => $fileSource, [rhConfigType = DEDUCED_FROM_FILE], [ keyConfigCommand = "command" ])
305              
306             Like rhRunFile0, but with what => "run".
307              
308             =cut
309 4     4 1 14 sub rhRunFile {
310 4         12 my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
311 4         9 my %p = @_;
312 4         10 return( $self->rhRunFile0(%p, what => "run") );
313             }
314              
315              
316              
317              
318              
319             =head2 rhDebugFile(file => $fileSource, [rhConfigType = DEDUCED_FROM_FILE], [ keyConfigCommand = "command" ])
320              
321             Like rhRunFile0, but with what => "debug".
322              
323             =cut
324             ### XXX refactor, DRY with rhRunFile
325 1     1 1 5 sub rhDebugFile {
326 1         4 my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
327 1         2 my %p = @_;
328 1         6 return( $self->rhRunFile0(%p, what => "debug") );
329             }
330              
331              
332              
333              
334              
335             =head2 rhRunFile0(file => $fileSource, what => "run" | "debug", [rhConfigType = DEDUCED_FROM_FILE], [ keyConfigCommand = "command" ])
336              
337             Figure out what type of source file $fileSource is, and how it should
338             be run/debugged.
339              
340             The settings in the global config->{$what_file} is used to determine
341             the details.
342              
343             The command to use is taken from
344             config->{$what_file}->{$keyConfigCommand}, if that is specified,
345             otherwise for "command".
346              
347             Return hash ref with (keys: "dir_$what_from", "command_$what",
348             "type_source_file"), or die on errors (like if no Project could be
349             found).
350              
351             dir_$what_from is an absolute directory name which should be the cwd
352             when command_$what is executed.
353              
354             type_source_file is something like "Test", "Module".
355              
356             =cut
357 5     5 1 6 sub rhRunFile0 {
358 5         12 my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
359 5         8 my %p = @_;
360 5         7 my $rhConfigType = $p{rhConfigType};
361 5         6 my $what = $p{what};
362 5   100     17 my $keyConfigCommand = $p{keyConfigCommand} || "command";
363              
364 5         13 $file = file($file)->absolute;
365 5   33     771 $rhConfigType ||= $self->rhConfigTypeForFile(
366             file => $file,
367             keyConfig => "${what}_file",
368             );
369              
370 5         140 my $dirProject = dir($self->dirProject)->absolute;
371             my %hTypeDirRunFrom = (
372 3     3   3 source_root_directory => sub { $dirProject },
373 2     2   6 file_directory => sub { $file->dir },
374 5         359 );
375 5         11 my $typeRunFrom = $rhConfigType->{"${what}_from"};
376 5 50       16 my $rsDirRunFrom = $hTypeDirRunFrom{$typeRunFrom} or die("Invalid ${what}_from value ($typeRunFrom)\n" . Dumper($rhConfigType) . "Allowed values: (" . join(", ", (sort keys %hTypeDirRunFrom)) . ")\n");
377 5         8 my $dirRunFrom = $rsDirRunFrom->();
378              
379 5         15 my @aDirIncProject = $self->aDirIncProject(dirRelativeTo => $dirRunFrom);
380 5         9 my $optionInc = join(" ", map { qq|"-I$_"| } @aDirIncProject);
  19         33  
381              
382 5         20 my $fileSource = $file->relative($dirRunFrom);
383             my $command
384             = $rhConfigType->{ $keyConfigCommand }
385             || $rhConfigType->{command}
386 5 50 33     592 or die("Could not find a config value for which 'command' to run\n");
387 5         13 my $commandRun = textRenderTemplate(
388             $command,
389             {
390             INC => $optionInc,
391             SOURCE_FILE => $fileSource . "",
392             },
393             );
394              
395             my $rhConfigRun = {
396             "dir_${what}_from" => $dirRunFrom . "",
397             "command_${what}" => $commandRun,
398             type_source_file => $rhConfigType->{moniker},
399 5         23 };
400 5         130 return($rhConfigRun);
401             }
402              
403              
404              
405              
406              
407             =head2 rhConfigTypeForFile(file => $fileSource, keyConfig => CONFIG_KEY)
408              
409             Return the config type hash ref (keys: command, moniker) from the ones
410             available in the config. Match the $fileSource name against each rex
411             in the config.
412              
413             Die if no configType could be identified.
414              
415             =cut
416 19     19 1 891 sub rhConfigTypeForFile {
417 19         56 my ($file, $keyConfig) = Devel::PerlySense::Util::aNamedArg(["file", "keyConfig"], @_);
418              
419 19         335 my $rhConfig = $self->oPerlySense->rhConfig;
420 19         351 for my $rhConfigType (@{ $rhConfig->{ $keyConfig } }) {
  19         39  
421             my $rex = $rhConfigType->{rex}
422 33 100       66 or die("Missing rex key in config chunk: " . Dumper($rhConfigType));
423              
424 31 100       25 eval { $file =~ /$rex/ } and return $rhConfigType;
  31         325  
425 18 100       128 $@ and die("Invalid rex value in config chunk.\nError: $@\n" . Dumper($rhConfigType));
426             }
427              
428 2         15 die("No run_perl rex matched the file ($file). Please check your config\n");
429             }
430              
431              
432              
433              
434              
435             =head2 aDirIncProject(dirRelativeTo => $dirRelativeTo)
436              
437             Return array with dir objects which are the inc_dir directories in the
438             config, plus the usual inc directories. They are all relative to
439             $dirRelativeTo.
440              
441             =cut
442 771     771 1 30373 sub aDirIncProject {
443 771         2439 my ($dirRelativeTo) = Devel::PerlySense::Util::aNamedArg(["dirRelativeTo"], @_);
444              
445 771         1781 my $dirProject = dir($self->dirProject)->absolute;
446 771         60769 my $dirProjectRelativeTo = $dirProject->relative( $dirRelativeTo );
447              
448             ###TODO: extract method for the inc_dir config entry aIncDirConfig
449 771 50       63125 my @aDirIncProject = @{ $self->oPerlySense->rhConfig->{project}->{inc_dir} || [] };
  771         13797  
450 771         21916 my @aDirInc = (@aDirIncProject, ".", "lib");
451              
452             my @aDirIncRelative =
453 771         1119 map { dir($dirProjectRelativeTo, $_) . "" }
  1551         33069  
454             @aDirInc;
455              
456 771         25405 return @aDirIncRelative;
457             }
458              
459              
460              
461              
462              
463             =head2 aDirIncAbsolute()
464              
465             Return array with absolute dir objects which are the inc_dir
466             directories in the config, plus the usual inc directories.
467              
468             =cut
469 544     544 1 3048 sub aDirIncAbsolute {
470 544         1269 my $dirProject = dir($self->dirProject)->absolute;
471              
472             ###TODO: extract method for the inc_dir config entry aIncDirConfig
473             my @aDirIncProject = @{
474 544 50       45081 $self->oPerlySense->rhConfig->{project}->{inc_dir} || []
  544         8549  
475             };
476 544         11375 my @aDirInc = (@aDirIncProject, ".", "lib");
477              
478             my @aDirIncAbsolute =
479 544         877 map { dir($dirProject, $_)->absolute . "" }
  1091         29867  
480             @aDirInc;
481 544         33897 return @aDirIncAbsolute;
482             }
483              
484              
485              
486              
487              
488             =head2 isFileInProject(file => $file)
489              
490             Return true if $file is within the project root, or in any of the INC
491             directories, else false. Die on errors.
492              
493             Test logically/structurally, not whether the file actually exists.
494              
495             =cut
496 7     7 1 806 sub isFileInProject {
497 7         33 my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
498              
499             my @aDirInc =
500 15         833 map { dir($self->dirProject, $_) }
501 7 50       12 @{ $self->oPerlySense->rhConfig->{project}->{inc_dir} || [] };
  7         175  
502             my @aDirSourceAbsolute =
503 7         353 map { dir($_)->absolute }
  22         1143  
504             ($self->dirProject, @aDirInc);
505              
506             ###TODO: Comment out debug statements when that failing test in t/PerlySense-Project-file-in-project.t is fixed
507 7         576 debug("\nTESTING WHETHER FILE\n($file) IS IN PROJECT\n(" . $self->dirProject . "),\ni.e.\n(" . join(")\n(", @aDirSourceAbsolute) . ")\n");
508 7         26 my @aDirProjectRegex = map { qr/^ \Q$_\E /x } @aDirSourceAbsolute;
  22         707  
509              
510 7         354 my $dirFileAbsolute = dir( filePathNormalize( file($file)->absolute->dir ) );
511 7         1158 debug("DIR ABSOLUTE ($dirFileAbsolute)\n");
512              
513 7         18 for my $dirProject (map { dir(filePathNormalize($_)) } @aDirSourceAbsolute) {
  22         2813  
514 16         3898 debug("Checking whether\n($dirFileAbsolute) is within\n($dirProject)\n");
515 16 100       78 $dirProject->subsumes($dirFileAbsolute) and debug("Found it"), return 1;
516             }
517              
518 3         822 debug("FILE ($file) is NOT in the Project (" . $self->dirProject . ")\n");
519 3         56 return 0;
520             }
521              
522              
523              
524              
525              
526             =head2 flymakeFile(file => $fileSource)
527              
528             Do a flymake run with $fileSource according to the flymake config and
529             output the result to STDOUT and STDERR.
530              
531             Return 1 or die on errors (but that will look like the result of a
532             failed flymake run).
533              
534             =cut
535              
536 0     0 1   sub flymakeFile {
537 0           my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
538              
539 0 0         if($self->oPerlySense->rhConfig->{external}{editor}{emacs}{flymake}{syntax}) {
540 0           my $rhConfigRun = $self->rhRunFile(
541             file => $file,
542             rhConfigType => {
543             command => q{perl -c ${INC} "${SOURCE_FILE}" 2>&1 | perl -ne " /Subroutine [\\w:]+ redefined at/ or print"},
544             moniker => "Flymake",
545             rex => "",
546             run_from => "file_directory",
547             },
548             );
549              
550 0           local $CWD = $rhConfigRun->{dir_run_from};
551 0           system( $rhConfigRun->{command_run} );
552             }
553              
554 0 0         if($self->oPerlySense->rhConfig->{external}{editor}{emacs}{flymake}{critic}) {
555             ###TODO: don't run if syntax errors found
556              
557 0           my $fileConfigCritic = file(
558             dir($self->dirProject)->absolute, ".PerlySenseProject", ".perlcritic",
559             );
560              
561 0           my @aOption = (-profile => $fileConfigCritic . "");
562 0 0         -e $fileConfigCritic or @aOption = ();
563              
564 0           my $oCritic = Perl::Critic->new(@aOption);
565              
566 0           my @aViolation = $oCritic->critique($file);
567              
568 0           Perl::Critic::Violation::set_format( "%m near '%r' (%e, %p) at %f line %l.\n" );
569 0           for my $violation (@aViolation) {
570 0           print STDERR "Warning: $violation";
571             }
572             }
573              
574 0           return 1;
575             }
576              
577              
578              
579              
580              
581             =head2 rhSubCovered(file => $fileSource)
582              
583             Do a "covered subs" call with $fileSource.
584              
585             Die if Devel::CoverX::Covered isn't installed.
586              
587             Return hash ref with (keys: sub name; values: quality)), or an empty
588             hash ref if no coverage info was found for $fileSource.
589              
590             Any subs with the same name will have their qualities combined.
591              
592             =cut
593 0     0 1   sub rhSubCovered {
594 0           my ($file) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
595              
596 0           local $CWD = $self->dirProject;
597              
598 0           eval {
599 0           require Devel::CoverX::Covered;
600 0           require Devel::CoverX::Covered::Db;
601             };
602 0 0         $@ and die("Devel::CoverX::Covered isn't installed\n");
603              
604             ###TODO: use dir specified in config and/or on command line
605 0           local $CWD = $self->dirProject . "";
606              
607             ###TODO: Change Devel::CoverX::Covered to expose this dir properly
608             ###and get it from there.
609 0           my $dirDb = "covered";
610 0 0         -d $dirDb or return( {} );
611              
612 0           my $db = Devel::CoverX::Covered::Db->new();
613 0           my $fileRelative = file($file)->relative( $self->dirProject );
614 0           my %hSubQuality;
615 0           for my $raSubQuality ( $db->covered_subs($fileRelative) ) {
616 0           my ($sub, $quality) = @$raSubQuality;
617 0           $hSubQuality{$sub} += $quality;
618             }
619              
620 0           return(\%hSubQuality);
621             }
622              
623              
624              
625              
626              
627             =head2 raFileTestOther(file => $fileSource, [sub => $sub])
628              
629             Return array ref with file names of files related to $file and
630             possibly $sub, i.e. the "other" files related $file.
631              
632             If $file is a source file, return test files, and vice verca.
633              
634             $sub is only ever active when $fileSource is a source file.
635              
636             Die if Devel::CoverX::Covered isn't installed.
637              
638             =cut
639 0     0 1   sub raFileTestOther {
640 0           my ($file, $sub) = Devel::PerlySense::Util::aNamedArg(["file", "sub"], @_);
641              
642 0           eval {
643 0           require Devel::CoverX::Covered;
644 0           require Devel::CoverX::Covered::Db;
645             };
646 0 0         $@ and die("Devel::CoverX::Covered isn't installed\n");
647              
648             ###TODO: verify there is a cover_db database present
649              
650 0           local $CWD = $self->dirProject . "";
651              
652 0           my $db = Devel::CoverX::Covered::Db->new();
653              
654 0           my $method = "source_files_covered_by"; # Default to test file
655 0 0         $file =~ m|\.pm$| and $method = "test_files_covering"; # If a module, it's source
656 0 0         $file =~ m|/t/| and $method = "source_files_covered_by"; # If it's in /t/, it's a test
657 0 0         $file =~ m|\.t$| and $method = "source_files_covered_by"; # If it's a .t file, it's a test
658             ### TODO: config with list of lib dirs and list of test dirs
659 0           debug("raFileTestOther with method ($method)");
660              
661 0           my $fileRelative = file($file)->relative( $self->dirProject );
662 0           my $raFileTestOther = [ $db->$method($fileRelative, $sub) ];
663              
664 0           return($raFileTestOther);
665             }
666              
667              
668              
669              
670              
671             =head2 raFileProjectOther(file => $fileSource, [sub => $sub])
672              
673             Return array ref with file names of files corresponding to $file.
674              
675             Die if there is no config file.
676              
677             =cut
678 0     0 1   sub raFileProjectOther {
679 0           my ($file, $sub) = Devel::PerlySense::Util::aNamedArg(["file"], @_);
680              
681 0           eval {
682 0           require File::Corresponding;
683 0           require File::Corresponding::Config::Find;
684             };
685 0 0         $@ and die("File::Corresponding isn't installed\n");
686              
687              
688             # Work from the project dir, so the rest of the paths will just work out
689 0           local $CWD = $self->dirProject . "";
690              
691 0 0         my $fileConfig = File::Corresponding::Config::Find->new(
692             preferred_dirs => [ dir(".PerlySenseProject"), dir(".") ],
693             )->user_config(".corresponding_file")
694             or die("Could not find a '.corresponding_file' config file in either 1) the .PerlySenseProject; b) the current directory; c) your home directory. See perldoc File::Corresponding for information on how to create one.\n");
695              
696 0           my $corresponding = File::Corresponding->new();
697 0 0         eval { $corresponding->load_config_file($fileConfig) }
  0            
698             or die("Could not read config file ($fileConfig): $@\n");
699              
700 0           my $fileRelative = file($file)->relative( $self->dirProject );
701             my @aFileProjectOther = uniq(
702 0           map { $_->file }
703 0           @{$corresponding->corresponding( $fileRelative )}
  0            
704             );
705              
706 0           return(\@aFileProjectOther);
707             }
708              
709              
710              
711              
712              
713             =head2 aFileSourceCode()
714              
715             Return array with file names with perl source code in the project.
716              
717             # TODO: also look inside files without extension and check for perlyness
718              
719             =cut
720 0     0 1   sub aFileSourceCode {
721 0           return File::Find::Rule
722             ->name("*.pm", "*.pl")
723             ->in( $self->aDirIncAbsolute );
724             }
725              
726              
727              
728              
729              
730              
731             1;
732              
733              
734              
735              
736              
737             __END__
738              
739             =encoding utf8
740              
741             =head1 AUTHOR
742              
743             Johan Lindstrom, C<< <johanl@cpan.org> >>
744              
745             =head1 BUGS
746              
747             Please report any bugs or feature requests to
748             C<bug-devel-perlysense@rt.cpan.org>, or through the web interface at
749             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Devel-PerlySense>.
750             I will be notified, and then you'll automatically be notified of progress on
751             your bug as I make changes.
752              
753             =head1 ACKNOWLEDGEMENTS
754              
755             =head1 COPYRIGHT & LICENSE
756              
757             Copyright 2005 Johan Lindstrom, All Rights Reserved.
758              
759             This program is free software; you can redistribute it and/or modify it
760             under the same terms as Perl itself.
761              
762             =cut