Suggest cause of error requiring .pm file.
authorPaul Johnson <paul@pjcj.net>
Wed, 26 Sep 2012 00:44:45 +0000 (02:44 +0200)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 30 Sep 2012 07:01:27 +0000 (00:01 -0700)
Following on from a recent thread I've put together a patch to expand
the error message when a module can't be loaded. With this patch,
instead of:

Can't locate Stuff/Of/Dreams.pm in @INC (@INC contains: ...)

You get:

Can't locate Stuff/Of/Dreams.pm in @INC (you may need to install the Stuff::Of::Dreams module) (@INC contains: ...)

[The committer tweaked the error message,
 based on a suggestion by Tony Cook.  See
 <https://rt.perl.org/rt3/Ticket/Display.html?id=115048#txn-1157750>.]

cpan/parent/t/parent.t
pp_ctl.c
t/op/require_errors.t

index 401fe39..6ee4494 100644 (file)
@@ -58,10 +58,10 @@ is( $Eval2::VERSION, '1.02' );
 
 
 eval q{use parent 'reallyReAlLyNotexists'};
-like( $@, q{/^Can't locate reallyReAlLyNotexists.pm in \@INC \(\@INC contains:/}, 'baseclass that does not exist');
+like( $@, q{/^Can't locate reallyReAlLyNotexists.pm in \@INC \(you may need to install the reallyReAlLyNotexists module\) \(\@INC contains:/}, 'baseclass that does not exist');
 
 eval q{use parent 'reallyReAlLyNotexists'};
-like( $@, q{/^Can't locate reallyReAlLyNotexists.pm in \@INC \(\@INC contains:/}, '  still failing on 2nd load');
+like( $@, q{/^Can't locate reallyReAlLyNotexists.pm in \@INC \(you may need to install the reallyReAlLyNotexists module\) \(\@INC contains:/}, '  still failing on 2nd load');
 {
     my $warning;
     local $SIG{__WARN__} = sub { $warning = shift };
index 3faa9b0..19c2417 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3932,22 +3932,36 @@ PP(pp_require)
                if (namesv) {                   /* did we lookup @INC? */
                    AV * const ar = GvAVn(PL_incgv);
                    I32 i;
+                   SV *const msg = newSVpv("", 0);
                    SV *const inc = newSVpvs_flags("", SVs_TEMP);
                    for (i = 0; i <= AvFILL(ar); i++) {
                        sv_catpvs(inc, " ");
                        sv_catsv(inc, *av_fetch(ar, i, TRUE));
                    }
+                   if (len >= 4 && memEQ(name + len - 3, ".pm", 4)) {
+                       const char *c, *e = name + len - 3;
+                       sv_catpv(msg, " (you may need to install the ");
+                       for (c = name; c < e; c++) {
+                           if (*c == '/') {
+                               sv_catpvn(msg, "::", 2);
+                           }
+                           else {
+                               sv_catpvn(msg, c, 1);
+                           }
+                       }
+                       sv_catpv(msg, " module)");
+                   }
+                   else if (len >= 2 && memEQ(name + len - 2, ".h", 3)) {
+                       sv_catpv(msg, " (change .h to .ph maybe?) (did you run h2ph?)");
+                   }
+                   else if (len >= 3 && memEQ(name + len - 3, ".ph", 4)) {
+                       sv_catpv(msg, " (did you run h2ph?)");
+                   }
 
                    /* diag_listed_as: Can't locate %s */
                    DIE(aTHX_
-                       "Can't locate %s in @INC%s%s (@INC contains:%" SVf ")",
-                       name,
-                       (len >= 2 && memEQ(name + len - 2, ".h", 3)
-                        ? " (change .h to .ph maybe?) (did you run h2ph?)" : ""),
-                       (len >= 3 && memEQ(name + len - 3, ".ph", 4)
-                        ? " (did you run h2ph?)" : ""),
-                       inc
-                       );
+                       "Can't locate %s in @INC%" SVf " (@INC contains:%" SVf ")",
+                       name, msg, inc);
                }
            }
            DIE(aTHX_ "Can't locate %s", name);
index 1f243a6..c60bc7d 100644 (file)
@@ -27,7 +27,7 @@ for my $file ($nonfile, ' ') {
 
 eval "require $nonfile";
 
-like $@, qr/^Can't locate $nonfile\.pm in \@INC \(\@INC contains: @INC\) at/,
+like $@, qr/^Can't locate $nonfile\.pm in \@INC \(you may need to install the $nonfile module\) \(\@INC contains: @INC\) at/,
     "correct error message for require $nonfile";
 
 eval {