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