File Coverage

blib/lib/Moops.pm
Criterion Covered Total %
statement 71 80 88.7
branch 11 14 78.5
condition 2 6 33.3
subroutine 21 22 95.4
pod 0 3 0.0
total 105 125 84.0


line stmt bran cond sub pod time code
1 2     2   56716 use v5.14;
  2     34   15  
  34         7488064  
  34         370  
2 2     2   10 use strict;
  2     34   2  
  2         40  
  34         188  
  34         74  
  34         893  
3 2     2   8 use warnings FATAL => 'all';
  2     34   2  
  2         80  
  34         176  
  34         71  
  34         1467  
4 2     2   11 no warnings qw(void once uninitialized numeric);
  2     34   2  
  2         158  
  34         179  
  34         149  
  34         2570  
5              
6             package Moops;
7              
8             our $AUTHORITY = 'cpan:TOBYINK';
9             our $VERSION = '0.037';
10              
11 36     36   15346 use Exporter::Tiny qw(mkopt);
  36         102940  
  36         238  
12 36     36   22970 use Keyword::Simple qw();
  36         798945  
  36         1073  
13 36     36   14371 use Parse::Keyword qw();
  36         123475  
  36         1331  
14 36     36   11993 use Module::Runtime qw(use_package_optimistically);
  36         45008  
  36         238  
15 36     36   2116 use feature qw();
  36         70  
  36         778  
16 36     36   14288 use true qw();
  36         369109  
  36         27717  
17              
18             # Disable 'experimental' warning categories because these lead to
19             # inconsistencies between the different Perl versions supported by
20             # Moops.
21             #
22             # Disable 'void', 'once', 'uninitialized' and 'numeric' because
23             # they are annoying.
24             #
25             # New warnings categories provided by new releases of Perl will not
26             # be added here (but they may be added to a @NONFATAL_WARNINGS array).
27             #
28              
29             our @FATAL_WARNINGS = (
30             'ambiguous',
31             'bareword',
32             'closed',
33             'closure',
34             'debugging',
35             'deprecated',
36             'digit',
37             'exec',
38             'exiting',
39             # 'experimental',
40             # 'experimental::lexical_subs',
41             # 'experimental::lexical_topic',
42             # 'experimental::regex_sets',
43             # 'experimental::smartmatch',
44             'glob',
45             'illegalproto',
46             'imprecision',
47             'inplace',
48             'internal',
49             'io',
50             'layer',
51             'malloc',
52             'misc',
53             'newline',
54             'non_unicode',
55             'nonchar',
56             # 'numeric',
57             # 'once',
58             'overflow',
59             'pack',
60             'parenthesis',
61             'pipe',
62             'portable',
63             'precedence',
64             'printf',
65             'prototype',
66             'qw',
67             'recursion',
68             'redefine',
69             'regexp',
70             'reserved',
71             'semicolon',
72             'severe',
73             'signal',
74             'substr',
75             'surrogate',
76             'syntax',
77             'taint',
78             'threads',
79             # 'uninitialized',
80             'unopened',
81             'unpack',
82             'untie',
83             'utf8',
84             # 'void',
85             );
86              
87             # Don't tamper please!
88             Internals::SvREADONLY(@FATAL_WARNINGS, 1);
89              
90             sub class_for_import_set
91             {
92 1     1 0 473 require Moops::ImportSet;
93 1         11 'Moops::ImportSet';
94             }
95              
96             sub class_for_parser
97             {
98 40     40 0 16206 require Moops::Parser;
99 40         183 'Moops::Parser';
100             }
101              
102             sub unimport
103             {
104 0     0   0 my $class = shift;
105             Keyword::Simple::undefine($_)
106 0         0 for $class->class_for_parser->keywords;
107             }
108              
109             sub import
110             {
111 40     40   14317 my $class = shift;
112 40 50 33     487 my %opts = (
    100          
113             ref($_[0]) eq 'ARRAY' ? (imports => $_[0]) :
114             (!ref($_[0]) and $_[0] eq -strict) ? (imports => ['strictures']) :
115             @_
116             );
117            
118             my $imports = ref($opts{imports}) eq 'ARRAY'
119 40 100       164 ? $class->class_for_import_set->new(imports => mkopt($opts{imports}))
120             : undef;
121            
122 40         233 'strict'->import();
123 40         857 'warnings'->unimport();
124 40         2228 'warnings'->import(FATAL => @FATAL_WARNINGS);
125 40         4867 'feature'->import(':5.14');
126 40         286 'true'->import();
127            
128             my $parser_class = $opts{traits}
129 40 50       30189 ? do {
130 0         0 require Moo::Role;
131 0         0 'Moo::Role'->create_class_with_roles($class->class_for_parser, @{$opts{traits}})
  0         0  
132             }
133             : $class->class_for_parser;
134            
135 40         210 for my $kw ($parser_class->keywords)
136             {
137             Keyword::Simple::define $kw => sub
138             {
139 95     95   1067806 my $ref = $_[0];
140            
141 95         2307 my $parser = $parser_class->new(
142             keyword => $kw,
143             ref => $ref,
144             ccstash => Parse::Keyword::compiling_package(),
145             );
146 95         503 $parser->parse;
147            
148 94         209 my %attrs;
149 94 100       334 $attrs{imports} = $imports if defined $imports;
150 94         423 my $kw = $parser->keyword_object(%attrs);
151            
152 94 50 33     667 if ($opts{function_parameters_everywhere}
153             or $ENV{'MOOPS_FUNCTION_PARAMETERS_EVERYWHERE'})
154             {
155 0         0 require Moo::Role;
156 0         0 'Moo::Role'->apply_roles_to_object($kw, 'Moops::TraitFor::Keyword::fp');
157             }
158            
159 94         614 $kw->check_prerequisites;
160            
161 93         490 my $code = $kw->generate_code;
162 93 100       11143 substr($$ref, 0, 0) = ($parser->is_empty ? "BEGIN { $code }" : "BEGIN { $code ");
163 160         3191 };
164             }
165             }
166              
167             sub at_runtime
168             {
169 92     92 0 8188344 my $class = shift;
170 92         298 my ($pkg) = @_;
171 92         179 for my $task (@{ $Moops::AT_RUNTIME{$pkg} })
  92         6761  
172             {
173 0         0 my ($code, @args) = @$task;
174 0         0 eval "package $pkg; \$code->(\@args)";
175             }
176             }
177              
178 1     1   1767 sub _true { !!1 };
179 1     1   5 sub _false { !!0 };
180              
181             1;
182              
183             __END__
184              
185             =pod
186              
187             =encoding utf-8
188              
189             =for stopwords featureful ro rw rwp superset
190              
191             =head1 NAME
192              
193             Moops - Moops Object-Oriented Programming Sugar
194              
195             =head1 SYNOPSIS
196              
197             use Moops;
198            
199             role NamedThing {
200             has name => (is => "ro", isa => Str);
201             }
202            
203             class Person with NamedThing;
204            
205             class Company with NamedThing;
206            
207             class Employee extends Person {
208             has job_title => (is => "rwp", isa => Str);
209             has employer => (is => "rwp", isa => InstanceOf["Company"]);
210            
211             method change_job ( Object $employer, Str $title ) {
212             $self->_set_job_title($title);
213             $self->_set_employer($employer);
214             }
215            
216             method promote ( Str $title ) {
217             $self->_set_job_title($title);
218             }
219             }
220              
221             =head1 STATUS
222              
223             Unstable.
224              
225             Will probably never be stable.
226              
227             A lot of the modules that Moops is built on have problems. In particular,
228             L<Devel::CallParser> is broken on a lot of Perl versions, and
229             L<Parse::Keyword> has I<< fundamental errors in the way it handles closures >>
230             (which Moops works around using L<PadWalker>).
231              
232             Moops will remain on CPAN for the foreseeable future and I'll continue
233             to accept patches that fix bugs, but don't expect any new features to
234             be added.
235              
236             For a replacement, consider L<MooX::Pression>. It's not a drop-in
237             replacement but it has a similar syntax to Moops, and provides many
238             of the same features.
239              
240             =head1 DESCRIPTION
241              
242             Moops is sugar for declaring and using roles and classes in Perl.
243              
244             The syntax is inspired by L<MooseX::Declare>, and Stevan Little's
245             p5-mop-redux project (which is in turn partly inspired by Perl 6).
246              
247             Moops has fewer than half of the dependencies as MooseX::Declare,
248             loads in about 25% of the time, and the classes built with it run
249             significantly faster. Moops does not use Devel::Declare, instead
250             using Perl's pluggable keyword API; I<< this requires Perl 5.14
251             or above >>.
252              
253             Moops uses L<Moo> to build classes and roles by default, but allows
254             you to use L<Moose> if you desire. (And L<Mouse> experimentally.)
255              
256             =head2 Classes
257              
258             The C<class> keyword declares a class:
259              
260             class Foo {
261             # ...
262             }
263              
264             A version number can be provided:
265              
266             class Foo 1.2 {
267             # ...
268             }
269              
270             If no version is provided, your class' C<< $VERSION >> variable is set
271             to the empty string; this helps the package be seen by L<Class::Load>.
272              
273             If your class extends an existing class through inheritance, or
274             consumes one or more roles, these can also be provided when declaring
275             the class.
276              
277             class Foo::Bar 1.2 extends Foo 1.1 with Magic::Monkeys {
278             # ...
279             }
280              
281             If you use Moops within a package other than C<main>, then package
282             names used within the declaration are "qualified" by that outer
283             package, unless they contain "::". So for example:
284              
285             package Quux;
286             use Moops;
287            
288             class Foo { } # declares Quux::Foo
289            
290             class Xyzzy::Foo # declares Xyzzy::Foo
291             extends Foo { } # ... extending Quux::Foo
292            
293             class ::Baz { } # declares Baz
294              
295             If you wish to use Moose or Mouse instead of Moo; include that in
296             the declaration:
297              
298             class Foo using Moose {
299             # ...
300             }
301              
302             It's also possible to create classes C<< using Tiny >> (L<Class::Tiny>),
303             but there's probably little point in it, because Moops uses Moo
304             internally, so the more capable Moo is already loaded and in memory.
305              
306             (The C<using> option is exempt from the package qualification rules
307             mentioned earlier.)
308              
309             Moops uses L<MooseX::MungeHas> in your classes so that the C<has> keyword
310             supports some Moo-specific features, even when you're using Moose or Mouse.
311             Specifically, it supports C<< is => 'rwp' >>, C<< is => 'lazy' >>,
312             C<< builder => 1 >>, C<< clearer => 1 >>, C<< predicate => 1 >>, and
313             C<< trigger => 1 >>. If you're using Moo, the L<MooX::late> extension is
314             enabled too, which allows Moose-isms in Moo too. With the combination of
315             these features, there should be very little difference between Moo, Mouse
316             and Moose C<has> keywords.
317              
318             Moops uses L<Lexical::Accessor> to provide you with private (lexical)
319             attributes - that is, attributes accessed via a coderef method in a
320             lexical variable.
321              
322             class Foo {
323             lexical_has foo => (
324             isa => Int,
325             accessor => \(my $_foo),
326             default => 0,
327             );
328             method increment_foo () {
329             $self->$_foo( 1 + $self->$_foo );
330             }
331             method get_foo () {
332             return $self->$_foo;
333             }
334             }
335            
336             my $x = Foo->new;
337             $x->increment_foo(); # ok
338             say $x->get_foo(); # says "1"
339             $x->$_foo(42); # dies; $_foo does not exist in this scope
340              
341             Moose classes are automatically accelerated using L<MooseX::XSAccessor>
342             if it's installed.
343              
344             Note that it is possible to declare a class with an empty body;
345             use a trailing semicolon.
346              
347             class Employee extends Person with Employment;
348              
349             If using Moose or Mouse, classes are automatically made immutable.
350              
351             L<namespace::autoclean> is automatically used in all classes.
352              
353             Between the class declaration and its body, L<Attribute::Handlers>-style
354             attributes may be provided:
355              
356             class Person :mutable {
357             # ...
358             }
359            
360             class Employee extends Person with Employment :mutable;
361              
362             The following attributes are defined for classes:
363              
364             =over
365              
366             =item *
367              
368             C<< :assertions >> - enables assertion checking (see below)
369              
370             =item *
371              
372             C<< :dirty >> - suppresses namespace::autoclean
373              
374             =item *
375              
376             C<< :fp >> - use L<Function::Parameters> instead of L<Kavorka>
377              
378             =item *
379              
380             C<< :mutable >> - suppresses making Moose classes immutable
381              
382             =item *
383              
384             C<< :ro >> - make attributes declared with C<has> default to 'ro'
385              
386             =item *
387              
388             C<< :rw >> - make attributes declared with C<has> default to 'rw'
389              
390             =item *
391              
392             C<< :rwp >> - make attributes declared with C<has> default to 'rwp'
393              
394             =back
395              
396             =head2 Roles
397              
398             Roles can be declared similarly to classes, but using the C<role> keyword.
399              
400             role Stringable
401             using Moose # we know you meant Moose::Role
402             {
403             # ...
404             }
405              
406             Roles do not support the C<extends> option.
407              
408             Roles can be declared to be C<< using >> Moo, Moose, Mouse or Tiny.
409             (Note that if you're mixing and matching role frameworks, there are
410             limitations to which class builders can consume which roles. Mouse
411             is generally the least compatible; Moo and Moose classes should be
412             able to consume each others' roles; Moo can also consume Role::Tiny
413             roles.)
414              
415             If roles use Moo, the L<MooX::late> extension is enabled.
416              
417             L<namespace::autoclean> is automatically used in all roles.
418              
419             Roles take similar L<Attribute::Handlers>-style attributes to
420             classes, but don't support C<< :mutable >>.
421              
422             =head3 A note on consuming roles
423              
424             In a standard:
425              
426             class MyClass with MyRole {
427             ...;
428             }
429              
430             You should note that role composition is delayed to happen at the
431             I<end> of the class declaration. This is usually what you want.
432              
433             However the interaction between method modifiers and roles is
434             complex, and I<sometimes> you'll want the role to be applied to
435             the class part-way through the declaration. In this case you can
436             use a C<with> statement I<inside> the class declaration:
437              
438             class MyClass {
439             ...;
440             with "MyRole";
441             ...;
442             }
443              
444             =head2 Namespaces
445              
446             The C<namespace> keyword works as above, but declares a package without
447             any class-specific or role-specific semantics.
448              
449             namespace Utils {
450             # ...
451             }
452              
453             L<namespace::autoclean> is not automatically used in namespaces.
454              
455             L<Attribute::Handlers>-style attributes are supported for namespaces,
456             but most of the built-in attributes make any sense without class/role
457             semantics. (C<< :assertions >> does.) Traits written as Moops extensions
458             may support namespaces.
459              
460             =head2 Functions and Methods
461              
462             Moops uses L<Kavorka> to declare functions and methods within classes
463             and roles. Kavorka provides the C<fun> and C<method> keywords.
464              
465             class Person {
466             use Scalar::Util 'refaddr';
467            
468             has name => (is => 'rwp'); # Moo attribute
469            
470             method change_name ( Str $newname ) {
471             $self->_set_name( $newname )
472             unless $newname eq 'Princess Consuela Banana-Hammock';
473             }
474            
475             fun is_same_as ( Object $x, Object $y ) {
476             refaddr($x) == refaddr($y)
477             }
478             }
479            
480             my $phoebe = Person->new(name => 'Phoebe');
481             my $ursula = Person->new(name => 'Ursula');
482            
483             Person::is_same_as($phoebe, $ursula); # false
484              
485             Note function signatures use type constraints from L<Types::Standard>;
486             L<MooseX::Types> and L<MouseX::Types> type constraints should also
487             work, I<< provided you use their full names, including their package >>.
488              
489             The C<is_same_as> function above could have been written as a class
490             method like this:
491              
492             class Person {
493             # ...
494             method is_same_as ( $class: Object $x, Object $y ) {
495             refaddr($x) == refaddr($y)
496             }
497             }
498            
499             # ...
500             Person->is_same_as($phoebe, $ursula); # false
501              
502             The C<method> keyword is not provided within packages declared using
503             C<namespace>; only within classes and roles.
504              
505             See also L<Kavorka::Manual::Methods> and L<Kavorka::Manual::Functions>.
506              
507             Within Moose classes and roles, the L<MooseX::KavorkaInfo> module is
508             loaded, to allow access to method signatures via the meta object
509             protocol. (This is currently broken for C<around> method modifiers.)
510              
511             In Moops prior to 0.025, L<Function::Parameters> was used instead of
512             Kavorka. If you wish to continue to use Function::Parameters in a class
513             you can use the C<< :fp >> attribute:
514              
515             class Person :fp {
516             ...;
517             }
518              
519             Or to do so for all classes in a lexical scope:
520              
521             use Moops function_parameters_everywhere => 1;
522             class Person {
523             ...;
524             }
525              
526             Or the environment variable C<MOOPS_FUNCTION_PARAMETERS_EVERYWHERE> can
527             be set to true to enable it globally, but this feature is likely to be
528             removed eventually.
529              
530             =head2 Method Modifiers
531              
532             Within classes and roles, C<before>, C<after> and C<around> keywords
533             are provided for declaring method modifiers. These use the same syntax
534             as C<method>.
535              
536             If your class or role is using Moose or Mouse, then you also get
537             C<augment> and C<override> keywords.
538              
539             See also L<Kavorka::Manual::MethodModifiers>.
540              
541             =head2 Multi Methods
542              
543             L<Moops> uses L<Kavorka> to implement multi subs and multi methods.
544              
545             See also L<Kavorka::Manual::MultiSubs>.
546              
547             =head2 Type Constraints
548              
549             The L<Types::Standard> type constraints are exported to each package
550             declared using Moops. This allows the standard type constraints to be
551             used as barewords.
552              
553             Type constraints can be used in attribute definitions (C<isa>) and
554             method signatures. Because Types::Standard is based on L<Type::Tiny>,
555             the same type constraints may be used whether you build your classes
556             and roles with Moo, Moose our Mouse.
557              
558             Alternative libraries can be imported using the C<types> option; a la:
559              
560             class Document types Types::XSD::Lite {
561             has title => (is => 'rw', isa => NormalizedString);
562             }
563              
564             Note that if an alternative type constraint library is imported, then
565             L<Types::Standard> is I<not> automatically loaded, and needs to be
566             listed explicitly:
567              
568             class Document types Types::Standard, Types::XSD::Lite {
569             # ...
570             }
571              
572             Type libraries built with L<Type::Library>, L<MooseX::Types> and
573             L<MouseX::Types> should all work.
574              
575             Bear in mind that type constraints from, say, a L<MooseX::Types>
576             library won't be usable in, say, Moo attribute definitions. However,
577             it's possible to wrap them with Type::Tiny, and make them usable:
578              
579             class Foo types MooseX::Types::Common::Numeric using Moo {
580             use Types::TypeTiny qw( to_TypeTiny );
581            
582             has favourite_number => (
583             is => 'rwp',
584             isa => to_TypeTiny(PositiveInt)
585             );
586             }
587              
588             =head2 Type Libraries
589              
590             You can use the C<library> keyword to declare a new type library:
591              
592             library MyTypes
593             extends Types::Standard
594             declares EmptyString, NonEmptyString {
595            
596             declare EmptyString,
597             as Str,
598             where { length($_) == 0 };
599            
600             declare NonEmptyString,
601             as Str,
602             where { length($_) > 0 };
603             }
604            
605             class StringChecker types MyTypes {
606             method check ( Str $foo ) {
607             return "empty" if EmptyString->check($foo);
608             return "non-empty" if NonEmptyString->check($foo);
609             return "impossible?!";
610             }
611             }
612              
613             Libraries declared this way can extend existing type libraries
614             written with L<Type::Library>, L<MooseX::Types> or L<MouseX::Types>.
615              
616             Note that this also provides a solution to the previously mentioned
617             problem of using L<MooseX::Types> type libraries in L<Moo> classes:
618              
619             library MyWrapper
620             extends MooseX::Types::Common::Numeric;
621            
622             class Foo types MyWrapper using Moo {
623             has favourite_number => (
624             is => 'rwp',
625             isa => PositiveInt,
626             );
627             }
628              
629             =head2 Constants
630              
631             The useful constants C<true> and C<false> are imported into all declared
632             packages. (Within classes and roles, namespace::autoclean will later remove
633             them from the symbol table, so they don't form part of your package's API.)
634             These constants can help make attribute declarations more readable.
635              
636             has name => (is => 'ro', isa => Str, required => true);
637              
638             Further constants can be declared using the C<define> keyword (see
639             L<PerlX::Define>):
640              
641             namespace Maths {
642             define PI = 3.2;
643             }
644              
645             Constants declared this way will I<not> be swept away by namespace::autoclean,
646             and are considered part of your package's API.
647              
648             =head2 Assertions
649              
650             Declared packages can contain assertions (see L<PerlX::Assert>). These
651             are normally optimized away at compile time, but you can force them to
652             be checked using the C<< :assertions >> attribute.
653              
654             class Foo {
655             assert(false); # not checked; optimized away
656             }
657            
658             class Bar :assertions {
659             assert(false); # checked; fails; throws exception
660             }
661              
662             =head2 More Sugar
663              
664             L<strict> and FATAL L<warnings> are imported into all declared packages.
665             However the C<uninitialized>, C<void>, C<once> and C<numeric> warning
666             categories are explicitly excluded, as are any warnings categories added
667             to Perl after version 5.14.
668              
669             Perl 5.14 features, including the C<state> and C<say> keywords,
670             and sane Unicode string handling are imported into all declared
671             packages.
672              
673             L<Try::Tiny> is imported into all declared packages.
674              
675             L<Scalar::Util>'s C<blessed> and L<Carp>'s C<confess> are imported
676             into all declared packages.
677              
678             =head2 Outer Sugar
679              
680             The "outer" package, where the C<< use Moops >> statement appears also
681             gets a little sugar: strict, the same warnings as "inner" packages, and
682             Perl 5.14 features are all switched on.
683              
684             L<true> is loaded, so you don't need to do this at the end of your
685             file:
686              
687             1;
688            
689              
690             =head2 Custom Sugar
691              
692             It is possible to inject other functions into all inner packages using:
693              
694             use Moops imports => [
695             'List::Util' => [qw( first reduce )],
696             'List::MoreUtils' => [qw( any all none )],
697             ];
698              
699             This is by far the easiest way to extend Moops with project-specific
700             extras.
701              
702             There is a shortcut for injecting L<strictures> into all inner packages:
703              
704             use Moops -strict;
705              
706             =head1 EXTENDING
707              
708             Moops is written to hopefully be fairly extensible.
709              
710             =head2 Extending Moops via imports
711              
712             The easiest way to extend Moops is to inject additional imports into
713             the inner packages using the technique outlined in L</Custom Sugar>
714             above. You can wrap all that up in a module:
715              
716             package MoopsX::Lists;
717             use base 'Moops';
718             use List::Util ();
719             use List::MoreUtils ();
720            
721             sub import {
722             my ($class, %opts) = @_;
723            
724             push @{ $opts{imports} ||= [] }, (
725             'List::Util' => [qw( first reduce )],
726             'List::MoreUtils' => [qw( any all none )],
727             );
728            
729             $class->SUPER::import(%opts);
730             }
731            
732             1;
733              
734             Now people can do C<< use MoopsX::Lists >> instead of C<< use Moops >>.
735              
736             =head2 Extending Moops via keyword traits
737              
738             Roles in the C<Moops::TraitFor::Keyword> namespace are automatically
739             loaded and applied to keyword objects when a corresponding
740             Attribute::Handlers-style attribute is seen.
741              
742             For examples extending Moops this way, see the
743             L<Moops::TraitFor::Keyword::dirty>,
744             L<Moops::TraitFor::Keyword::mutable>,
745             L<Moops::TraitFor::Keyword::ro>,
746             L<Moops::TraitFor::Keyword::rw> and
747             L<Moops::TraitFor::Keyword::rwp> traits.
748              
749             =head2 Extending Moops via parser traits
750              
751             For more complex needs, you can create a trait which will be applied to
752             Moops::Parser.
753              
754             Parser traits might want to override:
755              
756             =over
757              
758             =item *
759              
760             The C<keywords> class method, which returns the list of keywords
761             the parser can handle.
762              
763             =item *
764              
765             The C<class_for_keyword> object method, which returns the name of
766             a subclass of Moops::Keyword which will be used for translating
767             the result of parsing the keyword into a string using Perl's built-in
768             syntax.
769              
770             =back
771              
772             Hopefully you'll be able to avoid overriding the C<parse>
773             method itself, as it has a slightly messy API.
774              
775             Your C<class_for_keyword> subclass can either be a direct subclass of
776             Moops::Keyword, or of Moops::Keyword::Class or Moops::Keyword::Role.
777              
778             The keyword subclass might want to override:
779              
780             =over
781              
782             =item *
783              
784             The C<known_relationships> class method, which returns a list of valid
785             inter-package relationships such as C<extends> and C<using> for the
786             current keyword.
787              
788             =item *
789              
790             The C<qualify_relationship> class method, which, when given the name of
791             an inter-package relationship, indicates whether it should be subjected
792             to package qualification rules (like C<extends> and C<with> are, but
793             C<using> is not).
794              
795             =item *
796              
797             The C<version_relationship> class method, which, when given the name of
798             an inter-package relationship, indicates whether it should accept a version
799             number.
800              
801             =item *
802              
803             The C<generate_package_setup> object method which returns a list of
804             strings to inject into the package.
805              
806             =item *
807              
808             The C<arguments_for_function_parameters> object method which is used
809             by the default C<generate_package_setup> method to set up the arguments
810             to be passed to L<Function::Parameters>.
811              
812             =item *
813              
814             The C<check_prerequisites> method which performs certain pre-flight checks
815             and may throw an exception.
816              
817             =back
818              
819             Hopefully you'll be able to avoid overriding the C<generate_code>
820             method.
821              
822             You can apply your trait using:
823              
824             use Moops traits => [
825             'Moops::TraitFor::Parser::FooKeyword',
826             'Moops::TraitFor::Parser::BarKeyword',
827             ];
828              
829             =head1 BUGS
830              
831             If seeing test failures on threaded Perl 5.21+, it may be a bug in
832             L<Devel::CallParser> 0.002.
833             Try installing L<Alt::Devel::CallParser::ButWorking>.
834              
835             Please report any other bugs to
836             L<http://rt.cpan.org/Dist/Display.html?Queue=Moops>.
837              
838             =head1 SUPPORT
839              
840             B<< IRC: >> support is available through in the I<< #moops >> channel
841             on L<irc.perl.org|http://www.irc.perl.org/channels.html>.
842              
843             For general Moose/Moo queries which don't seem to be related to Moops'
844             syntactic sugar, your question may be answered more quickly in the
845             I<< #moose >> channel.
846              
847             B<< Web: >> if you ask a question on PerlMonks in
848             L<Seekers of Perl Wisdom|http://www.perlmonks.org/?node_id=479> with
849             "Moops" in the subject line, it should be answered pretty quickly.
850              
851             There is a L<moops tag|http://stackoverflow.com/questions/tagged/moops>
852             on StackOverflow.
853              
854             =head1 SEE ALSO
855              
856             Similar:
857             L<MooseX::Declare>,
858             L<https://github.com/stevan/p5-mop-redux>.
859              
860             Main functionality exposed by this module:
861             L<Moo>/L<MooX::late>, L<Kavorka>, L<Try::Tiny>, L<Types::Standard>,
862             L<namespace::autoclean>, L<true>, L<PerlX::Assert>.
863              
864             Internals fueled by:
865             L<Keyword::Simple>, L<Module::Runtime>, L<Import::Into>,
866             L<Attribute::Handlers>.
867              
868             L<http://en.wikipedia.org/wiki/The_Bubble_Boy_(Seinfeld)>.
869              
870             =head1 AUTHOR
871              
872             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
873              
874             =head1 COPYRIGHT AND LICENCE
875              
876             This software is copyright (c) 2013-2014 by Toby Inkster.
877              
878             This is free software; you can redistribute it and/or modify it under
879             the same terms as the Perl 5 programming language system itself.
880              
881             =head1 DISCLAIMER OF WARRANTIES
882              
883             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
884             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
885             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
886