Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,95 @@
package MooseX::Declare::Syntax::EmptyBlockIfMissing;
# ABSTRACT: Handle missing blocks after keywords
our $VERSION = '0.43';
use Moose::Role;
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod The L<MooseX::Declare::Syntax::NamespaceHandling> role will require that the
#pod consumer handles the case of non-existent blocks. This role will inject
#pod an empty block with only the generated code parts in it.
#pod
#pod =method handle_missing_block
#pod
#pod Object->handle_missing_block (Object $context, Str $body, %args)
#pod
#pod This will inject the generated code surrounded by C<{ ... }> into the code
#pod where the keyword was called.
#pod
#pod =cut
sub handle_missing_block {
my ($self, $ctx, $inject, %args) = @_;
# default to block with nothing more than the default contents
$ctx->inject_code_parts_here("{ $inject }");
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::NamespaceHandling>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::EmptyBlockIfMissing - Handle missing blocks after keywords
=head1 VERSION
version 0.43
=head1 DESCRIPTION
The L<MooseX::Declare::Syntax::NamespaceHandling> role will require that the
consumer handles the case of non-existent blocks. This role will inject
an empty block with only the generated code parts in it.
=head1 METHODS
=head2 handle_missing_block
Object->handle_missing_block (Object $context, Str $body, %args)
This will inject the generated code surrounded by C<{ ... }> into the code
where the keyword was called.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::NamespaceHandling>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,138 @@
package MooseX::Declare::Syntax::Extending;
# ABSTRACT: Extending with superclasses
our $VERSION = '0.43';
use Moose::Role;
use aliased 'MooseX::Declare::Context::Namespaced';
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod Extends a class by a specified C<extends> option.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::OptionHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::OptionHandling
);
around context_traits => sub { shift->(@_), Namespaced };
#pod =method add_extends_option_customizations
#pod
#pod Object->add_extends_option_customizations (
#pod Object $ctx,
#pod Str $package,
#pod ArrayRef $superclasses,
#pod HashRef $options
#pod )
#pod
#pod This will add a code part that will call C<extends> with the C<$superclasses>
#pod as arguments.
#pod
#pod =cut
sub add_extends_option_customizations {
my ($self, $ctx, $package, $superclasses) = @_;
# add code for extends keyword
$ctx->add_scope_code_parts(
sprintf 'extends %s',
join ', ',
map { "'$_'" }
map { $ctx->qualify_namespace($_) }
@{ $superclasses },
);
return 1;
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::Keyword::Class>
#pod * L<MooseX::Declare::Syntax::OptionHandling>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Extending - Extending with superclasses
=head1 VERSION
version 0.43
=head1 DESCRIPTION
Extends a class by a specified C<extends> option.
=head1 METHODS
=head2 add_extends_option_customizations
Object->add_extends_option_customizations (
Object $ctx,
Str $package,
ArrayRef $superclasses,
HashRef $options
)
This will add a code part that will call C<extends> with the C<$superclasses>
as arguments.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::OptionHandling>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::Keyword::Class>
=item *
L<MooseX::Declare::Syntax::OptionHandling>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,174 @@
package MooseX::Declare::Syntax::InnerSyntaxHandling;
# ABSTRACT: Keywords inside blocks
our $VERSION = '0.43';
use Moose::Role;
use MooseX::Declare::Util qw( outer_stack_push );
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This role allows you to setup keyword handlers that are only available
#pod inside blocks or other scoping environments.
#pod
#pod =head1 REQUIRED METHODS
#pod
#pod =head2 get_identifier
#pod
#pod Str get_identifier ()
#pod
#pod Required to return the name of the identifier of the current handler.
#pod
#pod =cut
requires qw(
get_identifier
);
#pod =method default_inner
#pod
#pod ArrayRef[Object] Object->default_inner ()
#pod
#pod Returns an empty C<ArrayRef> by default. If you want to setup additional
#pod keywords you will have to C<around> this method.
#pod
#pod =cut
sub default_inner { [] }
#pod =head1 MODIFIED METHODS
#pod
#pod =head2 setup_for
#pod
#pod Object->setup_for(ClassName $class, %args)
#pod
#pod After the keyword is setup inside itself, this will call L</setup_inner_for>.
#pod
#pod =cut
after setup_for => sub {
my ($self, $setup_class, %args) = @_;
# make sure stack is valid
my $stack = $args{stack} || [];
# setup inner keywords if we're inside ourself
if (grep { $_ eq $self->get_identifier } @$stack) {
$self->setup_inner_for($setup_class, %args);
}
};
#pod =method setup_inner_for
#pod
#pod Object->setup_inner_for(ClassName $class, %args)
#pod
#pod Sets up all handlers in the inner class.
#pod
#pod =cut
sub setup_inner_for {
my ($self, $setup_class, %args) = @_;
# setup each keyword in target class
for my $inner (@{ $self->default_inner($args{stack}) }) {
$inner->setup_for($setup_class, %args);
}
# push package onto stack for namespace management
if (exists $args{file}) {
outer_stack_push $args{file}, $args{outer_package};
}
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::NamespaceHandling>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::InnerSyntaxHandling - Keywords inside blocks
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role allows you to setup keyword handlers that are only available
inside blocks or other scoping environments.
=head1 METHODS
=head2 default_inner
ArrayRef[Object] Object->default_inner ()
Returns an empty C<ArrayRef> by default. If you want to setup additional
keywords you will have to C<around> this method.
=head2 setup_inner_for
Object->setup_inner_for(ClassName $class, %args)
Sets up all handlers in the inner class.
=head1 REQUIRED METHODS
=head2 get_identifier
Str get_identifier ()
Required to return the name of the identifier of the current handler.
=head1 MODIFIED METHODS
=head2 setup_for
Object->setup_for(ClassName $class, %args)
After the keyword is setup inside itself, this will call L</setup_inner_for>.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::NamespaceHandling>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,179 @@
package MooseX::Declare::Syntax::Keyword::Class;
# ABSTRACT: Class declarations
our $VERSION = '0.43';
use Moose;
use namespace::autoclean;
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod * L<MooseX::Declare::Syntax::RoleApplication>
#pod * L<MooseX::Declare::Syntax::Extending>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::MooseSetup
MooseX::Declare::Syntax::RoleApplication
MooseX::Declare::Syntax::Extending
);
#pod =head1 MODIFIED METHODS
#pod
#pod =head2 imported_moose_symbols
#pod
#pod List Object->imported_moose_symbols ()
#pod
#pod Extends the existing L<MooseX::Declare::Syntax::MooseSetup/imported_moose_symbols>
#pod with C<extends>, C<has>, C<inner> and C<super>.
#pod
#pod =cut
around imported_moose_symbols => sub { shift->(@_), qw( extends has inner super ) };
#pod =method generate_export
#pod
#pod CodeRef generate_export ()
#pod
#pod This will return a closure doing a call to L</make_anon_metaclass>.
#pod
#pod =cut
sub generate_export { my $self = shift; sub { $self->make_anon_metaclass } }
#pod =head2 auto_make_immutable
#pod
#pod Bool Object->auto_make_immutable ()
#pod
#pod Is set to a true value, so classes are made immutable by default.
#pod
#pod =cut
around auto_make_immutable => sub { 1 };
#pod =head2 make_anon_metaclass
#pod
#pod Object Object->make_anon_metaclass ()
#pod
#pod Returns an anonymous instance of L<Moose::Meta::Class>.
#pod
#pod =cut
around make_anon_metaclass => sub { Moose::Meta::Class->create_anon_class };
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::Keyword::Role>
#pod * L<MooseX::Declare::Syntax::RoleApplication>
#pod * L<MooseX::Declare::Syntax::Extending>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::Class - Class declarations
=head1 VERSION
version 0.43
=head1 METHODS
=head2 generate_export
CodeRef generate_export ()
This will return a closure doing a call to L</make_anon_metaclass>.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=item *
L<MooseX::Declare::Syntax::RoleApplication>
=item *
L<MooseX::Declare::Syntax::Extending>
=back
=head1 MODIFIED METHODS
=head2 imported_moose_symbols
List Object->imported_moose_symbols ()
Extends the existing L<MooseX::Declare::Syntax::MooseSetup/imported_moose_symbols>
with C<extends>, C<has>, C<inner> and C<super>.
=head2 auto_make_immutable
Bool Object->auto_make_immutable ()
Is set to a true value, so classes are made immutable by default.
=head2 make_anon_metaclass
Object Object->make_anon_metaclass ()
Returns an anonymous instance of L<Moose::Meta::Class>.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::Keyword::Role>
=item *
L<MooseX::Declare::Syntax::RoleApplication>
=item *
L<MooseX::Declare::Syntax::Extending>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,136 @@
package MooseX::Declare::Syntax::Keyword::Clean;
# ABSTRACT: Explicit namespace cleanups
our $VERSION = '0.43';
use Moose;
use constant NAMESPACING_ROLE => 'MooseX::Declare::Syntax::NamespaceHandling';
use Carp qw( cluck );
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This keyword will inject a call to L<namespace::clean> into its current
#pod position.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::KeywordHandling
);
sub find_namespace_handler {
my ($self, $ctx) = @_;
for my $item (reverse @{ $ctx->stack }) {
return $item
if $item->handler->does(NAMESPACING_ROLE);
}
return undef;
}
#pod =method parse
#pod
#pod Object->parse(Object $context)
#pod
#pod This will inject a call to L<namespace::clean> C<< -except => 'meta' >> into
#pod the code at the position of the keyword.
#pod
#pod =cut
sub parse {
my ($self, $ctx) = @_;
if (my $stack_item = $self->find_namespace_handler($ctx)) {
my $namespace = $stack_item->namespace;
cluck "Attempted to clean an already cleaned namespace ($namespace). Did you mean to use 'is dirty'?"
unless $stack_item->is_dirty;
}
$ctx->skip_declarator;
$ctx->inject_code_parts_here(
';use namespace::clean -except => [qw( meta )]',
);
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::Clean - Explicit namespace cleanups
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This keyword will inject a call to L<namespace::clean> into its current
position.
=head1 METHODS
=head2 parse
Object->parse(Object $context)
This will inject a call to L<namespace::clean> C<< -except => 'meta' >> into
the code at the position of the keyword.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,146 @@
package MooseX::Declare::Syntax::Keyword::Method;
# ABSTRACT: Handle method declarations
our $VERSION = '0.43';
use Moose;
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This role is an extension of L<MooseX::Declare::Syntax::MethodDeclaration>
#pod that allows you to install keywords that declare methods.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::MethodDeclaration>
#pod
#pod =cut
with 'MooseX::Declare::Syntax::MethodDeclaration';
#pod =method register_method_declaration
#pod
#pod Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
#pod
#pod This method required by the method declaration role will register the finished
#pod method object via the C<< $metaclass->add_method >> method.
#pod
#pod MethodModifier->new(
#pod identifier => 'around',
#pod modifier_type => 'around',
#pod prototype_injections => {
#pod declarator => 'around',
#pod injections => [ 'CodeRef $orig' ],
#pod },
#pod );
#pod
#pod This will mean that the signature C<(Str $foo)> will become
#pod C<CodeRef $orig: Object $self, Str $foo> and C<()> will become
#pod C<CodeRef $orig: Object $self>.
#pod
#pod =cut
sub register_method_declaration {
my ($self, $meta, $name, $method) = @_;
return $meta->add_method($name, $method);
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod * L<MooseX::Declare::Syntax::MethodDeclaration>
#pod * L<MooseX::Method::Signatures>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::Method - Handle method declarations
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role is an extension of L<MooseX::Declare::Syntax::MethodDeclaration>
that allows you to install keywords that declare methods.
=head1 METHODS
=head2 register_method_declaration
Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
This method required by the method declaration role will register the finished
method object via the C<< $metaclass->add_method >> method.
MethodModifier->new(
identifier => 'around',
modifier_type => 'around',
prototype_injections => {
declarator => 'around',
injections => [ 'CodeRef $orig' ],
},
);
This will mean that the signature C<(Str $foo)> will become
C<CodeRef $orig: Object $self, Str $foo> and C<()> will become
C<CodeRef $orig: Object $self>.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::MethodDeclaration>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=item *
L<MooseX::Declare::Syntax::MethodDeclaration>
=item *
L<MooseX::Method::Signatures>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,173 @@
package MooseX::Declare::Syntax::Keyword::MethodModifier;
# ABSTRACT: Handle method modifier declarations
our $VERSION = '0.43';
use Moose;
use Moose::Util;
use Moose::Util::TypeConstraints 'enum';
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod Allows the implementation of method modification handlers like C<around> and
#pod C<before>.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::MethodDeclaration>
#pod
#pod =cut
with 'MooseX::Declare::Syntax::MethodDeclaration';
#pod =attr modifier_type
#pod
#pod A required string that is one of:
#pod
#pod =for :list
#pod * around
#pod * after
#pod * before
#pod * override
#pod * augment
#pod
#pod =cut
has modifier_type => (
is => 'rw',
isa => enum([qw( around after before override augment )]),
required => 1,
);
#pod =method register_method_declaration
#pod
#pod Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
#pod
#pod This will add the method modifier to the C<$metaclass> via L<Moose::Util>s
#pod C<add_method_modifier>, whose return value will also be returned from this
#pod method.
#pod
#pod =cut
sub register_method_declaration {
my ($self, $meta, $name, $method) = @_;
return Moose::Util::add_method_modifier($meta->name, $self->modifier_type, [$name, $method->body]);
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod * L<MooseX::Declare::Syntax::MethodDeclaration>
#pod * L<MooseX::Method::Signatures>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::MethodModifier - Handle method modifier declarations
=head1 VERSION
version 0.43
=head1 DESCRIPTION
Allows the implementation of method modification handlers like C<around> and
C<before>.
=head1 ATTRIBUTES
=head2 modifier_type
A required string that is one of:
=over 4
=item *
around
=item *
after
=item *
before
=item *
override
=item *
augment
=back
=head1 METHODS
=head2 register_method_declaration
Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
This will add the method modifier to the C<$metaclass> via L<Moose::Util>s
C<add_method_modifier>, whose return value will also be returned from this
method.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::MethodDeclaration>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=item *
L<MooseX::Declare::Syntax::MethodDeclaration>
=item *
L<MooseX::Method::Signatures>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,160 @@
package MooseX::Declare::Syntax::Keyword::Namespace;
# ABSTRACT: Declare outer namespace
our $VERSION = '0.43';
use Moose;
use Carp qw( confess );
use MooseX::Declare::Util qw( outer_stack_push outer_stack_peek );
use namespace::autoclean;
#pod =head1 SYNOPSIS
#pod
#pod use MooseX::Declare;
#pod
#pod namespace Foo::Bar;
#pod
#pod class ::Baz extends ::Qux with ::Fnording {
#pod ...
#pod }
#pod
#pod =head1 DESCRIPTION
#pod
#pod The C<namespace> keyword allows you to declare an outer namespace under
#pod which other namespaced constructs can be nested. The L</SYNOPSIS> is
#pod effectively the same as
#pod
#pod use MooseX::Declare;
#pod
#pod class Foo::Bar::Baz extends Foo::Bar::Qux with Foo::Bar::Fnording {
#pod ...
#pod }
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::KeywordHandling
);
#pod =method parse
#pod
#pod Object->parse(Object $context)
#pod
#pod Will skip the declarator, parse the namespace and push the namespace
#pod in the file package stack.
#pod
#pod =cut
sub parse {
my ($self, $ctx) = @_;
confess "Nested namespaces are not supported yet"
if outer_stack_peek $ctx->caller_file;
$ctx->skip_declarator;
my $namespace = $ctx->strip_word
or confess "Expected a namespace argument to use from here on";
confess "Relative namespaces are currently not supported"
if $namespace =~ /^::/;
$ctx->skipspace;
my $next_char = $ctx->peek_next_char;
confess "Expected end of statement after namespace argument"
unless $next_char eq ';';
outer_stack_push $ctx->caller_file, $namespace;
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::Namespace - Declare outer namespace
=head1 VERSION
version 0.43
=head1 SYNOPSIS
use MooseX::Declare;
namespace Foo::Bar;
class ::Baz extends ::Qux with ::Fnording {
...
}
=head1 DESCRIPTION
The C<namespace> keyword allows you to declare an outer namespace under
which other namespaced constructs can be nested. The L</SYNOPSIS> is
effectively the same as
use MooseX::Declare;
class Foo::Bar::Baz extends Foo::Bar::Qux with Foo::Bar::Fnording {
...
}
=head1 METHODS
=head2 parse
Object->parse(Object $context)
Will skip the declarator, parse the namespace and push the namespace
in the file package stack.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,256 @@
package MooseX::Declare::Syntax::Keyword::Role;
# ABSTRACT: Role declarations
our $VERSION = '0.43';
use Moose;
use Moose::Util qw(does_role find_meta);
use aliased 'Parse::Method::Signatures' => 'PMS';
use aliased 'MooseX::Declare::Syntax::MethodDeclaration';
use aliased 'Parse::Method::Signatures::Param::Placeholder';
use aliased 'MooseX::Declare::Context::Parameterized', 'ParameterizedCtx';
use aliased 'MooseX::Declare::Syntax::MethodDeclaration::Parameterized', 'ParameterizedMethod';
use namespace::autoclean;
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod * L<MooseX::Declare::Syntax::RoleApplication>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::MooseSetup
MooseX::Declare::Syntax::RoleApplication
);
#pod =head1 MODIFIED METHODS
#pod
#pod =head2 imported_moose_symbols
#pod
#pod List Object->imported_moose_symbols ()
#pod
#pod Extends the existing L<MooseX::Declare::Syntax::MooseSetup/imported_moose_symbols>
#pod with C<requires>, C<extends>, C<has>, C<inner> and C<super>.
#pod
#pod =cut
around imported_moose_symbols => sub { shift->(@_), qw( requires excludes extends has inner super ) };
#pod =head2 import_symbols_from
#pod
#pod Str Object->import_symbols_from ()
#pod
#pod Will return L<Moose::Role> instead of the default L<Moose>.
#pod
#pod =cut
around import_symbols_from => sub {
my ($next, $self, $ctx) = @_;
return $ctx->has_parameter_signature
? 'MooseX::Role::Parameterized'
: 'Moose::Role';
};
#pod =head2 make_anon_metaclass
#pod
#pod Object Object->make_anon_metaclass ()
#pod
#pod This will return an anonymous instance of L<Moose::Meta::Role>.
#pod
#pod =cut
around make_anon_metaclass => sub { Moose::Meta::Role->create_anon_role };
around context_traits => sub { shift->(@_), ParameterizedCtx };
around default_inner => sub {
my ($next, $self, $stack) = @_;
my $inner = $self->$next;
return $inner
if !@{ $stack || [] } || !$stack->[-1]->is_parameterized;
ParameterizedMethod->meta->apply($_)
for grep { does_role($_, MethodDeclaration) } @{ $inner };
return $inner;
};
#pod =method generate_export
#pod
#pod CodeRef Object->generate_export ()
#pod
#pod Returns a closure with a call to L</make_anon_metaclass>.
#pod
#pod =cut
sub generate_export { my $self = shift; sub { $self->make_anon_metaclass } }
after parse_namespace_specification => sub {
my ($self, $ctx) = @_;
$ctx->strip_parameter_signature;
};
after add_namespace_customizations => sub {
my ($self, $ctx, $package, $options) = @_;
$self->add_parameterized_customizations($ctx, $package, $options)
if $ctx->has_parameter_signature;
};
sub add_parameterized_customizations {
my ($self, $ctx, $package, $options) = @_;
my $sig = PMS->signature(
input => "(${\$ctx->parameter_signature})",
from_namespace => $ctx->get_curstash_name,
);
confess 'Positional parameters are not allowed in parameterized roles'
if $sig->has_positional_params;
my @vars = map {
does_role($_, Placeholder)
? ()
: {
var => $_->variable_name,
name => $_->label,
tc => $_->meta_type_constraint,
($_->has_default_value
? (default => $_->default_value)
: ()),
},
} $sig->named_params;
$ctx->add_preamble_code_parts(
sprintf 'my (%s) = map { $_[0]->$_ } qw(%s);',
join(',', map { $_->{var} } @vars),
join(' ', map { $_->{name} } @vars),
);
for my $var (@vars) {
$ctx->add_parameter($var->{name} => {
is => 'ro',
isa => $var->{tc},
(exists $var->{default}
? (default => sub { eval $var->{default} })
: ()),
});
}
}
after handle_post_parsing => sub {
my ($self, $ctx, $package, $class) = @_;
return unless $ctx->has_parameter_signature;
$ctx->shadow(sub (&) {
my $meta = find_meta($class);
$meta->add_parameter($_->[0], %{ $_->[1] })
for $ctx->get_parameters;
$meta->role_generator($_[0]);
return $class;
});
};
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::Keyword::Class>
#pod * L<MooseX::Declare::Syntax::RoleApplication>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::Role - Role declarations
=head1 VERSION
version 0.43
=head1 METHODS
=head2 generate_export
CodeRef Object->generate_export ()
Returns a closure with a call to L</make_anon_metaclass>.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=item *
L<MooseX::Declare::Syntax::RoleApplication>
=back
=head1 MODIFIED METHODS
=head2 imported_moose_symbols
List Object->imported_moose_symbols ()
Extends the existing L<MooseX::Declare::Syntax::MooseSetup/imported_moose_symbols>
with C<requires>, C<extends>, C<has>, C<inner> and C<super>.
=head2 import_symbols_from
Str Object->import_symbols_from ()
Will return L<Moose::Role> instead of the default L<Moose>.
=head2 make_anon_metaclass
Object Object->make_anon_metaclass ()
This will return an anonymous instance of L<Moose::Meta::Role>.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::Keyword::Class>
=item *
L<MooseX::Declare::Syntax::RoleApplication>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,153 @@
package MooseX::Declare::Syntax::Keyword::With;
# ABSTRACT: Apply roles within a class- or role-body
our $VERSION = '0.43';
use Moose;
use Moose::Util;
use MooseX::Declare::Util qw( outer_stack_peek );
use aliased 'MooseX::Declare::Context::Namespaced';
use namespace::autoclean;
#pod =head1 SYNOPSIS
#pod
#pod use MooseX::Declare;
#pod
#pod class ::Baz {
#pod with 'Qux';
#pod ...
#pod }
#pod
#pod =head1 DESCRIPTION
#pod
#pod The C<with> keyword allows you to apply roles to the local class or role. It
#pod differs from the C<with>-option of the C<class> and C<role> keywords in that it
#pod applies the roles immediately instead of deferring application until the end of
#pod the class- or role-definition.
#pod
#pod It also differs slightly from the C<with> provided by L<Moose|Moose> in that it
#pod expands relative role names (C<::Foo>) according to the current C<namespace>.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::KeywordHandling
);
around context_traits => sub { shift->(@_), Namespaced };
#pod =method parse
#pod
#pod Object->parse(Object $context)
#pod
#pod Will skip the declarator and make with C<with> invocation apply the set of
#pod specified roles after possible C<namespace>-expanding has been done.
#pod
#pod =cut
sub parse {
my ($self, $ctx) = @_;
$ctx->skip_declarator;
my $pkg = outer_stack_peek $ctx->caller_file;
$ctx->shadow(sub {
Moose::Util::apply_all_roles($pkg, map {
$ctx->qualify_namespace($_)
} @_);
});
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::Keyword::Namespace>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::Keyword::With - Apply roles within a class- or role-body
=head1 VERSION
version 0.43
=head1 SYNOPSIS
use MooseX::Declare;
class ::Baz {
with 'Qux';
...
}
=head1 DESCRIPTION
The C<with> keyword allows you to apply roles to the local class or role. It
differs from the C<with>-option of the C<class> and C<role> keywords in that it
applies the roles immediately instead of deferring application until the end of
the class- or role-definition.
It also differs slightly from the C<with> provided by L<Moose|Moose> in that it
expands relative role names (C<::Foo>) according to the current C<namespace>.
=head1 METHODS
=head2 parse
Object->parse(Object $context)
Will skip the declarator and make with C<with> invocation apply the set of
specified roles after possible C<namespace>-expanding has been done.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::Keyword::Namespace>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,240 @@
package MooseX::Declare::Syntax::KeywordHandling;
# ABSTRACT: Basic keyword functionality
our $VERSION = '0.43';
use Moose::Role;
use Moose::Util::TypeConstraints qw(subtype as where);
use Devel::Declare ();
use Sub::Install qw( install_sub );
use Moose::Meta::Class ();
use Module::Runtime 'use_module';
use aliased 'MooseX::Declare::Context';
use namespace::autoclean -also => ['_uniq'];
#pod =head1 DESCRIPTION
#pod
#pod This role provides the functionality common for all keyword handlers
#pod in L<MooseX::Declare>.
#pod
#pod =head1 REQUIRED METHODS
#pod
#pod =head2 parse
#pod
#pod Object->parse (Object $context)
#pod
#pod This method must implement the actual parsing of the keyword syntax.
#pod
#pod =cut
requires qw(
parse
);
#pod =attr identifier
#pod
#pod This is the name of the actual keyword. It is a required string that is in
#pod the same format as a usual Perl identifier.
#pod
#pod =cut
has identifier => (
is => 'ro',
isa => subtype(as 'Str', where { /^ [_a-z] [_a-z0-9]* $/ix }),
required => 1,
);
#pod =method get_identifier
#pod
#pod Str Object->get_identifier ()
#pod
#pod Returns the name the handler will be setup under.
#pod
#pod =cut
sub get_identifier { shift->identifier }
sub context_class { Context }
sub context_traits { }
#pod =method setup_for
#pod
#pod Object->setup_for (ClassName $class, %args)
#pod
#pod This will setup the handler in the specified C<$class>. The handler will
#pod dispatch to the L</parse_declaration> method when the keyword is used.
#pod
#pod A normal code reference will also be exported into the calling namespace.
#pod It will either be empty or, if a C<generate_export> method is provided,
#pod the return value of that method.
#pod
#pod =cut
sub setup_for {
my ($self, $setup_class, %args) = @_;
# make sure the stack is valid
my $stack = $args{stack} || [];
my $ident = $self->get_identifier;
# setup the D:D handler for our keyword
Devel::Declare->setup_for($setup_class, {
$ident => {
const => sub { $self->parse_declaration((caller(1))[1], \%args, @_) },
},
});
# search or generate a real export
my $export = $self->can('generate_export') ? $self->generate_export($setup_class) : sub { };
# export subroutine
install_sub({
code => $export,
into => $setup_class,
as => $ident,
}) unless $setup_class->can($ident);
return 1;
}
#pod =method parse_declaration
#pod
#pod Object->parse_declaration (Str $filename, HashRef $setup_args, @call_args)
#pod
#pod This simply creates a new L<context|MooseX::Declare::Context> and passes it
#pod to the L</parse> method.
#pod
#pod =cut
sub parse_declaration {
my ($self, $caller_file, $args, @ctx_args) = @_;
# find and load context object class
my $ctx_class = $self->context_class;
use_module $ctx_class;
# do we have traits?
if (my @ctx_traits = _uniq($self->context_traits)) {
use_module $_
for @ctx_traits;
$ctx_class = Moose::Meta::Class->create_anon_class(
superclasses => [$ctx_class],
roles => [@ctx_traits],
cache => 1,
)->name;
}
# create a context object and initialize it
my $ctx = $ctx_class->new(
%{ $args },
caller_file => $caller_file,
);
$ctx->init(@ctx_args);
# parse with current context
return $self->parse($ctx);
}
sub _uniq { keys %{ +{ map { $_ => undef } @_ } } }
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Context>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::KeywordHandling - Basic keyword functionality
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role provides the functionality common for all keyword handlers
in L<MooseX::Declare>.
=head1 ATTRIBUTES
=head2 identifier
This is the name of the actual keyword. It is a required string that is in
the same format as a usual Perl identifier.
=head1 METHODS
=head2 get_identifier
Str Object->get_identifier ()
Returns the name the handler will be setup under.
=head2 setup_for
Object->setup_for (ClassName $class, %args)
This will setup the handler in the specified C<$class>. The handler will
dispatch to the L</parse_declaration> method when the keyword is used.
A normal code reference will also be exported into the calling namespace.
It will either be empty or, if a C<generate_export> method is provided,
the return value of that method.
=head2 parse_declaration
Object->parse_declaration (Str $filename, HashRef $setup_args, @call_args)
This simply creates a new L<context|MooseX::Declare::Context> and passes it
to the L</parse> method.
=head1 REQUIRED METHODS
=head2 parse
Object->parse (Object $context)
This method must implement the actual parsing of the keyword syntax.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Context>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,189 @@
package MooseX::Declare::Syntax::MethodDeclaration;
# ABSTRACT: Handles method declarations
our $VERSION = '0.43';
use Moose::Role;
use MooseX::Method::Signatures::Meta::Method;
use MooseX::Method::Signatures 0.36 ();
use MooseX::Method::Signatures::Types qw/PrototypeInjections/;
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod A role for keyword handlers that gives a framework to add or modify
#pod methods or things that look like methods.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::KeywordHandling
);
#pod =head1 REQUIRED METHODS
#pod
#pod =head2 register_method_declaration
#pod
#pod Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
#pod
#pod This method will be called with the target metaclass and the final built
#pod L<method meta object|MooseX::Method::Signatures::Meta::Method> and its name.
#pod The value it returns will be the value returned where the method was declared.
#pod
#pod =cut
requires qw(
register_method_declaration
);
#pod =attr prototype_injections
#pod
#pod An optional structure describing additional things to be added to a methods
#pod signature. A popular example is found in the C<around>
#pod L<method modifier handler|MooseX::Declare::Syntax::Keyword::MethodModifier>:
#pod
#pod =cut
has prototype_injections => (
is => 'ro',
isa => PrototypeInjections,
predicate => 'has_prototype_injections',
);
#pod =method parse
#pod
#pod Object->parse (Object $ctx);
#pod
#pod Reads a name and a prototype and builds the method meta object then registers
#pod it into the current class using MooseX::Method::Signatures and a
#pod C<custom_method_application>, that calls L</register_method_declaration>.
#pod
#pod =cut
sub parse {
my ($self, $ctx) = @_;
my %args = (
context => $ctx->_dd_context,
initialized_context => 1,
custom_method_application => sub {
my ($meta, $name, $method) = @_;
$self->register_method_declaration($meta, $name, $method);
},
);
$args{prototype_injections} = $self->prototype_injections
if $self->has_prototype_injections;
my $mxms = MooseX::Method::Signatures->new(%args);
$mxms->parser;
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::NamespaceHandling>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod * L<MooseX::Method::Signatures>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::MethodDeclaration - Handles method declarations
=head1 VERSION
version 0.43
=head1 DESCRIPTION
A role for keyword handlers that gives a framework to add or modify
methods or things that look like methods.
=head1 ATTRIBUTES
=head2 prototype_injections
An optional structure describing additional things to be added to a methods
signature. A popular example is found in the C<around>
L<method modifier handler|MooseX::Declare::Syntax::Keyword::MethodModifier>:
=head1 METHODS
=head2 parse
Object->parse (Object $ctx);
Reads a name and a prototype and builds the method meta object then registers
it into the current class using MooseX::Method::Signatures and a
C<custom_method_application>, that calls L</register_method_declaration>.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=back
=head1 REQUIRED METHODS
=head2 register_method_declaration
Object->register_method_declaration (Object $metaclass, Str $name, Object $method)
This method will be called with the target metaclass and the final built
L<method meta object|MooseX::Method::Signatures::Meta::Method> and its name.
The value it returns will be the value returned where the method was declared.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::NamespaceHandling>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=item *
L<MooseX::Method::Signatures>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,24 @@
package # hide from PAUSE
MooseX::Declare::Syntax::MethodDeclaration::Parameterized;
our $VERSION = '0.43';
use Moose::Role;
# we actually require MXRP 1.06 if versions 1.03,1.04,1.05 are installed
# (which is where current_metaclass was removed from the API), but this was
# only in the wild for a short time, so it's not worth creating a dynamic
# prereq for.
use MooseX::Role::Parameterized 0.12 ();
use namespace::autoclean;
around register_method_declaration => sub {
my ($next, $self, $parameterizable_meta, $name, $method) = @_;
my $meta = $self->metaclass_for_method_application($parameterizable_meta, $name, $method);
$self->$next($meta, $name, $method);
};
sub metaclass_for_method_application {
return MooseX::Role::Parameterized->current_metaclass;
}
1;

View File

@@ -0,0 +1,359 @@
package MooseX::Declare::Syntax::MooseSetup;
# ABSTRACT: Common Moose namespaces declarations
our $VERSION = '0.43';
use Moose::Role;
use Moose::Util qw( find_meta );
use Sub::Install qw( install_sub );
use aliased 'MooseX::Declare::Syntax::Keyword::MethodModifier';
use aliased 'MooseX::Declare::Syntax::Keyword::Method';
use aliased 'MooseX::Declare::Syntax::Keyword::With', 'WithKeyword';
use aliased 'MooseX::Declare::Syntax::Keyword::Clean', 'CleanKeyword';
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This role is basically an extension to
#pod L<NamespaceHandling|MooseX::Declare::Syntax::NamespaceHandling>. It adds all
#pod the common parts for L<Moose> namespace definitions. Examples of this role
#pod can be found in the L<class|MooseX::Declare::Syntax::Keyword::Class> and
#pod L<role|MooseX::Declare::Syntax::Keyword::Role> keywords.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::NamespaceHandling>
#pod * L<MooseX::Declare::Syntax::EmptyBlockIfMissing>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::NamespaceHandling
MooseX::Declare::Syntax::EmptyBlockIfMissing
);
#pod =method auto_make_immutable
#pod
#pod Bool Object->auto_make_immutable ()
#pod
#pod Since L<Moose::Role>s can't be made immutable (this is not a bug or a
#pod missing feature, it would make no sense), this always returns false.
#pod
#pod =cut
sub auto_make_immutable { 0 }
#pod =method imported_moose_symbols
#pod
#pod List Object->imported_moose_symbols ()
#pod
#pod This will return C<confess> and C<blessed> by default to provide as
#pod additional imports to the namespace.
#pod
#pod =cut
sub imported_moose_symbols { qw( confess blessed ) }
#pod =method import_symbols_from
#pod
#pod Str Object->import_symbols_from ()
#pod
#pod The namespace from which the additional imports will be imported. This
#pod will return C<Moose> by default.
#pod
#pod =cut
sub import_symbols_from { 'Moose' }
#pod =head1 MODIFIED METHODS
#pod
#pod =head2 default_inner
#pod
#pod ArrayRef default_inner ()
#pod
#pod This will provide the following default inner-handlers to the namespace:
#pod
#pod =for :list
#pod * method
#pod A simple L<Method|MooseX::Declare::Syntax::Keyword::Method> handler.
#pod * around
#pod This is a L<MethodModifier|MooseX::Declare::Syntax::Keyword::MethodModifier>
#pod handler that will start the signature of the generated method with
#pod C<$orig: $self> to provide the original method in C<$orig>.
#pod * after
#pod * before
#pod * override
#pod * augment
#pod These four handlers are L<MethodModifier|MooseX::Declare::Syntax::Keyword::MethodModifier>
#pod instances.
#pod * clean
#pod This is an instance of the L<Clean|MooseX::Declare::Syntax::Keyword::Clean> keyword
#pod handler.
#pod
#pod The original method will never be called and all arguments are ignored at the
#pod moment.
#pod
#pod =cut
around default_inner => sub {
return [
WithKeyword->new(identifier => 'with'),
Method->new(identifier => 'method'),
MethodModifier->new(
identifier => 'around',
modifier_type => 'around',
prototype_injections => {
declarator => 'around',
injections => [ 'CodeRef $orig' ],
},
),
map { MethodModifier->new(identifier => $_, modifier_type => $_) }
qw( after before override augment ),
];
};
#pod =head2 setup_inner_for
#pod
#pod Object->setup_inner_for (ClassName $class)
#pod
#pod This will install a C<with> function that will push its arguments onto a global
#pod storage array holding the roles of the current namespace.
#pod
#pod =cut
after setup_inner_for => sub {
my ($self, $setup_class, %args) = @_;
my $keyword = CleanKeyword->new(identifier => 'clean');
$keyword->setup_for($setup_class, %args);
};
#pod =head2 add_namespace_customizations
#pod
#pod Object->add_namespace_customizations (Object $context, Str $package, HashRef $options)
#pod
#pod After all other customizations, this will first add code to import the
#pod L</imported_moose_symbols> from the package returned in L</import_symbols_from> to
#pod the L<preamble|MooseX::Declare::Context/preamble_code_parts>.
#pod
#pod Then it will add a code part that will immutabilize the class to the
#pod L<cleanup|MooseX::Declare::Context/cleanup_code_parts> code if the
#pod L</auto_make_immutable> method returned a true value and C<< $options->{is}{mutable} >>
#pod does not exist.
#pod
#pod =cut
after add_namespace_customizations => sub {
my ($self, $ctx, $package) = @_;
# add Moose initializations to preamble
$ctx->add_preamble_code_parts(
sprintf 'use %s qw( %s )', $self->import_symbols_from($ctx), join ' ', $self->imported_moose_symbols($ctx),
);
# make class immutable unless specified otherwise
$ctx->add_cleanup_code_parts(
"${package}->meta->make_immutable",
) if $self->auto_make_immutable
and not exists $ctx->options->{is}{mutable};
};
#pod =head2 handle_post_parsing
#pod
#pod CodeRef Object->handle_post_parsing (Object $context, Str $package, Str|Object $name)
#pod
#pod Generates a callback that sets up the roles in the global role storage for the current
#pod namespace. The C<$name> parameter will be the specified name (in contrast to C<$package>
#pod which will always be the fully qualified name) or the anonymous metaclass instance if
#pod none was specified.
#pod
#pod =cut
after handle_post_parsing => sub {
my ($self, $ctx, $package, $class) = @_;
$ctx->shadow(sub (&) { shift->(); return $class; });
};
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<Moose>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::MooseSetup - Common Moose namespaces declarations
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role is basically an extension to
L<NamespaceHandling|MooseX::Declare::Syntax::NamespaceHandling>. It adds all
the common parts for L<Moose> namespace definitions. Examples of this role
can be found in the L<class|MooseX::Declare::Syntax::Keyword::Class> and
L<role|MooseX::Declare::Syntax::Keyword::Role> keywords.
=head1 METHODS
=head2 auto_make_immutable
Bool Object->auto_make_immutable ()
Since L<Moose::Role>s can't be made immutable (this is not a bug or a
missing feature, it would make no sense), this always returns false.
=head2 imported_moose_symbols
List Object->imported_moose_symbols ()
This will return C<confess> and C<blessed> by default to provide as
additional imports to the namespace.
=head2 import_symbols_from
Str Object->import_symbols_from ()
The namespace from which the additional imports will be imported. This
will return C<Moose> by default.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::NamespaceHandling>
=item *
L<MooseX::Declare::Syntax::EmptyBlockIfMissing>
=back
=head1 MODIFIED METHODS
=head2 default_inner
ArrayRef default_inner ()
This will provide the following default inner-handlers to the namespace:
=over 4
=item *
method
A simple L<Method|MooseX::Declare::Syntax::Keyword::Method> handler.
=item *
around
This is a L<MethodModifier|MooseX::Declare::Syntax::Keyword::MethodModifier>
handler that will start the signature of the generated method with
C<$orig: $self> to provide the original method in C<$orig>.
=item *
after
=item *
before
=item *
override
=item *
augment
These four handlers are L<MethodModifier|MooseX::Declare::Syntax::Keyword::MethodModifier>
instances.
=item *
clean
This is an instance of the L<Clean|MooseX::Declare::Syntax::Keyword::Clean> keyword
handler.
=back
The original method will never be called and all arguments are ignored at the
moment.
=head2 setup_inner_for
Object->setup_inner_for (ClassName $class)
This will install a C<with> function that will push its arguments onto a global
storage array holding the roles of the current namespace.
=head2 add_namespace_customizations
Object->add_namespace_customizations (Object $context, Str $package, HashRef $options)
After all other customizations, this will first add code to import the
L</imported_moose_symbols> from the package returned in L</import_symbols_from> to
the L<preamble|MooseX::Declare::Context/preamble_code_parts>.
Then it will add a code part that will immutabilize the class to the
L<cleanup|MooseX::Declare::Context/cleanup_code_parts> code if the
L</auto_make_immutable> method returned a true value and C<< $options->{is}{mutable} >>
does not exist.
=head2 handle_post_parsing
CodeRef Object->handle_post_parsing (Object $context, Str $package, Str|Object $name)
Generates a callback that sets up the roles in the global role storage for the current
namespace. The C<$name> parameter will be the specified name (in contrast to C<$package>
which will always be the fully qualified name) or the anonymous metaclass instance if
none was specified.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<Moose>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,440 @@
package MooseX::Declare::Syntax::NamespaceHandling;
# ABSTRACT: Handle namespaced blocks
our $VERSION = '0.43';
use Moose::Role;
use Moose::Util qw( does_role );
use MooseX::Declare::Util qw( outer_stack_peek );
use Carp;
use aliased 'MooseX::Declare::Context::Namespaced';
use aliased 'MooseX::Declare::Context::WithOptions';
use aliased 'MooseX::Declare::Context::Parameterized';
use aliased 'MooseX::Declare::StackItem';
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod Allows the implementation of namespaced blocks like the
#pod L<role|MooseX::Declare::Syntax::Keyword::Role> and
#pod L<class|MooseX::Declare::Syntax::Keyword::Class> keyword handlers.
#pod
#pod Namespaces are automatically nested. Meaning that, for example, a C<class Bar>
#pod declaration inside another C<class Foo> block gives the inner one actually the
#pod name C<Foo::Bar>.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::KeywordHandling>
#pod * L<MooseX::Declare::Syntax::InnerSyntaxHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::KeywordHandling
MooseX::Declare::Syntax::InnerSyntaxHandling
);
#pod =head1 REQUIRED METHODS
#pod
#pod =head2 handle_missing_block
#pod
#pod Object->handle_missing_block (Object $context, Str $body, %args)
#pod
#pod This must be implemented to decide what to do in case the statement is
#pod terminated rather than followed by a block. It will receive the context
#pod object, the produced code that needs to be injected, and all the arguments
#pod that were passed to the call to L<MooseX::Declare::Context/inject_code_parts>.
#pod
#pod The return value will be ignored.
#pod
#pod =cut
requires qw(
handle_missing_block
);
#pod =head1 EXTENDABLE STUB METHODS
#pod
#pod =head2 add_namespace_customizations
#pod
#pod =head2 add_optional_customizations
#pod
#pod Object->add_namespace_customizations (Object $context, Str $package, HashRef $options)
#pod Object->add_optional_customizations (Object $context, Str $package, HashRef $options)
#pod
#pod These will be called (in this order) by the L</parse> method. They allow specific hooks
#pod to attach before/after/around the customizations for the namespace and the provided
#pod options that are not attached to the namespace directly.
#pod
#pod While this distinction might seem superficial, we advise library developers facilitating
#pod this role to follow the precedent. This ensures that when another component needs to
#pod tie between the namespace and any additional customizations everything will run in the
#pod correct order. An example of this separation would be
#pod
#pod class Foo is mutable ...
#pod
#pod being an option of the namespace generation, while
#pod
#pod class Foo with Bar ...
#pod
#pod is an additional optional customization.
#pod
#pod =head2 handle_post_parsing
#pod
#pod Object->handle_post_parsing (Object $context, Str $package, Str | Object $name)
#pod
#pod Allows for additional modifications to the namespace after everything else has been
#pod done. It will receive the context, the fully qualified package name, and either a
#pod string with the name that was specified (might not be fully qualified, since
#pod namespaces can be nested) or the anonymous metaclass instance if no name was
#pod specified.
#pod
#pod The return value of this method will be the value returned to the user of the
#pod keyword. If you always return the C<$package> argument like this:
#pod
#pod sub handle_post_parsing {
#pod my ($self, $context, $package, $name) = @_;
#pod return $package;
#pod }
#pod
#pod and set this up in a C<foo> keyword handler, you can use it like this:
#pod
#pod foo Cthulhu {
#pod
#pod my $fhtagn = foo Fhtagn { }
#pod my $anon = foo { };
#pod
#pod say $fhtagn; # Cthulhu::Fhtagn
#pod say $anon; # some autogenerated package name
#pod }
#pod
#pod =head2 make_anon_metaclass
#pod
#pod Class::MOP::Class Object->make_anon_metaclass ()
#pod
#pod This method should be overridden if you want to provide anonymous namespaces.
#pod
#pod It does not receive any arguments for customization of the metaclass, because
#pod the configuration and customization will be done by L<MooseX::Declare> in the
#pod package of the generated class in the same way as in those that have specified
#pod names. This way ensures that anonymous and named namespaces are always handled
#pod equally.
#pod
#pod If you do not extend this method (it will return nothing by default), an error
#pod will be thrown when a user attempts to declare an anonymous namespace.
#pod
#pod =cut
sub add_namespace_customizations { }
sub add_optional_customizations { }
sub handle_post_parsing { }
sub make_anon_metaclass { }
around context_traits => sub { super, WithOptions, Namespaced };
sub parse_specification {
my ($self, $ctx) = @_;
$self->parse_namespace_specification($ctx);
$self->parse_option_specification($ctx);
return;
}
sub parse_namespace_specification {
my ($self, $ctx) = @_;
return scalar $ctx->strip_namespace;
}
sub parse_option_specification {
my ($self, $ctx) = @_;
return scalar $ctx->strip_options;
}
sub generate_inline_stack {
my ($self, $ctx) = @_;
return join ', ',
map { $_->serialize }
@{ $ctx->stack },
$self->generate_current_stack_item($ctx);
}
sub generate_current_stack_item {
my ($self, $ctx) = @_;
return StackItem->new(
identifier => $self->identifier,
is_dirty => $ctx->options->{is}{dirty},
is_parameterized => does_role($ctx, Parameterized) && $ctx->has_parameter_signature,
handler => ref($self),
namespace => $ctx->namespace,
);
}
#pod =method parse
#pod
#pod Any Object->parse (Object $context)
#pod
#pod This is the main handling routine for namespaces. It will remove the namespace
#pod name and its options. If the handler was invoked without a name, options or
#pod a following block, it is assumed that this is an instance of an autoquoted
#pod bareword like C<< class => "Foo" >>.
#pod
#pod The return value of the C<parse> method is also the value that is returned
#pod to the user of the keyword.
#pod
#pod =cut
sub parse {
my ($self, $ctx) = @_;
# keyword comes first
$ctx->skip_declarator;
# read the name and unwrap the options
$self->parse_specification($ctx);
my $name = $ctx->namespace;
my ($package, $anon);
# we have a name in the declaration, which will be used as package name
if (defined $name) {
$package = $name;
# there is an outer namespace stack item, meaning we namespace below
# it, if the name starts with ::
if (my $outer = outer_stack_peek $ctx->caller_file) {
$package = $outer . $package
if $name =~ /^::/;
}
}
# no name, no options, no block. Probably { class => 'foo' }
elsif (not(keys %{ $ctx->options }) and $ctx->peek_next_char ne '{') {
return;
}
# we have options and/or a block, but not name
else {
$anon = $self->make_anon_metaclass
or croak sprintf 'Unable to create an anonymized %s namespace', $self->identifier;
$package = $anon->name;
}
# namespace and mx:d initialisations
$ctx->add_preamble_code_parts(
"package ${package}",
sprintf(
"use %s %s => '%s', file => __FILE__, stack => [ %s ]",
$ctx->provided_by,
outer_package => $package,
$self->generate_inline_stack($ctx),
),
);
# allow consumer to provide specialisations
$self->add_namespace_customizations($ctx, $package);
# make options a separate step
$self->add_optional_customizations($ctx, $package);
# finish off preamble with a namespace cleanup
$ctx->add_preamble_code_parts(
$ctx->options->{is}->{dirty}
? 'use namespace::clean -except => [qw( meta )]'
: 'use namespace::autoclean'
);
# clean up our stack afterwards, if there was a name
$ctx->add_cleanup_code_parts(
['BEGIN',
'MooseX::Declare::Util::outer_stack_pop __FILE__',
],
);
# actual code injection
$ctx->inject_code_parts(
missing_block_handler => sub { $self->handle_missing_block(@_) },
);
# a last chance to change things
$self->handle_post_parsing($ctx, $package, defined($name) ? $name : $anon);
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::MooseSetup>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::NamespaceHandling - Handle namespaced blocks
=head1 VERSION
version 0.43
=head1 DESCRIPTION
Allows the implementation of namespaced blocks like the
L<role|MooseX::Declare::Syntax::Keyword::Role> and
L<class|MooseX::Declare::Syntax::Keyword::Class> keyword handlers.
Namespaces are automatically nested. Meaning that, for example, a C<class Bar>
declaration inside another C<class Foo> block gives the inner one actually the
name C<Foo::Bar>.
=head1 METHODS
=head2 parse
Any Object->parse (Object $context)
This is the main handling routine for namespaces. It will remove the namespace
name and its options. If the handler was invoked without a name, options or
a following block, it is assumed that this is an instance of an autoquoted
bareword like C<< class => "Foo" >>.
The return value of the C<parse> method is also the value that is returned
to the user of the keyword.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::KeywordHandling>
=item *
L<MooseX::Declare::Syntax::InnerSyntaxHandling>
=back
=head1 REQUIRED METHODS
=head2 handle_missing_block
Object->handle_missing_block (Object $context, Str $body, %args)
This must be implemented to decide what to do in case the statement is
terminated rather than followed by a block. It will receive the context
object, the produced code that needs to be injected, and all the arguments
that were passed to the call to L<MooseX::Declare::Context/inject_code_parts>.
The return value will be ignored.
=head1 EXTENDABLE STUB METHODS
=head2 add_namespace_customizations
=head2 add_optional_customizations
Object->add_namespace_customizations (Object $context, Str $package, HashRef $options)
Object->add_optional_customizations (Object $context, Str $package, HashRef $options)
These will be called (in this order) by the L</parse> method. They allow specific hooks
to attach before/after/around the customizations for the namespace and the provided
options that are not attached to the namespace directly.
While this distinction might seem superficial, we advise library developers facilitating
this role to follow the precedent. This ensures that when another component needs to
tie between the namespace and any additional customizations everything will run in the
correct order. An example of this separation would be
class Foo is mutable ...
being an option of the namespace generation, while
class Foo with Bar ...
is an additional optional customization.
=head2 handle_post_parsing
Object->handle_post_parsing (Object $context, Str $package, Str | Object $name)
Allows for additional modifications to the namespace after everything else has been
done. It will receive the context, the fully qualified package name, and either a
string with the name that was specified (might not be fully qualified, since
namespaces can be nested) or the anonymous metaclass instance if no name was
specified.
The return value of this method will be the value returned to the user of the
keyword. If you always return the C<$package> argument like this:
sub handle_post_parsing {
my ($self, $context, $package, $name) = @_;
return $package;
}
and set this up in a C<foo> keyword handler, you can use it like this:
foo Cthulhu {
my $fhtagn = foo Fhtagn { }
my $anon = foo { };
say $fhtagn; # Cthulhu::Fhtagn
say $anon; # some autogenerated package name
}
=head2 make_anon_metaclass
Class::MOP::Class Object->make_anon_metaclass ()
This method should be overridden if you want to provide anonymous namespaces.
It does not receive any arguments for customization of the metaclass, because
the configuration and customization will be done by L<MooseX::Declare> in the
package of the generated class in the same way as in those that have specified
names. This way ensures that anonymous and named namespaces are always handled
equally.
If you do not extend this method (it will return nothing by default), an error
will be thrown when a user attempts to declare an anonymous namespace.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::MooseSetup>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,157 @@
package MooseX::Declare::Syntax::OptionHandling;
# ABSTRACT: Option parser dispatching
our $VERSION = '0.43';
use Moose::Role;
use Carp qw( croak );
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This role will call a C<add_foo_option_customization> for every C<foo> option
#pod that is discovered.
#pod
#pod =head1 REQUIRED METHODS
#pod
#pod =head2 get_identifier
#pod
#pod Str Object->get_identifier ()
#pod
#pod This must return the name of the current keyword's identifier.
#pod
#pod =cut
requires qw( get_identifier );
#pod =method ignored_options
#pod
#pod List[Str] Object->ignored_options ()
#pod
#pod This method returns a list of option names that won't be dispatched. By default
#pod this only contains the C<is> option.
#pod
#pod =cut
sub ignored_options { qw( is ) }
#pod =head1 MODIFIED METHODS
#pod
#pod =head2 add_optional_customizations
#pod
#pod Object->add_optional_customizations (Object $context, Str $package, HashRef $options)
#pod
#pod This will dispatch to the respective C<add_*_option_customization> method for option
#pod handling unless the option is listed in the L</ignored_options>.
#pod
#pod =cut
after add_optional_customizations => sub {
my ($self, $ctx, $package) = @_;
my $options = $ctx->options;
# ignored options
my %ignored = map { ($_ => 1) } $self->ignored_options;
# try to find a handler for each option
for my $option (keys %$options) {
next if $ignored{ $option };
# call the handler with its own value and all options
if (my $method = $self->can("add_${option}_option_customizations")) {
$self->$method($ctx, $package, $options->{ $option }, $options);
}
# no handler method was found
else {
croak sprintf q/The '%s' keyword does not know what to do with an '%s' option/,
$self->get_identifier,
$option;
}
}
return 1;
};
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::NamespaceHandling>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::OptionHandling - Option parser dispatching
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role will call a C<add_foo_option_customization> for every C<foo> option
that is discovered.
=head1 METHODS
=head2 ignored_options
List[Str] Object->ignored_options ()
This method returns a list of option names that won't be dispatched. By default
this only contains the C<is> option.
=head1 REQUIRED METHODS
=head2 get_identifier
Str Object->get_identifier ()
This must return the name of the current keyword's identifier.
=head1 MODIFIED METHODS
=head2 add_optional_customizations
Object->add_optional_customizations (Object $context, Str $package, HashRef $options)
This will dispatch to the respective C<add_*_option_customization> method for option
handling unless the option is listed in the L</ignored_options>.
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::NamespaceHandling>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,134 @@
package MooseX::Declare::Syntax::RoleApplication;
# ABSTRACT: Handle user specified roles
our $VERSION = '0.43';
use Moose::Role;
use aliased 'MooseX::Declare::Context::Namespaced';
use namespace::autoclean;
#pod =head1 DESCRIPTION
#pod
#pod This role extends L<MooseX::Declare::Syntax::OptionHandling> and provides
#pod a C<with|/add_with_option_customizations> option.
#pod
#pod =head1 CONSUMES
#pod
#pod =for :list
#pod * L<MooseX::Declare::Syntax::OptionHandling>
#pod
#pod =cut
with qw(
MooseX::Declare::Syntax::OptionHandling
);
around context_traits => sub { shift->(@_), Namespaced };
#pod =method add_with_option_customizations
#pod
#pod Object->add_with_option_customizations (
#pod Object $context,
#pod Str $package,
#pod ArrayRef $roles,
#pod HashRef $options
#pod )
#pod
#pod This will add a call to C<with> in the scope code.
#pod
#pod =cut
sub add_with_option_customizations {
my ($self, $ctx, $package, $roles) = @_;
# consume roles
$ctx->add_early_cleanup_code_parts(
sprintf 'Moose::Util::apply_all_roles(%s->meta, %s)',
$package,
join ', ',
map { "q[$_]" }
map { $ctx->qualify_namespace($_) }
@{ $roles },
);
return 1;
}
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod * L<MooseX::Declare>
#pod * L<MooseX::Declare::Syntax::OptionHandling>
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
MooseX::Declare::Syntax::RoleApplication - Handle user specified roles
=head1 VERSION
version 0.43
=head1 DESCRIPTION
This role extends L<MooseX::Declare::Syntax::OptionHandling> and provides
a C<with|/add_with_option_customizations> option.
=head1 METHODS
=head2 add_with_option_customizations
Object->add_with_option_customizations (
Object $context,
Str $package,
ArrayRef $roles,
HashRef $options
)
This will add a call to C<with> in the scope code.
=head1 CONSUMES
=over 4
=item *
L<MooseX::Declare::Syntax::OptionHandling>
=back
=head1 SEE ALSO
=over 4
=item *
L<MooseX::Declare>
=item *
L<MooseX::Declare::Syntax::OptionHandling>
=back
=head1 AUTHOR
Florian Ragwitz <rafl@debian.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2008 by Florian Ragwitz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut