comparison scripts/code-style.pl @ 1:c1f4ac30525a 6.0

Drupal 6.0
author Franck Deroche <webmaster@defr.org>
date Tue, 23 Dec 2008 14:28:28 +0100
parents
children
comparison
equal deleted inserted replaced
0:5a113a1c4740 1:c1f4ac30525a
1 #!/usr/bin/perl -w
2 # $Id: code-style.pl,v 1.14 2007/02/15 11:40:19 dries Exp $
3
4 use Pod::Usage;
5 use Getopt::Long qw(GetOptions);
6 Getopt::Long::Configure ("bundling");
7
8 my %opt = ( "help" => 0,
9 'debug' => 0,
10 );
11
12 if(!GetOptions(\%opt,
13 'help|?',
14 'debug',
15 )) {
16 pod2usage(-exitval => 1, 'verbose'=>0);
17 }
18
19 pod2usage(-exitval => 0, -verbose => 2) if($opt{'help'});
20
21 $debug = $opt{'debug'};
22
23 $comment = 0; #flag used to signal we're inside /* */
24 $program = 0; #flag used to signal we're inside <?php ?>
25 #read the file
26 while (<>) {
27 $org=$_;
28 s/\\["']//g;
29 # please don't use nested comments for now... thanks!
30 # handles comments // style, but don't mess with http://
31 s/\/\/[^:].*//;
32 # handles comments /**/ on a single line
33 s/\/\*.*\*\///g;
34 # handles comments /**/ over several lines
35 if ($comment == 1) {
36 if (s/.*\*\///) {
37 $comment = 0;
38 }
39 else {
40 next;
41 }
42 }
43 if (s/\/\*.*//) {
44 $comment = 1;
45 }
46 if (/^\s*#/) {
47 next;
48 }
49
50 if (s/<\?php//) {
51 $program = 1;
52 }
53 if (/\?>/) {
54 $program = 0;
55 }
56
57 # enforce "bar". foo() ."bar" syntax
58 if (/^("[^"]*"|[^"])*("[^"]*")\.[^ ]/ && $program) {
59 $msg = "'\".' -> '\". '";
60 }
61 elsif (/^("[^"]*"|[^"])*("[^"]*")\s+\./ && $program) {
62 $msg = "'\" .' -> '\".'";
63 }
64 # enforce "bar". foo() ."bar" syntax
65 elsif (/^("[^"]*"|[^"])*[^ "]\.("[^"]*")/ && $program) {
66 $msg = "'.\"' -> '.\"'";
67 }
68 elsif (/^("[^"]*"|[^"])*[^ "]\.\s+("[^"]*")/ && $program) {
69 $msg = "'. \"' -> '.\"'";
70 }
71 # XHTML requires closing tag
72 elsif (/<br>/i) {
73 $msg = "'<br>' -> '<br />'";
74 }
75 elsif (/\$REQUEST_URI/i) {
76 $msg = "the use of REQUEST_URI is prone to XSS exploits and does not work on IIS; use request_uri() instead";
77 }
78 elsif (/\"REQUEST_URI\"/i) {
79 $msg = "the use of REQUEST_URI is prone to XSS exploits and does not work on IIS; use request_uri() instead";
80 }
81
82 # XHTML compatibility mode suggests a blank before /
83 # i.e. <br />
84 elsif (/<[a-z][^>]*[^ >]\/>/i) {
85 $msg = "'<foo/".">' -> '<foo />'";
86 }
87 # we write '{' on the same line, not on the next
88 elsif (/^\s*{/ && $program) {
89 $msg = "take '{' to previous line";
90 }
91 elsif (/([a-z])([A-Z])/) {
92 $msg = "no mixed case function or variable names, use lower case and _";
93 }
94 elsif (/<[\/]*[A-Z]+[^>]*>/) {
95 $msg = "XHTML demands tags to be lowercase";
96 }
97
98 # trying to recognize splitted lines
99 # there are only a few valid last characters in programming mode,
100 # only sometimes it is ( if you use if/else with a single statement
101
102 # from here on we need no more strings
103 while (s/^([^"]*)"[^"]*"/$1#/) {};
104 while (s/^([^']*)'[^']*'/$1#/) {};
105
106 # it should be 'if (' all the time
107 if (/(^|[^a-zA-Z])(if|else|elseif|while|foreach|switch|return|for)\(/) {
108 $msg = "'(' -> ' ('";
109 }
110 #elsif (/[^;{}:\s\n]\s*\n*$/ && $program && !/^[\s}]*(if|else)/) {
111 # $msg = "don't split lines";
112 #}
113 elsif (/\}\s*else/) {
114 $msg = "'} else' -> '}\\nelse'";
115 }
116 elsif (/[^{\s\n]\s*\n*$/ && $program && /^\s*(if|else)/) {
117 $msg = "every if/else needs a { at eol";
118 }
119 elsif (/([\(\[]) / && $program) {
120 $msg = "'$1 ' -> '$1'";
121 }
122 elsif (/\S ([\)\]])/ && $program) {
123 $msg = "' $1' -> '$1'";
124 }
125 # but no brackets
126 elsif (/([a-z-A-Z_][a-zA-Z0-9_-]*)\s+\(/ && $program) {
127 if ($1 ne "switch" and $1 ne "if" and $1 ne "while" and $1 ne "foreach" and $1 ne "return" and $1 ne "for" and $1 ne "elseif") {
128 $msg = "'$1 (' -> '$1('";
129 }
130 }
131 # there should be a space before '{'
132 if (/[^ ]{/ && $program) {
133 $msg = "missing space before '{'";
134 }
135 # there should be a space after ','
136 elsif (/[,][^ \n\r]/ && $program) {
137 $msg = "missing space after ','";
138 }
139 # spaces before and after, only foreach may use $foo=>bar
140 elsif (/[^ =|\-|\+](\+|\-)[^ =>|\-|\+]/ && $program && !/foreach/) {
141 $msg = "'$1' -> ' $1 '";
142 }
143 elsif (/[^ =](\*|==|\.=|=>|=|\|\|)[^ =>]/ && $program && !/foreach/) {
144 $msg = "'$1' -> ' $1 '";
145 }
146 # ensure $bar["foo"] and $bar[$foo] and $bar[0]
147 elsif (/\[[^#][^\]]*\]/ && !/\[[0-9\$][^\]]*\]/ && !/\[\]/) {
148 $msg = "only [\"foo\"], [\$foo] or [0] is allowed";
149 }
150 # first try to find missing quotes after = in (X)HTML tags
151 elsif (/<[^>]*=[a-zA-Z0-9][^>]*>/) {
152 $msg = "=... -> =\"...\"";
153 }
154 if (defined $msg) {
155 if ($debug==0) {
156 print $ARGV .":". $. .": $msg : ". $org;
157 }
158 undef $msg;
159 }
160 elsif ($debug==1) {
161 print $org;
162 }
163 } continue {
164 close ARGV if eof;
165 }
166
167 __END__
168
169 =head1 NAME
170
171 code-style.pl - Review drupal code for style
172
173 =head1 SYNOPSIS
174
175 code-style.pl [options] <filename>
176
177 Options:
178
179 -? --help detailed help message
180
181 =head1 DESCRIPTION
182
183 Originally written for Drupal (http://drupal.org/) to ensure stylish
184 code. This program reviews PHP code, and tries to show as many code
185 improvements as possible with no false positives.
186
187 =head1 OPTIONS
188
189 --comment
190
191 =head1 EXAMPLES
192
193 ./code-style.pl ../index.php
194
195 =cut