annotate scripts/code-style.pl @ 20:e3d20ebd63d1 tip

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