f78fd9b217a1a4edc4619dbf007de7536637b84b
[sepia.git] / lib / Sepia / Xref.pm
blobf78fd9b217a1a4edc4619dbf007de7536637b84b
1 package Sepia::Xref;
3 =head1 NAME
5 Sepia::Xref - Generates cross reference database for use by Perl programs.
7 =head1 SYNOPSIS
9 use Sepia::Xref qw(rebuild defs callers);
11 rebuild;
12 for (defs 'foo') {
13 printf "%s:%d: sub %s\::foo() defined\n", @{$_}[0..2];
16 for (callers 'foo') {
17 printf "%s:%d: sub foo() called by %s\::%s().\n", @{$_}[0..3];
20 =head1 DESCRIPTION
22 C<Sepia::Xref> is intended as a programmatic interface to the
23 information supplied by L<B::Xref>. It is intended to be a component
24 for interactive Perl development, with other packages providing a
25 friendly interface to the raw information it extracts. C<B::Xref>
26 could be seen as an example of this sort of user-level tool, if it
27 weren't for the fact that this module was created later, and stole
28 most of its code.
30 =cut
32 # use Sepia '_apropos_re';
33 require Sepia;
34 BEGIN { *_apropos_re = *Sepia::_apropos_re; }
36 use strict;
37 use Config;
38 use Cwd 'abs_path';
39 use B qw(peekop class comppadlist main_start svref_2object walksymtable
40 OPpLVAL_INTRO SVf_POK OPpOUR_INTRO OPf_MOD OPpDEREF_HV OPpDEREF_AV
41 cstring);
42 # stupid warnings...
43 no warnings 'uninitialized';
45 =head2 Variables
47 =over
49 =item C<%call>
51 A map of subs to call locations and callers
53 =item C<%callby>
55 A map of subs to subs called.
57 =item C<%var_use>
59 A map of global/package variables to uses.
61 =item C<%var_def>
63 A map of global/package variables to definitions (usually empty, since
64 it only picks up local (...) declarations.
66 =back
68 =cut
70 our %call;
71 our %callby;
72 our %var_def;
73 our %var_use;
75 require Exporter;
76 our @ISA = 'Exporter';
77 my @most = qw(redefined forget rebuild callers callees
78 var_defs var_uses
79 var_apropos);
80 our @EXPORT_OK = (@most,
81 qw(xref_definitions xref_object xref_main
82 %call %callby %var_use %var_def));
84 our %EXPORT_TAGS =
85 (':all' => \@EXPORT_OK,
86 ':most' => \@most);
88 ######################################################################
89 ## Xref state variables:
91 sub UNKNOWN { ["?", "?", "?"] }
93 my @pad; # lexicals in current pad
94 # as ["(lexical)", type, name]
95 my @padval;
96 our %done; # keyed by $$op: set when each $op is done
97 my $top = UNKNOWN; # shadows top element of stack as
98 # [pack, type, name] (pack can be "(lexical)")
99 our $file; # shadows current filename
100 my $line; # shadows current line number
101 our $subname; # shadows current sub name
102 our @todo = (); # List of CVs that need processing
103 my $lastclass; # last bareword seen after entersub.
105 our $DEBUG = 0;
106 sub dprint {
107 my $type = shift;
108 my $res = "@_";
109 $res =~ s/%//g; # XXX: work around EPL's misuse of (message)
110 print STDERR "@_" if $DEBUG =~ /$type/;
113 my %code = (intro => "i", used => "",
114 subdef => "s", subused => "&",
115 formdef => "f", meth => "->");
117 =head2 Functions
119 =over 4
121 =item C<guess_module_file($pack, $ofile)>
123 XXX: it turns out that rooting around trying to figure out the file
124 ourselves is more reliable than what we grab from the op. Are we
125 doing this wrong?
127 =cut
129 sub guess_module_file {
130 my ($pack, $ofile) = @_;
131 my $file;
133 # XXX: is this why we get the bogus defs?
134 return undef if $ofile =~ /Exporter\.pm$/;
135 # Try for standard translation in %INC:
136 (my $fn = $pack) =~ s/::/\//g;
137 return unless $fn; # stupid warnings...
138 if (exists $INC{"$fn.pm"}) {
139 return $INC{"$fn.pm"};
142 # Try what they told us:
143 chomp $ofile;
144 return $ofile if -f $ofile;
146 # Try "parent" packages:
147 while ($fn =~ s|/?[^/]+$|| && !$file) {
148 $file ||= $INC{"$fn.pm"};
151 if ($file && $file !~ /^\//) {
152 $file = abs_path($file);
155 if (!$file || !-f $file) {
156 undef $file;
158 $file;
161 # XXX: should weed through the code below so it only generates decent
162 # package names, but this will fix it for now.
163 sub realpack {
164 my $p = shift;
165 if (!defined $p || $p eq '?' || $p eq '(method)') {
166 return undef;
167 } elsif ($p eq '') {
168 return 'main';
169 } else {
170 return $p;
174 # Turn a possibly-qualified name into a package and basename.
175 sub split_name {
176 local $_ = shift;
177 my ($p, $s);
178 if (/^(.*)::(.+)$/) {
179 ($p, $s) = ($1, $2);
180 } else {
181 ($p, $s) = ('main', $_);
183 undef $s if $s eq '?';
184 ($p, $s);
187 sub process {
188 my ($var, $event) = @_;
189 my ($pack, $type, $name) = @$var;
190 $pack = realpack($pack);
191 dprint 'loud', "Processing $event: @$var ($subname)";
192 if ($type eq "*") {
193 if ($event eq "used" || $event eq 'set') {
194 return;
195 } elsif ($event eq "subused") {
196 $type = "&";
197 } elsif ($event eq "meth") {
198 $type = '->';
201 $type =~ s/(.)\*$/$1/g;
202 $file = guess_module_file($pack, $file);
204 if (($type eq '&' || $type eq '->') && $subname ne '(definitions)') {
205 # Handle caller/callee relations
206 my ($spack, $sname) = split_name($subname);
208 $call{$name}{$pack}{$subname} = 1;
209 $callby{$sname}{$spack}{"$pack\::$name"} = 1;
210 } elsif ($type eq 's' || $subname eq '(definitions)') {
211 # definition
212 } elsif ($name !~ /^[\x00-\x1f^] | ^\d+$ | ^[\W_]$
213 | ^(?:ENV|INC|STD(?:IN|OUT|ERR)|SIG)$ /x
214 && realpack($pack)) {
215 # Variables, but ignore specials and lexicals
216 my ($spack, $sname) = split_name($subname);
217 if ($event eq 'intro') {
218 $var_def{$name}{$pack} =
219 { file => $file,
220 package => $spack,
221 line => $line,
222 sub => $sname,
224 } elsif ($event eq 'used' || $event eq 'set') {
225 push @{$var_use{$name}{$pack}},
226 { file => $file,
227 package => $spack,
228 line => $line,
229 sub => $sname,
230 assign => ($event eq 'set'),
232 } else {
233 dprint 'ignore', "Ignoring var event $event";
235 } else {
236 dprint 'ignore', "Ignoring $type event $event";
240 sub load_pad {
241 my $padlist = shift;
242 my ($namelistav, $vallistav, @namelist, $ix);
243 @pad = ();
244 @padval = ();
245 return if class($padlist) eq "SPECIAL";
246 ($namelistav,$vallistav) = $padlist->ARRAY;
247 @namelist = $namelistav->ARRAY;
248 for ($ix = 1; $ix < @namelist; $ix++) {
249 my $namesv = $namelist[$ix];
250 next if class($namesv) eq "SPECIAL";
251 my ($type, $name) = $namesv->PV =~ /^(.)([^\0]*)(\0.*)?$/;
252 $pad[$ix] = [undef, $type, $name];
254 if ($Config{useithreads}) {
255 my (@vallist);
256 @vallist = $vallistav->ARRAY;
257 for ($ix = 1; $ix < @vallist; $ix++) {
258 my $valsv = $vallist[$ix];
259 next unless class($valsv) eq "GV";
260 # these pad GVs don't have corresponding names, so same @pad
261 # array can be used without collisions
263 # XXX: for some reason, on 5.10 $valsv->STASH can be a
264 # B::SPECIAL, which doesn't have a name.
266 # XXX: this segfaults on 5.10 for some reason while
267 # traversing File::Find::contract_name from main
269 next if ref $valsv->STASH eq 'B::SPECIAL';
270 $pad[$ix] = [$valsv->STASH->NAME, "*", $valsv->NAME];
273 @padval = $vallistav->ARRAY;
276 sub xref {
277 my $start = shift;
278 my $op;
279 for ($op = $start; $$op; $op = $op->next) {
280 last if $done{$$op}++;
281 my $opname = $op->name;
282 if ($opname =~ /^(or|and|mapwhile|grepwhile|range|cond_expr)$/) {
283 xref($op->other);
284 } elsif ($opname eq "match" || $opname eq "subst") {
285 xref($op->pmreplstart);
286 } elsif ($opname eq "substcont") {
287 xref($op->other->pmreplstart);
288 $op = $op->other;
289 redo;
290 } elsif ($opname eq "enterloop") {
291 xref($op->redoop);
292 xref($op->nextop);
293 xref($op->lastop);
294 } elsif ($opname eq "subst") {
295 xref($op->pmreplstart);
296 } else {
297 no strict 'refs';
298 my $ppname = "pp_$opname";
299 &$ppname($op) if defined(&$ppname);
304 sub xref_cv {
305 my $cv = shift;
306 my $pack = $cv->GV->STASH->NAME;
307 local $subname = ($pack eq "main" ? "" : "$pack\::") . $cv->GV->NAME;
308 load_pad($cv->PADLIST);
309 xref($cv->START);
312 sub xref_object {
313 my $cvref = shift;
314 local (@todo, %done);
315 my $cv = svref_2object($cvref);
316 xref_cv($cv);
317 dprint 'todo', "todo = (@todo)";
318 my $gv = $cv->GV;
319 process([$gv->STASH->NAME, '&', $gv->NAME], 'subdef');
322 sub xref_main {
323 $subname = "(main)";
324 load_pad(comppadlist);
325 xref(main_start);
326 while (@todo) {
327 xref_cv(shift @todo);
331 sub pp_pushmark {
332 my $op = shift;
333 my ($class, $meth);
334 if (($class = $op->next)->name eq 'const') {
335 my $sv = $class->sv;
336 my $classname;
337 # constant could be in the pad (under useithreads)
338 if (class($sv) ne "SPECIAL" && $sv->FLAGS & SVf_POK) {
339 $classname = $sv->PV;
340 } else {
341 my $pv = $padval[$class->targ];
342 if (class($pv) =~ /^PV/ && class($sv) eq 'SPECIAL'
343 ## bareword flag -- should use this?
344 # && ($op->private & 64)
346 $classname = $pv->PV;
349 $lastclass = $classname;
353 sub pp_nextstate {
354 my $op = shift;
355 $file = $op->file;
356 die "pp_nextstate: $file" if $file =~ /::/;
357 $line = $op->line;
358 $top = UNKNOWN;
361 sub use_type($) {
362 my ($op) = @_;
363 if ($op->private & (OPpLVAL_INTRO | OPpOUR_INTRO)) {
364 'intro';
365 } elsif ($op->flags & OPf_MOD
366 && !($op->private & (OPpDEREF_HV | OPpDEREF_AV))) {
367 'set';
368 } else {
369 'used';
373 sub pp_padsv {
374 my $op = shift;
375 $top = $pad[$op->targ];
376 # process($top, $op->private & OPpLVAL_INTRO ? "intro" : "used");
379 sub pp_padav { pp_padsv(@_) }
380 sub pp_padhv { pp_padsv(@_) }
382 sub deref {
383 my ($op, $var, $as) = @_;
384 $var->[1] = $as . $var->[1];
385 process($var, use_type $op);
388 sub pp_rv2cv { deref(shift, $top, "&"); }
389 sub pp_rv2hv { deref(shift, $top, "%"); }
390 sub pp_rv2sv { deref(shift, $top, "\$"); }
391 sub pp_rv2av { deref(shift, $top, "\@"); }
392 sub pp_rv2gv { deref(shift, $top, "*"); }
394 sub pp_gvsv {
395 my $op = shift;
396 my $gv;
397 if ($Config{useithreads}) {
398 $top = $pad[$op->padix];
399 $top = UNKNOWN unless $top;
400 $top->[1] = '$';
402 else {
403 $gv = $op->gv;
404 $top = [$gv->STASH->NAME, '$', $gv->SAFENAME];
406 process($top, use_type $op);
409 sub pp_gv {
410 my $op = shift;
411 my $gv;
412 if ($Config{useithreads}) {
413 $top = $pad[$op->padix];
414 $top = UNKNOWN unless $top;
415 $top->[1] = '*';
417 else {
418 $gv = $op->gv;
419 $top = [$gv->STASH->NAME, "*", $gv->SAFENAME];
421 process($top, use_type $op);
424 sub pp_method {
425 my $op = shift;
426 $top = [$lastclass || "(method)", "->".$top->[1], $top->[2]];
427 dprint 'method', "pp_method($top->[1])";
428 undef $lastclass;
431 sub pp_method_named {
432 use Data::Dumper;
433 my $op = shift;
434 my $sv = $op->sv;
435 my $pviv = $padval[$op->targ];
436 if ($pviv && class($pviv) =~ /^PV/) {
437 my $name = $pviv->PV;
438 dprint 'method_named', $op->targ.": $name";
439 undef $top->[2] if $top->[2] eq '?';
440 $top = [$lastclass || "(method)", '->', $name];
441 undef $lastclass;
442 } else {
443 dprint 'method_named', "method_named: wtf: sizeof padval = ".@padval;
447 sub pp_entersub {
448 my $op = shift;
449 if ($top->[1] =~ /^(?:m$|->)/) {
450 dprint 'method', "call to (@$top) from $subname";
451 process($top, "meth");
452 } else {
453 process($top, "subused");
455 undef $lastclass;
456 $top = UNKNOWN;
460 # Stuff for cross referencing definitions of variables and subs
463 sub B::GV::xref {
464 my $gv = shift;
465 my $cv = $gv->CV;
466 $file = $gv->FILE;
467 # XXX: sometimes the "file" is a module. Why?
468 $line = $gv->LINE;
469 if ($$cv) {
470 #return if $done{$$cv}++;
471 process([$gv->STASH->NAME, "&", $gv->NAME], "subdef");
472 push(@todo, $cv);
474 my $form = $gv->FORM;
475 if ($$form) {
476 return if $done{$$form}++;
477 process([$gv->STASH->NAME, "", $gv->NAME], "formdef");
481 ## Exclude all pragmatic modules (lowercase first letter) and the
482 ## following problematic things, which tend to cause more harm than
483 ## good when they get xref'd:
484 my %exclude;
485 BEGIN {
486 undef $exclude{"$_\::"}
487 for qw(B O AutoLoader DynaLoader XSLoader Config DB VMS
488 FileHandle Exporter Carp PerlIO::Layer);
491 sub xref_exclude {
492 my $x = shift;
493 $x =~ /^[a-z]/ || exists $exclude{$x};
496 sub xref_definitions {
497 my ($pack, %exclude);
498 $subname = "(definitions)";
499 no strict qw(vars refs);
500 walksymtable(\%{"main::"}, "xref", sub { !xref_exclude($_[0]) });
503 =item C<rebuild()>
505 Rebuild the Xref database.
507 =cut
509 sub rebuild {
510 %call = (); %callby = ();
511 %var_def = (); %var_use = ();
512 local (@todo, %done);
513 xref_definitions;
514 xref_main;
518 sub unmention {
519 my ($h, $K, $V, $pack) = @_;
520 dprint 'unmention', "Unmentioning $K => $V";
521 while (my ($k, $v) = each %$h) {
522 while (my ($k2, $v2) = each %$v) {
523 if (ref $v2 eq 'ARRAY') {
524 $v->{$k2} = [grep {
525 $_->{$K} ne $V || !$pack || $pack ne $_->{package}
526 } @$v2];
527 delete $v->{$k2} unless @{$v->{$k2}};
528 } else {
529 delete $v->{$k2} if $k2 eq $V;
532 delete $h->{$k} unless keys %{$h->{$k}};
536 sub unmention_sub {
537 my ($h, $sub, $pack) = @_;
538 dprint 'unmention', "Unmentioning $pack\::$sub";
539 if ($pack) {
540 delete $h->{$sub}{$pack};
541 delete $h->{$sub} unless keys %{$h->{$sub}};
542 } else {
543 delete $h->{$sub};
547 =item C<forget($func [, $mod])>
549 Forget that C<$func> was defined.
551 =cut
553 sub forget {
554 my ($obj, $pack) = @_;
555 unmention_sub \%callby, @_;
556 unmention \%call, 'sub', @_;
557 unmention \%var_use, 'sub', @_;
558 unmention \%var_def, 'sub', @_;
561 =item C<redefined($func [, $pack])>
563 Recompute xref info for C<$func>, or C<$pack::$func> if C<$pack> given.
565 =cut
567 sub redefined {
568 forget @_;
570 no strict 'refs';
571 my ($sub, $pack) = @_;
572 $pack ||= 'main';
573 $sub = $pack eq 'main' ? $sub : "$pack\::$sub";
574 local $subname = '(definitions)';
575 xref_object \&$sub;
579 ######################################################################
580 # Apropos and definition-finding:
582 sub _ret_list
584 my ($h, $sub, $mod) = @_;
585 if ($sub =~ /^(.*)::([^:]+)$/) {
586 $sub = $2;
587 $mod = $1;
589 $h = $h->{$sub};
590 my @r;
591 if ($mod) {
592 @r = keys %{$h->{$mod}};
593 } else {
594 # @r = map { @$_ } values %$h;
595 my %h;
596 @h{keys %$_} = 1 for values %$h;
597 @r = keys %h;
599 @r = sort @r;
600 return wantarray ? @r : \@r;
603 sub _var_ret_list
605 my ($h, $v, $mod, $assign) = @_;
606 if ($v =~ /^(.*)::([^:]+)$/) {
607 $mod = $1;
608 $v = $2;
610 $h = $h->{$v};
611 my @r;
612 if ($mod) {
613 @r = exists $h->{$mod} ? @{$h->{$mod}} : ();
614 } else {
615 ## XXX: Need to revisit when this is/isn't an array!
616 @r = map { ref $_ eq 'ARRAY' ? @$_ : $_ } values %$h;
618 @r = grep $_->{assign}, @r if $assign;
619 @r = map { [@{$_}{qw(file line sub package)}] } @r;
620 return wantarray ? @r : \@r;
623 =item C<callers($func)>
625 List callers of C<$func>.
627 =cut
629 sub callers {
630 _ret_list \%call, @_;
633 =item C<callees($func)>
635 List callees of C<$func>.
637 =cut
639 sub callees {
640 _ret_list \%callby, @_;
643 =item C<var_defs($var)>
645 Find locations where C<$var> is defined.
647 =cut
649 sub var_defs {
650 return _var_ret_list \%var_def, @_;
653 =item C<var_uses($var)>
655 Find locations where C<$var> is used.
657 =cut
659 sub var_uses {
660 return _var_ret_list \%var_use, @_;
663 =item C<var_assigns($var)>
665 Find locations where C<$var> is assigned to.
667 =cut
669 sub var_assigns {
670 my ($v, $pack) = @_;
671 return _var_ret_list \%var_use, $v, $pack, 1;
674 =item C<file_modules($file)>
676 List the modules defined in file C<$file>.
678 =cut
680 sub file_modules {
681 my $file = shift;
682 eval {
683 require Module::Info;
684 my $mod = Module::Info->new_from_file(abs_path($file));
685 if ( $mod ) {
686 return $mod->packages_inside();
691 =item C<var_apropos($expr)>
693 Find variables matching C<$expr>.
695 =cut
697 sub _apropos {
698 my ($h, $re, $mod) = @_;
699 my @r = do {
700 if($re) {
701 $re = _apropos_re($re);
702 sort grep /$re/, keys %$h;
703 } else {
704 sort keys %$h;
707 if ($mod) {
708 $mod = _apropos_re($mod);
709 my %r;
710 for (@r) {
711 my $sn = $_;
712 for (keys %{$h->{$_}}) {
713 $r{$_ eq 'main' ? $sn : "$_\::$sn"} = 1 if /$mod/;
716 @r = sort keys %r;
718 return wantarray ? @r : \@r;
721 sub var_apropos {
722 _apropos \%var_use, @_;
727 __END__
729 =back
731 =head1 EXPORTS
733 Nothing by default, but all sub and variable described above can be
734 imported. C<Sepia::Xref> also defines the tags C<:most> for the
735 above-listed functions, and C<:all> for those and the variables as
736 well.
738 =head1 BUGS
740 =over 4
742 =item See L<B::Xref>.
744 =item module names are ignored when looking up a sub.
746 =item file and line number guessing is evil
748 Both should be done more cleanly and effectively. This is a hack
749 because I don't quite understand what perl saves. We should be able
750 to do as well as its warning messages.
752 =item Some packages are not xref'd.
754 Some "internal" packages are deliberately not cross-referenced, either
755 because they are hairy and cause us problems, or because they are so
756 commonly included as to be uninteresting. The current list includes
757 all pragmatic modules, plus: B, O, AutoLoader, DynaLoader, XSLoader,
758 Config, DB, VMS, FileHandle, Exporter, Carp, PerlIO::Layer.
760 =item Tree-view is not fully functional
762 Ideally, clicking the function names in tree view would take you to
763 that function. This doesn't work. Also, more keys (like "q" to quit)
764 should be implemented.
766 =back
768 =head1 SEE ALSO
770 C<B::Xref>, of which C<Sepia::Xref> is a bastard child.
772 =head1 AUTHOR
774 L<B::Xref> by Malcolm Beattie, m(angl|odifi)ed by Sean O'Rourke
775 (seano@cpan.org).
777 =cut