initial import from onelab svn codebase
[plewww.git] / scripts / code-style.pl
1 #!/usr/bin/perl -w
2 # $Id: code-style.pl 144 2007-03-28 07:52:20Z thierry $
3
4 # Author: Alexander Schwartz (alexander.schwartz@gmx.net)
5 # Licence: GPL
6 # First version: 2001-10-15
7
8 # Originally written for Drupal (http://drupal.org/) to ensure stylish
9 # code.  This program tries to show as many improvements as possible with
10 # no false positives.
11
12 # $Id: code-style.pl 144 2007-03-28 07:52:20Z thierry $
13
14 $comment = 0;
15 $program = 0;
16 if ($ARGV[0] eq '-debug') {
17   $debug=1;
18   shift (@ARGV);
19 }
20 else {
21   $debug=0;
22 }
23 while (<>) {
24   $org=$_;
25   s/\\["']//g;
26   # please don't use nested comments for now... thanks!
27   # handles comments // style, but don't mess with http://
28   s/\/\/[^:].*//;
29   # handles comments /**/ on a single line
30   s/\/\*.*\*\///g;
31   # handles comments /**/ over several lines
32   if ($comment == 1) {
33     if (s/.*\*\///) {
34       $comment = 0;
35     }
36     else {
37       next;
38     }
39   }
40   if (s/\/\*.*//) {
41     $comment = 1;
42   }
43   if (/^\s*#/) {
44     next;
45   }
46
47   if (s/<\?php//) {
48     $program = 1;
49   }
50   if (/\?>/) {
51     $program = 0;
52   }
53
54   # enforce "bar". foo() ."bar" syntax
55   if (/^("[^"]*"|[^"])*("[^"]*")\.[^ ]/ && $program) {
56     $msg = "'\".' -> '\". '";
57   }
58   elsif (/^("[^"]*"|[^"])*("[^"]*")\s+\./ && $program) {
59     $msg = "'\" .' -> '\".'";
60   }
61   # enforce "bar". foo() ."bar" syntax
62   elsif (/^("[^"]*"|[^"])*[^ "]\.("[^"]*")/ && $program) {
63     $msg = "'.\"' -> '.\"'";
64   }
65   elsif (/^("[^"]*"|[^"])*[^ "]\.\s+("[^"]*")/ && $program) {
66     $msg = "'. \"' -> '.\"'";
67   }
68   # XHTML requires closing tag
69   elsif (/<br>/i) {
70     $msg = "'<br>' -> '<br />'";
71   }
72   elsif (/\$REQUEST_URI/i) {
73     $msg = "the use of REQUEST_URI is prone to XSS exploits and does not work on IIS; use request_uri() instead";
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
79   # XHTML compatibility mode suggests a blank before /
80   # i.e. <br />
81   elsif (/<[a-z][^>]*[^ >]\/>/i) {
82     $msg = "'<foo/".">' -> '<foo />'";
83   }
84   # we write '{' on the same line, not on the next
85   elsif (/^\s*{/ && $program) {
86     $msg = "take '{' to previous line";
87   }
88   elsif (/([a-z])([A-Z])/) {
89     $msg = "no mixed case function or variable names, use lower case and _";
90   }
91   elsif (/<[\/]*[A-Z]+[^>]*>/) {
92     $msg = "XHTML demands tags to be lowercase";
93   }
94
95   # trying to recognize splitted lines
96   # there are only a few valid last characters in programming mode,
97   # only sometimes it is ( if you use if/else with a single statement
98
99   # from here on we need no more strings
100   while (s/^([^"]*)"[^"]*"/$1#/) {};
101   while (s/^([^']*)'[^']*'/$1#/) {};
102
103   # it should be 'if (' all the time
104   if (/(^|[^a-zA-Z])(if|else|elseif|while|foreach|switch|return|for)\(/) {
105     $msg = "'(' -> ' ('";
106   }
107   #elsif (/[^;{}:\s\n]\s*\n*$/ && $program && !/^[\s}]*(if|else)/) {
108   #  $msg = "don't split lines";
109   #}
110   elsif (/\}\s*else/) {
111     $msg = "'} else' -> '}\\nelse'";
112   }
113   elsif (/[^{\s\n]\s*\n*$/ && $program && /^\s*(if|else)/) {
114     $msg = "every if/else needs a { at eol";
115   }
116   elsif (/([\(\[]) / && $program) {
117     $msg = "'$1 ' -> '$1'";
118   }
119   elsif (/ ([\)\]])/ && $program) {
120     $msg = "' $1' -> '$1'";
121   }
122   # but no brackets
123   elsif (/([a-z-A-Z_][a-zA-Z0-9_-]*)\s+\(/ && $program) {
124     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") {
125       $msg = "'$1 (' -> '$1('";
126     }
127   }
128   # there should be a space before '{'
129   if (/[^ ]{/ && $program) {
130     $msg = "missing space before '{'";
131   }
132   # there should be a space after ','
133   elsif (/[,][^ \n\r]/ && $program) {
134     $msg = "missing space after ','";
135   }
136   # spaces before and after, only foreach may use $foo=>bar
137   elsif (/[^ =|\-|\+](\+|\-)[^ =>|\-|\+]/ && $program && !/foreach/) {
138     $msg = "'$1' -> ' $1 '";
139   }
140   elsif (/[^ =](\*|==|\.=|=>|=|\|\|)[^ =>]/ && $program && !/foreach/) {
141     $msg = "'$1' -> ' $1 '";
142   }
143   # ensure $bar["foo"] and $bar[$foo] and $bar[0]
144   elsif (/\[[^#][^\]]*\]/ && !/\[[0-9\$][^\]]*\]/ && !/\[\]/) {
145     $msg = "only [\"foo\"], [\$foo] or [0] is allowed";
146   }
147   # first try to find missing quotes after = in (X)HTML tags
148   elsif (/<[^>]*=[a-zA-Z0-9][^>]*>/) {
149     $msg = "=... -> =\"...\"";
150   }
151   if (defined $msg) {
152     if ($debug==0) {
153       print $ARGV .":". $. .": $msg : ". $org;
154     }
155     undef $msg;
156   }
157   elsif ($debug==1) {
158     print $org;
159   }
160 } continue {
161   close ARGV if eof;
162 }