File Coverage

blib/lib/Fukurama/Class/Attributes/OOStandard/DefinitionCheck.pm
Criterion Covered Total %
statement 284 318 89.3
branch 71 118 60.1
condition 24 42 57.1
subroutine 31 32 96.8
pod 12 12 100.0
total 422 522 80.8


line stmt bran cond sub pod time code
1             package Fukurama::Class::Attributes::OOStandard::DefinitionCheck;
2 4     4   24 use Fukurama::Class::Version(0.03);
  4         13  
  4         24  
3 4     4   20 use Fukurama::Class::Rigid;
  4         9  
  4         25  
4 4     4   24 use Fukurama::Class::Carp;
  4         6  
  4         29  
5 4     4   2368 use Fukurama::Class::DataTypes();
  4         13  
  4         104  
6 4     4   2734 use Fukurama::Class::Attributes::OOStandard::Decorator();
  4         12  
  4         68  
7 4     4   6638 use Data::Dumper();
  4         44491  
  4         121  
8 4     4   43 use Fukurama::Class::Tree();
  4         9  
  4         87  
9 4     4   2839 use Fukurama::Class::Attributes::OOStandard::InheritationCheck();
  4         14  
  4         18059  
10              
11             my $DATATYPES = 'Fukurama::Class::DataTypes';
12             my $DECORATOR = 'Fukurama::Class::Attributes::OOStandard::Decorator';
13             my $WHITESPACES = qr/(?:[ \t\n\r]*,[ \t\n\r]*|[ \t\n\r]+)/;
14             my $SPLIT_TYPE = qr/^(.*?)((?:\[\]|\(\))*)$/;
15             my $SPLIT_PART = qr/\|/;
16             my $SPLIT_SUBPART = qr/[\@;]/;
17             my $DEF_ERROR = undef;
18             my $ATT_TYPE = undef;
19             my $REGISTER = {};
20              
21             my $ACCESS_LEVEL = {
22             public => 1,
23             protected => 2,
24             private => 3,
25             };
26             my $ACCESS_LEVEL_TYPE = {# ENUM('', 'unoverwritable')
27             public => '',
28             protected => '',
29             private => '',
30             };
31             my $STATIC = {
32             static => 1,
33             '' => 1,
34             };
35             my $TYPE = {
36             abstract => 'overwrite',
37             '' => 'normal',
38             final => 'unoverwritable',
39             };
40              
41             =head1 NAME
42              
43             Fukurama::Class::Attributes::OOStandard::DefinitionCheck - Helper-class to check syntax of code attributes
44              
45             =head1 VERSION
46              
47             Version 0.03 (beta)
48              
49             =head1 SYNOPSIS
50              
51             - (its only a collection of methods, it's unusable outside of it's own context :)
52              
53             =head1 DESCRIPTION
54              
55             A Helper class for Fukurama::Class::Attributes::OOStandard to check code attribute syntax.
56              
57             =head1 EXPORT
58              
59             -
60              
61             =head1 METHODS
62              
63             =over 4
64              
65             =item get_translated_def( sub_data:\HASH, def:\HASH, sub_def:\ARRAY, result_def:\ARRAY,
66             array_result_def:\ARRAY, para_def:\ARRAY, opt_para_def:\ARRAY) return:\HASH
67            
68             Translate the given attribute data (e.g. static|void|string) into an wellformed hash which contain
69             all definitions include implizit definitions.
70              
71             =item set_type( type:STRING ) return:VOID
72              
73             Set the type-name of the actual checked code attribute. It's only for error messages.
74              
75             =item throw_def_error( sub_data:\HASH, msg:STRING) return:VOID
76              
77             Died with the given message and output some detailed informations about the involved method(s).
78              
79             =item resolve_def( sub_data:\HASH ) return:VOID
80              
81             Resolved the method name from a given subroutine code reference.
82              
83             =item try_check_translated_def( sub_data:\HASH, translated_def:\HASH, def:\HASH ) return:VOID
84              
85             Check all defintions of the given code attribute declaration.
86              
87             =item decorate_sub( def:\HASH ) return:VOID
88              
89             Decorates subroutines with a check method to check parameter and return values.
90              
91             =item try_check_parameter( id:STRING, io_list:\ARRAY ) return:VOID
92              
93             Check the content of the parameter list for a subroutine.
94              
95             =item try_check_result( id:SRING, io_list:\ARRAY, list_context:BOOLEAN ) return:VOID
96              
97             Check the content of the return value(s) for a subroutine.
98              
99             =item try_check_abstract( id:STRING ) return:VOID
100              
101             Check the caller of a subroutine, to avoid directly called, abstract methods.
102              
103             =item try_check_access( id:STRING ) return:VOID
104              
105             Check the caller of a subroutine, to avoid unauthorized calls for e.g. private methods from outside the own class.
106              
107             =item try_check_call( id:STRING, class_parameter:SCALAR ) return:VOID
108              
109             Check the first argument of the method for static or nonstatic calls and the correct usage.
110              
111             =item check_inheritation( method_name:STRING, parent_class:CLASS, child_class:CLASS, inheritation_type:STRING ) return:VOID
112              
113             Check the inheritations of all defined declarations to avoid differend method signatures for parent and child.
114              
115             =back
116              
117             =head1 AUTHOR, BUGS, SUPPORT, ACKNOWLEDGEMENTS, COPYRIGHT & LICENSE
118              
119             see perldoc of L
120              
121             =cut
122              
123              
124             # STATIC boolean
125             sub get_translated_def {
126 27     27 1 41 my $class = $_[0];
127 27         36 my $sub_data = $_[1];
128 27         32 my $def = $_[2];
129 27         36 my $sub_def = $_[3];
130 27         27 my $result_def = $_[4];
131 27         34 my $array_result_def = $_[5];
132 27         33 my $para_def = $_[6];
133 27         29 my $opt_para_def = $_[7];
134            
135 27         90 my $access_level = $class->_extract_access_level_def($sub_def, $sub_data->{'sub_name'});
136 27         81 $class->_try_check_access_level_def($sub_data, $access_level);
137            
138 27         69 my $static = $class->_extract_static_def($sub_def);
139 27         102 $class->_try_check_static_def($sub_data, $static);
140            
141 27         73 my $type = $class->_extract_type_def($sub_def);
142 27         79 $class->_try_check_type_def($sub_data, $type);
143              
144 27         74 my $result = $class->_extract_io_def($result_def);
145 27         93 $class->_try_check_io_def($sub_data, $result, '$return value', []);
146 27 50       76 if(scalar(@$result) != 1) {
147 0         0 $class->throw_def_error($sub_data, "\$return value definition must contain exact 1 element but is " . scalar(@$result) . " elements long.");
148             }
149 27 50       71 if($result->[0]->{'ref'} eq '()') {
150 0         0 $class->throw_def_error($sub_data, "\$return value '$result->[0]->{'type'}$result->[0]->{'ref'}' is not allowed. You can't use () in scalar context.");
151             }
152            
153 27         72 my $array_result = $class->_extract_io_def($array_result_def);
154 27 100       60 if(@$array_result) {
155 5         19 $class->_try_check_io_def($sub_data, $array_result, '@return value', [qw/void/]);
156 5         23 $class->_try_check_list_result($sub_data, [@$array_result]);
157             }
158            
159 27         68 my $para = $class->_extract_io_def($para_def);
160 27         102 $class->_try_check_io_def($sub_data, $para, 'parameter', [qw/void/]);
161            
162 27         86 my $opt_para = $class->_extract_io_def($opt_para_def);
163 27         89 $class->_try_check_io_def($sub_data, $opt_para, 'optional parameter', [qw/void/]);
164            
165 27         115 $class->_try_check_list_parameter($sub_data, [@$para, @$opt_para], scalar(@$para));
166              
167             return {
168 27         272 access_level => $access_level,
169             static => $static,
170             type => $type,
171             result => $result,
172             array_result => $array_result,
173             para => $para,
174             opt_para => $opt_para,
175             sub_data => $sub_data,
176             };
177             }
178             # STATIC void
179             sub _try_check_list_result {
180 5     5   12 my $class = $_[0];
181 5         7 my $sub_data = $_[1];
182 5         5 my $list = $_[2];
183            
184 5         8 my $last_element = pop(@$list);
185 5         7 my $i = 0;
186 5         11 foreach my $entry (@$list) {
187 0 0       0 if($entry->{'ref'} eq '()') {
188 0         0 $class->throw_def_error($sub_data, "\@result $i '$entry->{'type'}$entry->{'ref'}' is not allowed. You can use () only as last element.");
189             }
190 0         0 ++$i;
191             }
192 5         10 return;
193             }
194             # STATIC void
195             sub _try_check_list_parameter {
196 27     27   35 my $class = $_[0];
197 27         37 my $sub_data = $_[1];
198 27         30 my $list = $_[2];
199 27         30 my $needed_length = $_[3];
200            
201 27         34 my $last_element = pop(@$list);
202 27         35 my $i = 0;
203 27         50 foreach my $entry (@$list) {
204 11 50       20 if($entry->{'ref'} eq '()') {
205 0 0       0 my $name = ($i > $needed_length ? 'optional parameter' : 'parameter');
206 0         0 $class->throw_def_error($sub_data, "$name $i '$entry->{'type'}$entry->{'ref'}' is not allowed. You can use () only as last element.");
207             }
208 11         15 ++$i;
209             }
210 27         48 return;
211             }
212             # STATIC void
213             sub set_type {
214 27     27 1 56 my $class = $_[0];
215 27         41 my $type = $_[1];
216            
217 27         33 $ATT_TYPE = $type;
218             return:
219 27         58 }
220             # STATIC void
221             sub throw_def_error {
222 0     0 1 0 my $class = $_[0];
223 0         0 my $sub_data = $_[1];
224 0         0 my $msg = $_[2];
225            
226 0 0       0 my $type = (defined($ATT_TYPE) ? " $ATT_TYPE": '');
227 0 0       0 if($DEF_ERROR) {
228 0         0 $DEF_ERROR = "Last error thrown twice";
229             } else {
230 0         0 $DEF_ERROR = "Error in$type declaration:\n $sub_data->{'class'}\->$sub_data->{'sub_name'}($sub_data->{'data'})\n> $msg\n\n";
231             }
232 0         0 _croak($DEF_ERROR);
233 0         0 return;
234             }
235             # STATIC array[]
236             sub resolve_def {
237 27     27 1 42 my $class = $_[0];
238 27         32 my $sub_data = $_[1];
239            
240 27         44 my @data = ();
241 27         152 foreach my $part (split($SPLIT_PART, $sub_data->{'data'})) {
242 56         79 my @subdata = ();
243 56         244 foreach my $subpart (split($SPLIT_SUBPART, $part . ' ')) {
244 65         86 my @entry = ();
245 65         385 foreach my $entry (split($WHITESPACES, $subpart)) {
246 78         537 my ($type, $ref) = $entry =~ $SPLIT_TYPE;
247 78         356 push(@entry, {
248             data => $type,
249             type => $ref,
250             });
251             }
252 65 100 66     603 if($subpart =~ m/,$/ || $subpart =~ m/^$WHITESPACES$/) {
253 3         19 push(@entry, {
254             data => '',
255             type => '',
256             });
257             }
258 65         221 push(@subdata, \@entry);
259             }
260 56         166 push(@data, \@subdata);
261             }
262 27         95 return \@data;
263             }
264             # STATIC string
265             sub _extract_access_level_def {
266 27     27   44 my $class = $_[0];
267 27         36 my $sub_def = $_[1];
268 27         29 my $sub_name = $_[2];
269            
270 27         39 my $access_level = {};
271 27         59 foreach my $entry (@$sub_def) {
272 39 100       120 if($ACCESS_LEVEL->{$entry->{'data'}}) {
273 18 50       48 return undef if($access_level->{$entry->{'data'}});
274 18         60 $access_level->{$entry->{'data'}} = 1;
275             }
276             }
277            
278 27 100       96 if($sub_name =~ /^_/) {
279 7 50       20 return undef if($access_level->{'public'});
280 7 50 66     40 $access_level->{'protected'} = 1 if(!$access_level->{'protected'} && !$access_level->{'private'});
281            
282             } else {
283 20 50 33     156 return undef if($access_level->{'protected'} || $access_level->{'private'});
284 20         52 $access_level->{'public'} = 1;
285             }
286            
287            
288 27         94 my @access_level = keys(%$access_level);
289 27 50       75 return undef if(scalar(@access_level) != 1);
290 27         97 return $access_level[0];
291             }
292             # STATIC void
293             sub _try_check_access_level_def {
294 27     27   36 my $class = $_[0];
295 27         36 my $sub_data = $_[1];
296 27         31 my $access_level = $_[2];
297              
298 27 50 33     109 $class->throw_def_error($sub_data, 'access level declaration is wrong. Maybe a conflict between sub name and declared access level.') if(!defined($access_level) || !$ACCESS_LEVEL->{$access_level});
299 27         51 return;
300             }
301             # STATIC string
302             sub _extract_static_def {
303 27     27   35 my $class = $_[0];
304 27         29 my $sub_def = $_[1];
305            
306 27         46 my $static = {};
307 27         48 foreach my $entry (@$sub_def) {
308 39 100       113 if($STATIC->{$entry->{'data'}}) {
309 20 50       48 return undef if($static->{$entry->{'data'}});
310 20         72 $static->{$entry->{'data'}} = 1;
311             }
312             }
313 27         81 my @static = keys(%$static);
314 27 50       67 return undef if(scalar(@static) > 1);
315 27   100     118 return $static[0] || '';
316             }
317             # STATIC void
318             sub _try_check_static_def {
319 27     27   50 my $class = $_[0];
320 27         37 my $sub_data = $_[1];
321 27         33 my $static = $_[2];
322            
323 27 50 33     110 $class->throw_def_error($sub_data, 'static declaration is wrong') if(!defined($static) || !$STATIC->{$static});
324 27         44 return;
325             }
326             # STATIC string[]
327             sub _extract_type_def {
328 27     27   36 my $class = $_[0];
329 27         35 my $sub_def = $_[1];
330            
331 27         44 my $type = {};
332 27         50 foreach my $entry (@$sub_def) {
333 39 100       117 if($TYPE->{$entry->{'data'}}) {
334 1 50       5 return undef if($type->{$entry->{'data'}});
335 1         9 $type->{$entry->{'data'}} = 1;
336             }
337             }
338            
339 27         65 my @type = keys(%$type);
340 27 50       57 return undef if(scalar(@type) > 1);
341 27   100     136 return $type[0] || '';
342             }
343             # STATIC void
344             sub _try_check_type_def {
345 27     27   32 my $class = $_[0];
346 27         35 my $sub_data = $_[1];
347 27         34 my $type = $_[2];
348            
349 27 50 33     129 $class->throw_def_error($sub_data, 'type declaration is not allowed') if(!defined($type) || !$TYPE->{$type});
350 27         49 return;
351             }
352             # STATIC string[]
353             sub _extract_io_def {
354 108     108   133 my $class = $_[0];
355 108         128 my $io_def = $_[1];
356            
357 108         162 my $io = [];
358 108         201 foreach my $entry (@$io_def) {
359 54         232 push(@$io, {
360             type => $entry->{'data'},
361             ref => $entry->{'type'},
362             check => $DATATYPES->get_check_definition($entry->{'data'}, $entry->{'type'}),
363             });
364             }
365 108         462 return $io;
366             }
367             # STATIC void
368             sub _try_check_io_def {
369 86     86   111 my $class = $_[0];
370 86         98 my $sub_data = $_[1];
371 86         84 my $io = $_[2];
372 86         89 my $name = $_[3];
373 86         104 my $forbidden_types = $_[4];
374            
375 86         160 foreach my $entry (@$io) {
376 54 50       179 if(!$DATATYPES->is_ref_allowed($entry->{'ref'})) {
377 0         0 $class->throw_def_error($sub_data, "$name definition '$entry->{'type'}$entry->{'ref'}' is not allowed");
378             }
379 54         73 my $error = 0;
380 54         87 foreach my $type (@$forbidden_types) {
381 27 50       77 $error = 1 if($entry->{'type'} eq $type);
382             }
383 54 50 33     251 if($error || !$DATATYPES->check_parameter_definition($entry->{'type'}, $entry->{'check'})) {
384 0 0       0 if($entry->{'check'}->{'is_class'}) {
385 0         0 $class->throw_def_error(
386             $sub_data,
387             "$name '$entry->{'type'}$entry->{'ref'}' is wrong. This class is not loaded or doesn't exist."
388             );
389             } else {
390 0         0 $class->throw_def_error(
391             $sub_data,
392             "$name '$entry->{'type'}$entry->{'ref'}' is not allowed."
393             );
394             }
395             }
396             }
397             }
398             # STATIC void
399             sub try_check_translated_def {
400 27     27 1 38 my $class = $_[0];
401 27         37 my $sub_data = $_[1];
402 27         30 my $translated_def = $_[2];
403 27         42 my $def = $_[3];
404            
405 27         53 my $def_keys = {};
406 27         35 foreach my $entry (@{$def->[0]->[0]}) {
  27         70  
407 39         134 $def_keys->{$entry->{'data'}} = 1;
408             }
409            
410 27         104 foreach my $key (values(%$translated_def)) {
411 216         388 delete($def_keys->{$key});
412             }
413            
414 27         70 my @forbidden_keys = keys(%$def_keys);
415 27 50       66 if(@forbidden_keys) {
416 0         0 my $keys = join(', ', @forbidden_keys);
417 0         0 $class->throw_def_error($sub_data, "forbidden key(s): '$keys' used in declaration");
418             }
419 27         91 return;
420             }
421             # STATIC void
422             sub decorate_sub {
423 27     27 1 41 my $class = $_[0];
424 27         34 my $def = $_[1];
425            
426 27         47 my $sub_data = $def->{'sub_data'};
427 27         38 my $old = $sub_data->{'sub'};
428 27         71 my $identifier = $sub_data->{'class'} . '::' . $sub_data->{'sub_name'};
429              
430 27 50       65 $DECORATOR->remove_decoration($identifier, $old) if($REGISTER->{$identifier});
431 27         122 $DECORATOR->decorate($identifier, $old, __PACKAGE__);
432 27         72 $REGISTER->{$identifier} = $def;
433 27         67 return;
434             }
435             # STATIC void
436             sub try_check_parameter {
437 13     13 1 23 my $class = $_[0];
438 13         13 my $id = $_[1];
439 13         19 my $io_list = $_[2];
440            
441 13         22 my $def = $REGISTER->{$id};
442 13 50       27 _croak("Internal error:\n sub $id() has no definition\n\n") if(!$def);
443            
444 13         17 my $io_def_list = [@{$def->{'para'}}, @{$def->{'opt_para'}}];
  13         25  
  13         29  
445 13         22 my $length = scalar(@$io_def_list);
446 13         14 my $needed_length = scalar(@{$def->{'para'}});
  13         21  
447 13         18 my $given_length = scalar(@$io_list);
448            
449 13 50       32 $length = $given_length if($given_length >= $needed_length);
450 13         41 $class->_try_check_io($io_def_list, $io_list, $length, $def, 'parameter');
451 12         35 return;
452             }
453             # STATIC void
454             sub try_check_result {
455 10     10 1 18 my $class = $_[0];
456 10         13 my $id = $_[1];
457 10         13 my $io_list = $_[2];
458 10         13 my $list_context = $_[3];
459            
460 10         25 my $def = $REGISTER->{$id};
461 10 50       26 _croak("Internal error:\n sub $id() has no definition\n\n") if(!$def);
462            
463 10         13 my $io_type = undef;
464 10         12 my $io_def_list = undef;
465 10 100 100     30 if($list_context && scalar(@{$def->{'array_result'}})) {
  2         6  
466 2         3 $io_def_list = [@{$def->{'array_result'}}];
  2         5  
467 2         4 $io_type = 'listcontext result';
468             } else {
469 8         13 $io_def_list = [@{$def->{'result'}}];
  8         23  
470 8         14 $io_type = 'result';
471             }
472            
473            
474 10         16 my $length = scalar(@$io_def_list);
475 10         14 my $needed_length = $length;
476 10         13 my $given_length = scalar(@$io_list);
477            
478 10 100       25 $length = $given_length if($given_length > $needed_length);
479 10         31 $class->_try_check_io($io_def_list, $io_list, $length, $def, $io_type);
480 9         30 return;
481             }
482             # STATIC void
483             sub _try_check_io {
484 23     23   29 my $class = $_[0];
485 23         28 my $io_def_list = $_[1];
486 23         38 my $io_list = $_[2];
487 23         33 my $length = $_[3];
488 23         25 my $def = $_[4];
489 23         28 my $io_type = $_[5];
490            
491 23         30 my $errors = [];
492 23         61 for(my $i = 0; $i < $length; $i++) {
493 22         35 my $pdef = $io_def_list->[$i];
494 22         33 my $entry = $io_list->[$i];
495 22 100       53 if(!ref($pdef)) {
496 1         2 my $defined = '';
497 1 50       4 if(!defined($entry)) {
498 0         0 $defined = ' (undefined)';
499 0         0 $entry = '';
500             }
501 1         14 push(@$errors, "Error in $io_type " . ($i + 1) .
502             ":\n $def->{'sub_data'}->{'class'}->$def->{'sub_data'}->{'sub_name'}($def->{'sub_data'}->{'data'})\n" .
503             "> no further $io_type expected, only " . scalar(@$io_def_list) . " is/are allowed.\n" .
504             "> extra $io_type '$entry'$defined given\n\n");
505 1         5 next;
506             }
507 21         30 my $old_entry = $entry;
508 21         59 (my $is_ok, $entry, my $error_msg) = &{$pdef->{'check'}->{'check'}}($pdef->{'check'}->{'param_0'}, $entry, $pdef->{'type'}, \$i, $io_list);
  21         80  
509 21 100       94 if(!$is_ok) {
510 1         1 my $defined = '';
511 1 50 33     10 if(!defined($old_entry) || !defined($entry)) {
    50          
512 0 0       0 $defined = ' (undefined)' if(!defined($old_entry));
513 0         0 $entry = '';
514             } elsif(ref($entry) eq 'ARRAY') {
515 0         0 local $Data::Dumper::Maxdepth = 1;
516 0         0 $entry = Data::Dumper::Dumper($entry);
517 0         0 $entry =~ s/^[^\[]*//;
518 0         0 $entry =~ s/[^\]]*$//;
519             }
520 1 50       4 my $class = ($pdef->{'check'}->{'is_class'} ? ' class (or child of)' : '');
521 1 50       4 $class = 'Any kind of a' if($pdef->{'type'} eq 'class');
522 1 50       3 my $extended_msg = (defined($error_msg) ? " ($error_msg)" : '');
523 1         11 push(@$errors, "Error in $io_type " . ($i + 1) .
524             ":\n $def->{'sub_data'}->{'class'}->$def->{'sub_data'}->{'sub_name'}($def->{'sub_data'}->{'data'})\n" .
525             "> $class '$pdef->{'type'}$pdef->{'ref'}' expected but '$entry'$defined given$extended_msg.\n\n");
526 1         9 next;
527             }
528             }
529 23 100       60 _croak(join('', @$errors)) if(@$errors);
530 21         46 return;
531             }
532             # STATIC void
533             sub try_check_abstract {
534 13     13 1 20 my $class = $_[0];
535 13         22 my $id = $_[1];
536            
537 13         21 my $def = $REGISTER->{$id};
538 13 50       31 _croak("Internal error:\n sub $id() has no definition\n\n") if(!$def);
539            
540 13 50       41 if($def->{'type'} eq 'abstract') {
541 0         0 $class->_throw_access_error(
542             $def,
543             'This ' . lcfirst($def->{'sub_data'}->{'attribute'}) . ' is declared as abstract but called directly.'
544             );
545             }
546 13         32 return;
547             }
548             # STATIC void
549             sub try_check_access {
550 14     14 1 21 my $class = $_[0];
551 14         18 my $id = $_[1];
552            
553 14         22 my $def = $REGISTER->{$id};
554 14 50       35 _croak("Internal error:\n sub $id() has no definition\n\n") if(!$def);
555            
556 14 100       60 return if($def->{'access_level'} eq 'public');
557            
558 4         13 my ($caller_package, $filename, $line) = caller();
559 4         8 my $msg = '';
560 4 100       17 if($def->{'access_level'} eq 'protected') {
    50          
561 1 50 33     5 return if(UNIVERSAL::isa($caller_package, $def->{'sub_data'}->{'class'}) || UNIVERSAL::isa($def->{'sub_data'}->{'class'}, $caller_package));
562 0         0 $msg = 'protected but called from outside the inheritation';
563             } elsif($def->{'access_level'} eq 'private') {
564 3 100       12 return if($caller_package eq $def->{'sub_data'}->{'class'});
565 1         3 $msg = 'private but called from another class';
566             }
567             $class->_throw_access_error(
568 1         10 $def,
569             'This ' . lcfirst($def->{'sub_data'}->{'attribute'}) . " is declared as $msg",
570             "Called from class/package: '$caller_package'"
571             );
572              
573 0         0 return;
574             }
575             # STATIC void
576             sub check_inheritation {
577 198     198 1 215 my $class = $_[0];
578 198         238 my $method_name = $_[1];
579 198         765 my $parent_class = $_[2];
580 198         201 my $child_class = $_[3];
581 198         205 my $inheritation_type = $_[4];
582            
583 198         881 my $definition_data = {
584             register => $REGISTER,
585             type => $TYPE,
586             access_level_type => $ACCESS_LEVEL_TYPE,
587             access_level => $ACCESS_LEVEL,
588             };
589 198         754 Fukurama::Class::Attributes::OOStandard::InheritationCheck->check_inheritation($method_name, $parent_class, $child_class, $inheritation_type, $definition_data);
590 196         667 return;
591             }
592             #STATIC void
593             sub try_check_call {
594 19     19 1 35 my $class = $_[0];
595 19         27 my $id = $_[1];
596 19         25 my $class_param = $_[2];
597            
598 19         41 my $def = $REGISTER->{$id};
599 19 50       44 _croak("Internal error:\n sub $id() has no definition\n\n") if(!$def);
600            
601 19   100     72 my $is_class = ref($class_param) || $class_param;
602 19         44 my $should_class = $def->{'sub_data'}->{'class'};
603            
604 19 100 66     115 if(!defined($is_class) || !defined($should_class)) {
    100 66        
605 2         7 $class->_throw_access_error($def, 'this subroutine was called directly, not over a class or an object');
606             } elsif(UNIVERSAL::isa($is_class, $should_class) || UNIVERSAL::isa($should_class, $is_class)) {
607 15 100       94 return if($def->{'static'} eq 'static');
608            
609 3 100       14 return if(ref($class_param));
610 1         6 $class->_throw_access_error(
611             $def,
612             'this non-static method was called as static method',
613             'only over a class, not an object',
614             'used class: ' . $class_param
615             );
616             } else {
617 2         11 $class->_throw_access_error(
618             $def,
619             'this method was called over the wrong class/object',
620             'it seems that you call it direct an pass a wrong, first parameter into it',
621             '1st parameter: ' . $class_param
622             );
623             }
624 0         0 return;
625             }
626             # STATIC void
627             sub _throw_access_error {
628 6     6   18 my ($class, $def, @msg) = @_;
629            
630 6         54 _croak("Error in access " .
631             ":\n $def->{'sub_data'}->{'class'}->$def->{'sub_data'}->{'sub_name'}($def->{'sub_data'}->{'data'})\n" .
632             " > " . join("\n > ", @msg) . "\n\n");
633             }
634             1;