40 t = re.sub(r"\S", "x", m.group(2)) |
40 t = re.sub(r"\S", "x", m.group(2)) |
41 return m.group(1) + t |
41 return m.group(1) + t |
42 |
42 |
43 |
43 |
44 testpats = [ |
44 testpats = [ |
|
45 [ |
45 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"), |
46 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"), |
46 (r'\W\$?\(\([^\)]*\)\)', "don't use (()) or $(()), use 'expr'"), |
47 (r'\W\$?\(\([^\)]*\)\)', "don't use (()) or $(()), use 'expr'"), |
47 (r'^function', "don't use 'function', use old style"), |
48 (r'^function', "don't use 'function', use old style"), |
48 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
49 (r'echo.*\\n', "don't use 'echo \\n', use printf"), |
50 (r'echo.*\\n', "don't use 'echo \\n', use printf"), |
65 ('^([^"\']|("[^"]*")|(\'[^\']*\'))*\\^', "^ must be quoted"), |
66 ('^([^"\']|("[^"]*")|(\'[^\']*\'))*\\^', "^ must be quoted"), |
66 (r'^source\b', "don't use 'source', use '.'"), |
67 (r'^source\b', "don't use 'source', use '.'"), |
67 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
68 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
68 (r'ls\s+[^|-]+\s+-', "options to 'ls' must come before filenames"), |
69 (r'ls\s+[^|-]+\s+-', "options to 'ls' must come before filenames"), |
69 (r'[^>]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
70 (r'[^>]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
|
71 ], |
|
72 # warnings |
|
73 [] |
70 ] |
74 ] |
71 |
75 |
72 testfilters = [ |
76 testfilters = [ |
73 (r"( *)(#([^\n]*\S)?)", repcomment), |
77 (r"( *)(#([^\n]*\S)?)", repcomment), |
74 (r"<<(\S+)((.|\n)*?\n\1)", rephere), |
78 (r"<<(\S+)((.|\n)*?\n\1)", rephere), |
75 ] |
79 ] |
76 |
80 |
77 uprefix = r"^ \$ " |
81 uprefix = r"^ \$ " |
78 uprefixc = r"^ > " |
82 uprefixc = r"^ > " |
79 utestpats = [ |
83 utestpats = [ |
|
84 [ |
80 (r'^(\S| $ ).*(\S\s+|^\s+)\n', "trailing whitespace on non-output"), |
85 (r'^(\S| $ ).*(\S\s+|^\s+)\n', "trailing whitespace on non-output"), |
81 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"), |
86 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"), |
82 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
87 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
83 (uprefix + r'.*\$\?', "explicit exit code checks unnecessary"), |
88 (uprefix + r'.*\$\?', "explicit exit code checks unnecessary"), |
84 (uprefix + r'.*\|\| echo.*(fail|error)', |
89 (uprefix + r'.*\|\| echo.*(fail|error)', |
85 "explicit exit code checks unnecessary"), |
90 "explicit exit code checks unnecessary"), |
86 (uprefix + r'set -e', "don't use set -e"), |
91 (uprefix + r'set -e', "don't use set -e"), |
87 (uprefixc + r'( *)\t', "don't use tabs to indent"), |
92 (uprefixc + r'( *)\t', "don't use tabs to indent"), |
88 ] |
93 ], |
89 |
94 # warnings |
90 for p, m in testpats: |
95 [] |
|
96 ] |
|
97 |
|
98 for p, m in testpats[0] + testpats[1]: |
91 if p.startswith('^'): |
99 if p.startswith('^'): |
92 p = uprefix + p[1:] |
100 p = uprefix + p[1:] |
93 else: |
101 else: |
94 p = uprefix + p |
102 p = uprefix + p |
95 utestpats.append((p, m)) |
103 utestpats.append((p, m)) |
97 utestfilters = [ |
105 utestfilters = [ |
98 (r"( *)(#([^\n]*\S)?)", repcomment), |
106 (r"( *)(#([^\n]*\S)?)", repcomment), |
99 ] |
107 ] |
100 |
108 |
101 pypats = [ |
109 pypats = [ |
|
110 [ |
102 (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
111 (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
103 "tuple parameter unpacking not available in Python 3+"), |
112 "tuple parameter unpacking not available in Python 3+"), |
104 (r'lambda\s*\(.*,.*\)', |
113 (r'lambda\s*\(.*,.*\)', |
105 "tuple parameter unpacking not available in Python 3+"), |
114 "tuple parameter unpacking not available in Python 3+"), |
106 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
115 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
110 (r'\S;\s*\n', "semicolon"), |
119 (r'\S;\s*\n', "semicolon"), |
111 (r'\w,\w', "missing whitespace after ,"), |
120 (r'\w,\w', "missing whitespace after ,"), |
112 (r'\w[+/*\-<>]\w', "missing whitespace in expression"), |
121 (r'\w[+/*\-<>]\w', "missing whitespace in expression"), |
113 (r'^\s+\w+=\w+[^,)]$', "missing whitespace in assignment"), |
122 (r'^\s+\w+=\w+[^,)]$', "missing whitespace in assignment"), |
114 (r'.{85}', "line too long"), |
123 (r'.{85}', "line too long"), |
115 (r'.{81}', "warning: line over 80 characters"), |
|
116 (r'[^\n]\Z', "no trailing newline"), |
124 (r'[^\n]\Z', "no trailing newline"), |
117 (r'(\S\s+|^\s+)\n', "trailing whitespace"), |
125 (r'(\S\s+|^\s+)\n', "trailing whitespace"), |
118 # (r'^\s+[^_ ][^_. ]+_[^_]+\s*=', "don't use underbars in identifiers"), |
126 # (r'^\s+[^_ ][^_. ]+_[^_]+\s*=', "don't use underbars in identifiers"), |
119 # (r'\w*[a-z][A-Z]\w*\s*=', "don't use camelcase in identifiers"), |
127 # (r'\w*[a-z][A-Z]\w*\s*=', "don't use camelcase in identifiers"), |
120 (r'^\s*(if|while|def|class|except|try)\s[^[]*:\s*[^\]#\s]+', |
128 (r'^\s*(if|while|def|class|except|try)\s[^[]*:\s*[^\]#\s]+', |
148 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
156 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
149 "missing whitespace around operator"), |
157 "missing whitespace around operator"), |
150 (r'[^+=*!<>&| -](\s=|=\s)[^= ]', |
158 (r'[^+=*!<>&| -](\s=|=\s)[^= ]', |
151 "wrong whitespace around ="), |
159 "wrong whitespace around ="), |
152 (r'raise Exception', "don't raise generic exceptions"), |
160 (r'raise Exception', "don't raise generic exceptions"), |
|
161 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
|
162 (r' [=!]=\s+(True|False|None)', |
|
163 "comparison with singleton, use 'is' or 'is not' instead"), |
|
164 ], |
|
165 # warnings |
|
166 [ |
|
167 (r'.{81}', "warning: line over 80 characters"), |
153 (r'^\s*except:$', "warning: naked except clause"), |
168 (r'^\s*except:$', "warning: naked except clause"), |
154 (r'ui\.(status|progress|write|note|warn)\([\'\"]x', |
169 (r'ui\.(status|progress|write|note|warn)\([\'\"]x', |
155 "warning: unwrapped ui message"), |
170 "warning: unwrapped ui message"), |
156 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
171 ] |
157 (r' [=!]=\s+(True|False|None)', |
|
158 "comparison with singleton, use 'is' or 'is not' instead"), |
|
159 ] |
172 ] |
160 |
173 |
161 pyfilters = [ |
174 pyfilters = [ |
162 (r"""(?msx)(?P<comment>\#.*?$)| |
175 (r"""(?msx)(?P<comment>\#.*?$)| |
163 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
176 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
164 (?P<text>(([^\\]|\\.)*?)) |
177 (?P<text>(([^\\]|\\.)*?)) |
165 (?P=quote))""", reppython), |
178 (?P=quote))""", reppython), |
166 ] |
179 ] |
167 |
180 |
168 cpats = [ |
181 cpats = [ |
|
182 [ |
169 (r'//', "don't use //-style comments"), |
183 (r'//', "don't use //-style comments"), |
170 (r'^ ', "don't use spaces to indent"), |
184 (r'^ ', "don't use spaces to indent"), |
171 (r'\S\t', "don't use tabs except for indent"), |
185 (r'\S\t', "don't use tabs except for indent"), |
172 (r'(\S\s+|^\s+)\n', "trailing whitespace"), |
186 (r'(\S\s+|^\s+)\n', "trailing whitespace"), |
173 (r'.{85}', "line too long"), |
187 (r'.{85}', "line too long"), |
180 (r'\w,\w', "missing whitespace after ,"), |
194 (r'\w,\w', "missing whitespace after ,"), |
181 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
195 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
182 (r'^#\s+\w', "use #foo, not # foo"), |
196 (r'^#\s+\w', "use #foo, not # foo"), |
183 (r'[^\n]\Z', "no trailing newline"), |
197 (r'[^\n]\Z', "no trailing newline"), |
184 (r'^\s*#import\b', "use only #include in standard C code"), |
198 (r'^\s*#import\b', "use only #include in standard C code"), |
|
199 ], |
|
200 # warnings |
|
201 [] |
185 ] |
202 ] |
186 |
203 |
187 cfilters = [ |
204 cfilters = [ |
188 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), |
205 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), |
189 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
206 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
256 fp.close() |
273 fp.close() |
257 if "no-" + "check-code" in pre: |
274 if "no-" + "check-code" in pre: |
258 break |
275 break |
259 for p, r in filters: |
276 for p, r in filters: |
260 post = re.sub(p, r, post) |
277 post = re.sub(p, r, post) |
|
278 if warnings: |
|
279 pats = pats[0] + pats[1] |
|
280 else: |
|
281 pats = pats[0] |
261 # print post # uncomment to show filtered version |
282 # print post # uncomment to show filtered version |
262 z = enumerate(zip(pre.splitlines(), post.splitlines(True))) |
283 z = enumerate(zip(pre.splitlines(), post.splitlines(True))) |
263 for n, l in z: |
284 for n, l in z: |
264 if "check-code" + "-ignore" in l[0]: |
285 if "check-code" + "-ignore" in l[0]: |
265 continue |
286 continue |
266 for p, msg in pats: |
287 for p, msg in pats: |
267 if not warnings and msg.startswith("warning"): |
|
268 continue |
|
269 if re.search(p, l[1]): |
288 if re.search(p, l[1]): |
270 bd = "" |
289 bd = "" |
271 if blame: |
290 if blame: |
272 bd = 'working directory' |
291 bd = 'working directory' |
273 if not blamecache: |
292 if not blamecache: |