File: MultidimensionalArrayEmulation.pm

package info (click to toggle)
libperl-critic-community-perl 1.0.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 428 kB
  • sloc: perl: 1,100; makefile: 2
file content (114 lines) | stat: -rw-r--r-- 3,648 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package Perl::Critic::Policy::Community::MultidimensionalArrayEmulation;

use strict;
use warnings;

use Perl::Critic::Utils qw(:severities :classification :ppi);
use parent 'Perl::Critic::Policy';

use List::Util 'any';

our $VERSION = 'v1.0.4';

use constant DESC => 'Use of multidimensional array emulation in hash subscript';
use constant EXPL => 'A list in a hash subscript used with the $ sigil triggers Perl 4 multidimensional array emulation. Nest structures using references instead.';

sub supported_parameters { () }
sub default_severity { $SEVERITY_LOW }
sub default_themes { 'community' }
sub applies_to { 'PPI::Structure::Subscript' }

sub violates {
	my ($self, $elem) = @_;
	return () unless $elem->complete and $elem->braces eq '{}';
	
	my @contents = $elem->schildren;
	@contents = $contents[0]->schildren if @contents == 1 and $contents[0]->isa('PPI::Statement::Expression');
	
	# check for function call with no parentheses; following args won't trigger MAE
	if (@contents > 1 and $contents[0]->isa('PPI::Token::Word') and !$contents[1]->isa('PPI::Structure::List')
		and !($contents[1]->isa('PPI::Token::Operator') and ($contents[1] eq ',' or $contents[1] eq '=>'))) {
		return ();
	}
	
	# check if contains top level , or multi-word qw
	return () unless any {
		($_->isa('PPI::Token::Operator') and ($_ eq ',' or $_ eq '=>')) or
		($_->isa('PPI::Token::QuoteLike::Words') and (my @words = $_->literal) > 1)
	} @contents;
	
	# check if it's a postderef slice
	my $prev = $elem->sprevious_sibling;
	return () if $prev and $prev->isa('PPI::Token::Cast') and ($prev eq '@' or $prev eq '%');
	
	# check if it's a slice
	my ($cast, $found_symbol);
	$prev = $elem;
	while ($prev = $prev->sprevious_sibling) {
		last if $found_symbol and !$prev->isa('PPI::Token::Cast');
		if ($prev->isa('PPI::Token::Symbol')) {
			$cast = $prev->raw_type;
			$found_symbol = 1;
		} elsif ($prev->isa('PPI::Structure::Block')) {
			$found_symbol = 1;
		} elsif ($found_symbol and $prev->isa('PPI::Token::Cast')) {
			$cast = $prev;
		} else {
			last unless $prev->isa('PPI::Structure::Subscript')
				or ($prev->isa('PPI::Token::Operator') and $prev eq '->');
		}
	}
	return () if $cast and ($cast eq '@' or $cast eq '%');
	
	return $self->violation(DESC, EXPL, $elem);
}

1;

=head1 NAME

Perl::Critic::Policy::Community::MultidimensionalArrayEmulation - Don't use
multidimensional array emulation

=head1 DESCRIPTION

When used with the C<@> or C<%> sigils, a list in a hash subscript (C<{}>) will
access multiple elements of the hash as a slice. With the C<$> sigil however,
it accesses the single element at the key defined by joining the list with the
subscript separator C<$;>. This feature is known as
L<perldata/"Multi-dimensional array emulation"> and provided a way to emulate
a multidimensional structure before Perl 5 introduced references. Perl now
supports true multidimensional structures, so this feature is now unnecessary
in most cases.

In Perl 5.34 or newer, or automatically under C<use v5.36> or newer,
L<feature/"The 'multidimensional' feature> can be disabled to remove this
syntax from the parser.

  $foo{$x,$y,$z}   # not ok
  $foo{qw(a b c)}  # not ok
  $foo{$x}{$y}{$z} # ok
  @foo{$x,$y,$z}   # ok

=head1 AFFILIATION

This policy is part of L<Perl::Critic::Community>.

=head1 CONFIGURATION

This policy is not configurable except for the standard options.

=head1 AUTHOR

Dan Book, C<dbook@cpan.org>

=head1 COPYRIGHT AND LICENSE

Copyright 2015, Dan Book.

This library is free software; you may redistribute it and/or modify it under
the terms of the Artistic License version 2.0.

=head1 SEE ALSO

L<Perl::Critic>