File: MaybeTypeCheck.pm

package info (click to toggle)
libgraphql-perl 0.54-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 712 kB
  • sloc: perl: 5,094; makefile: 2
file content (80 lines) | stat: -rw-r--r-- 2,005 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package GraphQL::MaybeTypeCheck;

use 5.014;
use strict;
use warnings;

use Attribute::Handlers;
use Devel::StrictMode;
use Import::Into;

=head1 NAME

GraphQL::MaybeTypeCheck - Conditional type-checking at runtime

=head1 SYNOPSIS

  use GraphQL::MaybeTypeCheck;

  method foo(
    $arg1 Str,
    $arg2 Int
  ) :ReturnType(Map[Str, Int]) {
    # ...
  }

=head1 DESCRIPTION

This module B<optionally> enables type-checking in the caller as implemented by
L<Function::Parameters> and L<Return::Type> depending on whether L<Devel::StrictMode>
is activated.

=head3 C<Devel::StrictMode> ON

When L<Devel::StrictMode> is active, this module will import L<Function::Parameters>
into the caller with its default configuration. As of writing, this includes
checking both argument count and type.

When in strict mode this also C<require>s L<Return::Type> which registers the
C<ReturnType> attribute.

=head3 C<Devel::StrictMode> OFF

When strict mode is inactive this module still imports C<Function::Parameters>
into the caller however it sets C<fun> and C<method> to L<lax mode|Function::Parameters/function_lax> and disables
argument type checking.

This also installs a no-op C<ReturnType> attribute so the existing syntax isn't
broken.

=cut

sub ReturnType : ATTR(CODE) {
  my ($package, $symbol, $referent, $attr, $data) = @_;

  # If strict mode is enabled, wrap the sub so the return type is checked
  if (STRICT) {
    my %args = (@$data % 2) ? (scalar => @$data) : @$data;
    Return::Type->wrap_sub($referent, %args);
  }
}

sub import {
  return unless $_[0] eq __PACKAGE__;
  my $caller = caller;
  {
    no strict 'refs';
    push @{"${caller}::ISA"}, __PACKAGE__;
  }
  if (STRICT) {
    Function::Parameters->import::into($caller, ':strict');
    require Return::Type;
  } else {
    Function::Parameters->import::into($caller, {
      fun    => {defaults => 'function_lax', check_argument_types => 0},
      method => {defaults => 'method_lax',   check_argument_types => 0},
    });
  }
}

1;