Class-Generate
view release on metacpan or search on metacpan
lib/Class/Generate.pm view on Meta::CPAN
. join( '|', map $_->name, @private_class_methods ) . ')'
. '(\s*\((?:\s*\))?)?';
}
else
{
undef $private_class_methods_regexp;
}
}
sub substituted($)
{ # Within a code fragment, replace
my $code = $_[0]; # member names and accessors with the
# appropriate forms.
$code =~ s/$member_regexp/member_invocation($1, $&)/eg
if defined $member_regexp;
$code =~ s/$accessor_regexp/accessor_invocation($1, $+, $&)/eg
if defined $accessor_regexp;
$code =~ s/$user_defined_methods_regexp/accessor_invocation($1, $1, $&)/eg
if defined $user_defined_methods_regexp;
$code =~
s/$private_class_methods_regexp/nonpublic_method_invocation("'" . $class->name . "'", $1, $2)/eg
lib/Class/Generate.pm view on Meta::CPAN
package Class::Generate::Code_Checker; # This package encapsulates
$Class::Generate::Code_Checker::VERSION = '1.18';
use strict; # checking for warnings and
use Carp; # errors in user-defined code.
my $package_decl;
my $member_error_message = '%s, member "%s": In "%s" code: %s';
my $method_error_message = '%s, method "%s": %s';
sub create_code_checking_package($);
sub fragment_as_sub($$\@;\@);
sub collect_code_problems($$$$@);
# Check each user-defined code fragment in $class for errors. This includes
# pre, post, and assert code, as well as user-defined methods. Set
# $errors_found according to whether errors (not warnings) were found.
sub check_user_defined_code($$$$)
{
my ( $class, $class_name_label, $warnings, $errors ) = @_;
my ( $code, $instance_var, @valid_variables, @class_vars, $w, $e, @members,
$problems_in_pre, %seen );
create_code_checking_package $class;
@valid_variables = map {
$seen{ $_->name } ? () : do { $seen{ $_->name } = 1; $_->as_var }
lib/Class/Generate.pm view on Meta::CPAN
);
@class_vars = $class->class_vars;
$instance_var = $class->instance_var;
@$warnings = ();
undef $$errors;
for my $member ( $class->constructor, @members )
{
if ( defined( $code = $member->pre ) )
{
$code = fragment_as_sub $code, $instance_var, @class_vars,
@valid_variables;
collect_code_problems $code,
$warnings, $errors,
$member_error_message, $class_name_label, $member->name, 'pre';
$problems_in_pre = @$warnings || $$errors;
}
# Because post shares pre's scope, check post with pre prepended.
# Strip newlines in pre to preserve line numbers in post.
if ( defined( $code = $member->post ) )
{
my $pre = $member->pre;
if ( defined $pre && !$problems_in_pre )
{ # Don't report errors
$pre =~ s/\n+/ /g; # in pre again.
$code = $pre . $code;
}
$code = fragment_as_sub $code, $instance_var, @class_vars,
@valid_variables;
collect_code_problems $code,
$warnings, $errors,
$member_error_message, $class_name_label, $member->name, 'post';
}
if ( defined( $code = $member->assert ) )
{
$code = fragment_as_sub "unless($code){die}", $instance_var,
@class_vars, @valid_variables;
collect_code_problems $code,
$warnings, $errors,
$member_error_message, $class_name_label, $member->name,
'assert';
}
}
for my $method ( $class->user_defined_methods_values )
{
if ( $method->isa('Class::Generate::Class_Method') )
{
$code = fragment_as_sub $method->body, $class->class_var,
@class_vars;
}
else
{
$code = fragment_as_sub $method->body, $instance_var, @class_vars,
@valid_variables;
}
collect_code_problems $code, $warnings, $errors, $method_error_message,
$class_name_label, $method->name;
}
}
sub create_code_checking_package($)
{ # Each class with user-defined code gets
my $class = $_[0]; # its own package in which that code is
lib/Class/Generate.pm view on Meta::CPAN
if ( $class->check_params )
{
$packages .= 'use Carp;';
$packages .= join( ';', $class->warnings_pragmas );
}
$packages .= join( '', map( 'use ' . $_ . ';', $class->use_packages ) );
$packages .= 'use vars qw(@ISA);' if $class->parents;
eval $package_decl . $packages;
}
# Evaluate a code fragment, passing on
sub collect_code_problems($$$$@)
{ # warnings and errors.
my ( $code_form, $warnings, $errors, $error_message, @params ) = @_;
my @warnings;
local $SIG{__WARN__} = sub { push @warnings, $_[0] };
local $SIG{__DIE__};
eval $package_decl . $code_form;
push @$warnings,
map( filtered_message( $error_message, $_, @params ), @warnings );
$$errors .= filtered_message( $error_message, $@, @params ) if $@;
}
sub filtered_message
{ # Clean up errors and messages
my ( $message, $error, @params ) = @_; # a little by removing the
$error =~ s/\(eval \d+\) //g; # "(eval N)" forms that perl
return sprintf( $message, @params, $error ); # inserts.
}
sub fragment_as_sub($$\@;\@)
{
my ( $code, $id_var, $class_vars, $valid_vars ) = @_;
my $form;
$form = "sub{my $id_var;";
if ( $#$class_vars >= 0 )
{
$form .= 'my('
. join( ',', map( ( ref $_ ? keys %$_ : $_ ), @$class_vars ) )
. ');';
}
lib/Class/Generate.pm view on Meta::CPAN
Classes that contain user defined code can yield Perl errors and warnings.
These messages are prefixed by one of the following phrases:
Class class_name, member "name": In "<x>" code:
Class class_name, method "name":
where C<E<lt>xE<gt>> is one of C<pre>, C<post>, or C<assert>.
See L<perldiag> for an explanation of such messages.
The message will include a line number that is relative to the
lines in the erroneous code fragment,
as well as the line number on which the class begins.
For instance, suppose the file C<stacks.pl> contains the following code:
#! /bin/perl
use warnings;
use Class::Generate 'class';
class Stack => [
top_e => { type => '$', private => 1, default => -1 },
elements => { type => '@', private => 1, default => '[]' },
'&push' => '$elements[++$top_e] = $_[0];',
( run in 3.499 seconds using v1.01-cache-2.11-cpan-364913b4093 )