);
}
+sub list_non_method_package_symbols {
+ my $self = shift;
+
+ my %method_names = map { $_ => 1 } $self->get_all_method_names;
+
+ # this is injected for classes that use overloading
+ $method_names{'()'} = 1;
+
+ my @all_symbols = $self->list_all_package_symbols("CODE");
+
+ return grep { not exists $method_names{$_} } @all_symbols;
+}
+
+sub warn_on_symbol_pollution {
+ my $self = shift;
+
+ if ( my @pollution = $self->list_non_method_package_symbols ) {
+ Carp::carp( "Polluting symbols found in "
+ . $self->name . ": "
+ . join( ", ", @pollution )
+ . ". Consider unimporting or using namespace::autoclean" );
+ }
+}
+
sub make_immutable {
my ( $self, @args ) = @_;
=over 4
+=item B<< $metaclass->list_non_method_package_symbols >>
+
+Compares the list of all C<CODE> symbols to the output of
+C<get_all_method_names> and returns the non method ones.
+
+=item B<< $metaclass->warn_on_symbol_pollution >>
+
+Issues a warning if C<list_non_method_package_symbols> returns anything.
+
=item B<< $metaclass->make_immutable(%options) >>
This method will create an immutable transformer and use it to make
use strict;
use warnings;
-use Test::More tests => 304;
+use Test::More tests => 308;
use Test::Exception;
use Class::MOP;
immutable_trait immutable_options
constructor_name constructor_class destructor_class
+ list_non_method_package_symbols warn_on_symbol_pollution
+
DESTROY
);
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More tests => 5;
+
+{
+ package Foo;
+ use metaclass;
+
+ use Scalar::Util qw(blessed);
+
+ no warnings 'once';
+ *a_glob_assignment = \&Scalar::Util::blessed;
+
+ sub a_declared_method { }
+
+ Class::MOP::Class->initialize(__PACKAGE__)->add_method("an_added_method" => sub {});
+}
+
+my @warnings;
+
+{
+ local $SIG{__WARN__} = sub { push @warnings, $_[0] };
+ Class::MOP::Class->initialize("Foo")->warn_on_symbol_pollution();
+}
+
+is( scalar(@warnings), 1, "warning generated" );
+
+my $warning = $warnings[0];
+
+like( $warning, qr/blessed/, "mentions import" );
+like( $warning, qr/a_glob_assignment/, "mentions glob assignment" );
+unlike( $warning, qr/a_declared_method/, "doesn't mention normal method" );
+unlike( $warning, qr/an_added_method/, "doesn't mention a manually installed method" );
+
+