blob: 81b3710dce1a498b844e0987fcdadacc3e46951f [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d1982009-02-19 16:33:1227
jochen9ea8fdbc2014-09-25 13:21:3528# The NetscapePlugIn library is excluded from pan-project as it will soon
29# be deleted together with the rest of the NPAPI and it's not worthwhile to
30# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3831_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3232 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3833)
34
[email protected]06e6d0ff2012-12-11 01:36:4435# Fragment of a regular expression that matches C++ and Objective-C++
36# implementation files.
37_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
38
39# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3244 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4450 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4951 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4752 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4953 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0854 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4955 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4456)
[email protected]ca8d1982009-02-19 16:33:1257
[email protected]eea609a2011-11-18 13:10:1258_TEST_ONLY_WARNING = (
59 'You might be calling functions intended only for testing from\n'
60 'production code. It is OK to ignore this warning if you know what\n'
61 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5862 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1263
64
[email protected]cf9b78f2012-11-14 11:40:2865_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4066 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2167 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
68 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2869
[email protected]127f18ec2012-06-16 05:05:5970_BANNED_OBJC_FUNCTIONS = (
71 (
72 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2073 (
74 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5975 'prohibited. Please use CrTrackingArea instead.',
76 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
77 ),
78 False,
79 ),
80 (
[email protected]eaae1972014-04-16 04:17:2681 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2082 (
83 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5984 'instead.',
85 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
86 ),
87 False,
88 ),
89 (
90 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2091 (
92 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5993 'Please use |convertPoint:(point) fromView:nil| instead.',
94 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
95 ),
96 True,
97 ),
98 (
99 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20100 (
101 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59102 'Please use |convertPoint:(point) toView:nil| instead.',
103 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
104 ),
105 True,
106 ),
107 (
108 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20109 (
110 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59111 'Please use |convertRect:(point) fromView:nil| instead.',
112 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
113 ),
114 True,
115 ),
116 (
117 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20118 (
119 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59120 'Please use |convertRect:(point) toView:nil| instead.',
121 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
122 ),
123 True,
124 ),
125 (
126 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20127 (
128 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59129 'Please use |convertSize:(point) fromView:nil| instead.',
130 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
131 ),
132 True,
133 ),
134 (
135 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20136 (
137 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59138 'Please use |convertSize:(point) toView:nil| instead.',
139 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
140 ),
141 True,
142 ),
143)
144
145
146_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20147 # Make sure that gtest's FRIEND_TEST() macro is not used; the
148 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30149 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20150 (
151 'FRIEND_TEST(',
152 (
[email protected]e3c945502012-06-26 20:01:49153 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20154 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
155 ),
156 False,
[email protected]7345da02012-11-27 14:31:49157 (),
[email protected]23e6cbc2012-06-16 18:51:20158 ),
159 (
160 'ScopedAllowIO',
161 (
[email protected]e3c945502012-06-26 20:01:49162 'New code should not use ScopedAllowIO. Post a task to the blocking',
163 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20164 ),
[email protected]e3c945502012-06-26 20:01:49165 True,
[email protected]7345da02012-11-27 14:31:49166 (
nyad2c548b2015-12-09 03:22:32167 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10168 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49169 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22170 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
alematee4016bb2014-11-12 17:38:51171 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
172 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09173 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
[email protected]de7d61ff2013-08-20 11:30:41174 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
175 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48176 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
177 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01178 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54179 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
joedow91151042016-02-08 21:18:13180 r"^remoting[\\\/]host[\\\/]security_key[\\\/]"
181 "gnubby_auth_handler_linux\.cc$",
dnicoara171d8c82015-03-05 20:46:18182 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
rjkroege8471a0a92016-02-04 19:50:29183 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49184 ),
[email protected]23e6cbc2012-06-16 18:51:20185 ),
[email protected]52657f62013-05-20 05:30:31186 (
187 'SkRefPtr',
188 (
189 'The use of SkRefPtr is prohibited. ',
190 'Please use skia::RefPtr instead.'
191 ),
192 True,
193 (),
194 ),
195 (
196 'SkAutoRef',
197 (
198 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
199 'Please use skia::RefPtr instead.'
200 ),
201 True,
202 (),
203 ),
204 (
205 'SkAutoTUnref',
206 (
207 'The use of SkAutoTUnref is dangerous because it implicitly ',
208 'converts to a raw pointer. Please use skia::RefPtr instead.'
209 ),
210 True,
211 (),
212 ),
213 (
214 'SkAutoUnref',
215 (
216 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
217 'because it implicitly converts to a raw pointer. ',
218 'Please use skia::RefPtr instead.'
219 ),
220 True,
221 (),
222 ),
[email protected]d89eec82013-12-03 14:10:59223 (
224 r'/HANDLE_EINTR\(.*close',
225 (
226 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
227 'descriptor will be closed, and it is incorrect to retry the close.',
228 'Either call close directly and ignore its return value, or wrap close',
229 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
230 ),
231 True,
232 (),
233 ),
234 (
235 r'/IGNORE_EINTR\((?!.*close)',
236 (
237 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
238 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
239 ),
240 True,
241 (
242 # Files that #define IGNORE_EINTR.
243 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
244 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
245 ),
246 ),
[email protected]ec5b3f02014-04-04 18:43:43247 (
248 r'/v8::Extension\(',
249 (
250 'Do not introduce new v8::Extensions into the code base, use',
251 'gin::Wrappable instead. See http://crbug.com/334679',
252 ),
253 True,
[email protected]f55c90ee62014-04-12 00:50:03254 (
joaodasilva718f87672014-08-30 09:25:49255 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03256 ),
[email protected]ec5b3f02014-04-04 18:43:43257 ),
skyostilf9469f72015-04-20 10:38:52258 (
sdefresneeaeccc52015-04-22 08:18:32259 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52260 (
261 'MessageLoopProxy is deprecated. ',
262 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
263 ),
264 True,
kinuko59024ce2015-04-21 22:18:30265 (
266 # Internal message_loop related code may still use it.
267 r'^base[\\\/]message_loop[\\\/].*',
268 ),
skyostilf9469f72015-04-20 10:38:52269 ),
[email protected]127f18ec2012-06-16 05:05:59270)
271
mlamouria82272622014-09-16 18:45:04272_IPC_ENUM_TRAITS_DEPRECATED = (
273 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
274 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
275
[email protected]127f18ec2012-06-16 05:05:59276
[email protected]b00342e7f2013-03-26 16:21:54277_VALID_OS_MACROS = (
278 # Please keep sorted.
279 'OS_ANDROID',
280 'OS_BSD',
281 'OS_CAT', # For testing.
282 'OS_CHROMEOS',
283 'OS_FREEBSD',
284 'OS_IOS',
285 'OS_LINUX',
286 'OS_MACOSX',
287 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21288 'OS_NACL_NONSFI',
289 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54290 'OS_OPENBSD',
291 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37292 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54293 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54294 'OS_WIN',
295)
296
297
[email protected]55459852011-08-10 15:17:19298def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
299 """Attempts to prevent use of functions intended only for testing in
300 non-testing code. For now this is just a best-effort implementation
301 that ignores header files and may have some false positives. A
302 better implementation would probably need a proper C++ parser.
303 """
304 # We only scan .cc files and the like, as the declaration of
305 # for-testing functions in header files are hard to distinguish from
306 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44307 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19308
jochenc0d4808c2015-07-27 09:25:42309 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19310 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09311 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19312 exclusion_pattern = input_api.re.compile(
313 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
314 base_function_pattern, base_function_pattern))
315
316 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44317 black_list = (_EXCLUDED_PATHS +
318 _TEST_CODE_EXCLUDED_PATHS +
319 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19320 return input_api.FilterSourceFile(
321 affected_file,
322 white_list=(file_inclusion_pattern, ),
323 black_list=black_list)
324
325 problems = []
326 for f in input_api.AffectedSourceFiles(FilterFile):
327 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24328 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03329 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46330 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03331 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19332 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03333 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19334
335 if problems:
[email protected]f7051d52013-04-02 18:31:42336 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03337 else:
338 return []
[email protected]55459852011-08-10 15:17:19339
340
[email protected]10689ca2011-09-02 02:31:54341def _CheckNoIOStreamInHeaders(input_api, output_api):
342 """Checks to make sure no .h files include <iostream>."""
343 files = []
344 pattern = input_api.re.compile(r'^#include\s*<iostream>',
345 input_api.re.MULTILINE)
346 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
347 if not f.LocalPath().endswith('.h'):
348 continue
349 contents = input_api.ReadFile(f)
350 if pattern.search(contents):
351 files.append(f)
352
353 if len(files):
354 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06355 'Do not #include <iostream> in header files, since it inserts static '
356 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54357 '#include <ostream>. See http://crbug.com/94794',
358 files) ]
359 return []
360
361
[email protected]72df4e782012-06-21 16:28:18362def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52363 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18364 problems = []
365 for f in input_api.AffectedFiles():
366 if (not f.LocalPath().endswith(('.cc', '.mm'))):
367 continue
368
369 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04370 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18371 problems.append(' %s:%d' % (f.LocalPath(), line_num))
372
373 if not problems:
374 return []
375 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
376 '\n'.join(problems))]
377
378
danakj61c1aa22015-10-26 19:55:52379def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
380 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
381 errors = []
382 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
383 input_api.re.MULTILINE)
384 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
385 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
386 continue
387 for lnum, line in f.ChangedContents():
388 if input_api.re.search(pattern, line):
389 errors.append(output_api.PresubmitError(
390 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
391 'DCHECK_IS_ON()", not forgetting the braces.')
392 % (f.LocalPath(), lnum)))
393 return errors
394
395
mcasasb7440c282015-02-04 14:52:19396def _FindHistogramNameInLine(histogram_name, line):
397 """Tries to find a histogram name or prefix in a line."""
398 if not "affected-histogram" in line:
399 return histogram_name in line
400 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
401 # the histogram_name.
402 if not '"' in line:
403 return False
404 histogram_prefix = line.split('\"')[1]
405 return histogram_prefix in histogram_name
406
407
408def _CheckUmaHistogramChanges(input_api, output_api):
409 """Check that UMA histogram names in touched lines can still be found in other
410 lines of the patch or in histograms.xml. Note that this check would not catch
411 the reverse: changes in histograms.xml not matched in the code itself."""
412 touched_histograms = []
413 histograms_xml_modifications = []
414 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
415 for f in input_api.AffectedFiles():
416 # If histograms.xml itself is modified, keep the modified lines for later.
417 if f.LocalPath().endswith(('histograms.xml')):
418 histograms_xml_modifications = f.ChangedContents()
419 continue
420 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
421 continue
422 for line_num, line in f.ChangedContents():
423 found = pattern.search(line)
424 if found:
425 touched_histograms.append([found.group(1), f, line_num])
426
427 # Search for the touched histogram names in the local modifications to
428 # histograms.xml, and, if not found, on the base histograms.xml file.
429 unmatched_histograms = []
430 for histogram_info in touched_histograms:
431 histogram_name_found = False
432 for line_num, line in histograms_xml_modifications:
433 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
434 if histogram_name_found:
435 break
436 if not histogram_name_found:
437 unmatched_histograms.append(histogram_info)
438
eromanb90c82e7e32015-04-01 15:13:49439 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19440 problems = []
441 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49442 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19443 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45444 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19445 histogram_name_found = False
446 for line in histograms_xml:
447 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
448 if histogram_name_found:
449 break
450 if not histogram_name_found:
451 problems.append(' [%s:%d] %s' %
452 (f.LocalPath(), line_num, histogram_name))
453
454 if not problems:
455 return []
456 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
457 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49458 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19459
460
[email protected]8ea5d4b2011-09-13 21:49:22461def _CheckNoNewWStrings(input_api, output_api):
462 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27463 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22464 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20465 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57466 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
467 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20468 continue
[email protected]8ea5d4b2011-09-13 21:49:22469
[email protected]a11dbe9b2012-08-07 01:32:58470 allowWString = False
[email protected]b5c24292011-11-28 14:38:20471 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58472 if 'presubmit: allow wstring' in line:
473 allowWString = True
474 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27475 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58476 allowWString = False
477 else:
478 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22479
[email protected]55463aa62011-10-12 00:48:27480 if not problems:
481 return []
482 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58483 ' If you are calling a cross-platform API that accepts a wstring, '
484 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27485 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22486
487
[email protected]2a8ac9c2011-10-19 17:20:44488def _CheckNoDEPSGIT(input_api, output_api):
489 """Make sure .DEPS.git is never modified manually."""
490 if any(f.LocalPath().endswith('.DEPS.git') for f in
491 input_api.AffectedFiles()):
492 return [output_api.PresubmitError(
493 'Never commit changes to .DEPS.git. This file is maintained by an\n'
494 'automated system based on what\'s in DEPS and your changes will be\n'
495 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34496 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44497 'for more information')]
498 return []
499
500
tandriief664692014-09-23 14:51:47501def _CheckValidHostsInDEPS(input_api, output_api):
502 """Checks that DEPS file deps are from allowed_hosts."""
503 # Run only if DEPS file has been modified to annoy fewer bystanders.
504 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
505 return []
506 # Outsource work to gclient verify
507 try:
508 input_api.subprocess.check_output(['gclient', 'verify'])
509 return []
510 except input_api.subprocess.CalledProcessError, error:
511 return [output_api.PresubmitError(
512 'DEPS file must have only git dependencies.',
513 long_text=error.output)]
514
515
[email protected]127f18ec2012-06-16 05:05:59516def _CheckNoBannedFunctions(input_api, output_api):
517 """Make sure that banned functions are not used."""
518 warnings = []
519 errors = []
520
521 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
522 for f in input_api.AffectedFiles(file_filter=file_filter):
523 for line_num, line in f.ChangedContents():
524 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
[email protected]eaae1972014-04-16 04:17:26525 matched = False
526 if func_name[0:1] == '/':
527 regex = func_name[1:]
528 if input_api.re.search(regex, line):
529 matched = True
530 elif func_name in line:
531 matched = True
532 if matched:
[email protected]127f18ec2012-06-16 05:05:59533 problems = warnings;
534 if error:
535 problems = errors;
536 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
537 for message_line in message:
538 problems.append(' %s' % message_line)
539
540 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
541 for f in input_api.AffectedFiles(file_filter=file_filter):
542 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49543 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
544 def IsBlacklisted(affected_file, blacklist):
545 local_path = affected_file.LocalPath()
546 for item in blacklist:
547 if input_api.re.match(item, local_path):
548 return True
549 return False
550 if IsBlacklisted(f, excluded_paths):
551 continue
[email protected]d89eec82013-12-03 14:10:59552 matched = False
553 if func_name[0:1] == '/':
554 regex = func_name[1:]
555 if input_api.re.search(regex, line):
556 matched = True
557 elif func_name in line:
558 matched = True
559 if matched:
[email protected]127f18ec2012-06-16 05:05:59560 problems = warnings;
561 if error:
562 problems = errors;
563 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
564 for message_line in message:
565 problems.append(' %s' % message_line)
566
567 result = []
568 if (warnings):
569 result.append(output_api.PresubmitPromptWarning(
570 'Banned functions were used.\n' + '\n'.join(warnings)))
571 if (errors):
572 result.append(output_api.PresubmitError(
573 'Banned functions were used.\n' + '\n'.join(errors)))
574 return result
575
576
[email protected]6c063c62012-07-11 19:11:06577def _CheckNoPragmaOnce(input_api, output_api):
578 """Make sure that banned functions are not used."""
579 files = []
580 pattern = input_api.re.compile(r'^#pragma\s+once',
581 input_api.re.MULTILINE)
582 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
583 if not f.LocalPath().endswith('.h'):
584 continue
585 contents = input_api.ReadFile(f)
586 if pattern.search(contents):
587 files.append(f)
588
589 if files:
590 return [output_api.PresubmitError(
591 'Do not use #pragma once in header files.\n'
592 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
593 files)]
594 return []
595
[email protected]127f18ec2012-06-16 05:05:59596
[email protected]e7479052012-09-19 00:26:12597def _CheckNoTrinaryTrueFalse(input_api, output_api):
598 """Checks to make sure we don't introduce use of foo ? true : false."""
599 problems = []
600 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
601 for f in input_api.AffectedFiles():
602 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
603 continue
604
605 for line_num, line in f.ChangedContents():
606 if pattern.match(line):
607 problems.append(' %s:%d' % (f.LocalPath(), line_num))
608
609 if not problems:
610 return []
611 return [output_api.PresubmitPromptWarning(
612 'Please consider avoiding the "? true : false" pattern if possible.\n' +
613 '\n'.join(problems))]
614
615
[email protected]55f9f382012-07-31 11:02:18616def _CheckUnwantedDependencies(input_api, output_api):
617 """Runs checkdeps on #include statements added in this
618 change. Breaking - rules is an error, breaking ! rules is a
619 warning.
620 """
mohan.reddyf21db962014-10-16 12:26:47621 import sys
[email protected]55f9f382012-07-31 11:02:18622 # We need to wait until we have an input_api object and use this
623 # roundabout construct to import checkdeps because this file is
624 # eval-ed and thus doesn't have __file__.
625 original_sys_path = sys.path
626 try:
627 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47628 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18629 import checkdeps
630 from cpp_checker import CppChecker
631 from rules import Rule
632 finally:
633 # Restore sys.path to what it was before.
634 sys.path = original_sys_path
635
636 added_includes = []
637 for f in input_api.AffectedFiles():
638 if not CppChecker.IsCppFile(f.LocalPath()):
639 continue
640
641 changed_lines = [line for line_num, line in f.ChangedContents()]
642 added_includes.append([f.LocalPath(), changed_lines])
643
[email protected]26385172013-05-09 23:11:35644 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18645
646 error_descriptions = []
647 warning_descriptions = []
648 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
649 added_includes):
650 description_with_path = '%s\n %s' % (path, rule_description)
651 if rule_type == Rule.DISALLOW:
652 error_descriptions.append(description_with_path)
653 else:
654 warning_descriptions.append(description_with_path)
655
656 results = []
657 if error_descriptions:
658 results.append(output_api.PresubmitError(
659 'You added one or more #includes that violate checkdeps rules.',
660 error_descriptions))
661 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42662 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18663 'You added one or more #includes of files that are temporarily\n'
664 'allowed but being removed. Can you avoid introducing the\n'
665 '#include? See relevant DEPS file(s) for details and contacts.',
666 warning_descriptions))
667 return results
668
669
[email protected]fbcafe5a2012-08-08 15:31:22670def _CheckFilePermissions(input_api, output_api):
671 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15672 if input_api.platform == 'win32':
673 return []
mohan.reddyf21db962014-10-16 12:26:47674 args = [input_api.python_executable, 'tools/checkperms/checkperms.py',
675 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22676 for f in input_api.AffectedFiles():
677 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11678 try:
679 input_api.subprocess.check_output(args)
680 return []
681 except input_api.subprocess.CalledProcessError as error:
682 return [output_api.PresubmitError(
683 'checkperms.py failed:',
684 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22685
686
[email protected]c8278b32012-10-30 20:35:49687def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
688 """Makes sure we don't include ui/aura/window_property.h
689 in header files.
690 """
691 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
692 errors = []
693 for f in input_api.AffectedFiles():
694 if not f.LocalPath().endswith('.h'):
695 continue
696 for line_num, line in f.ChangedContents():
697 if pattern.match(line):
698 errors.append(' %s:%d' % (f.LocalPath(), line_num))
699
700 results = []
701 if errors:
702 results.append(output_api.PresubmitError(
703 'Header files should not include ui/aura/window_property.h', errors))
704 return results
705
706
[email protected]cf9b78f2012-11-14 11:40:28707def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
708 """Checks that the lines in scope occur in the right order.
709
710 1. C system files in alphabetical order
711 2. C++ system files in alphabetical order
712 3. Project's .h files
713 """
714
715 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
716 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
717 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
718
719 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
720
721 state = C_SYSTEM_INCLUDES
722
723 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57724 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28725 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55726 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28727 for line_num, line in scope:
728 if c_system_include_pattern.match(line):
729 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55730 problem_linenums.append((line_num, previous_line_num,
731 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28732 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55733 problem_linenums.append((line_num, previous_line_num,
734 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28735 elif cpp_system_include_pattern.match(line):
736 if state == C_SYSTEM_INCLUDES:
737 state = CPP_SYSTEM_INCLUDES
738 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55739 problem_linenums.append((line_num, previous_line_num,
740 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28741 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55742 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28743 elif custom_include_pattern.match(line):
744 if state != CUSTOM_INCLUDES:
745 state = CUSTOM_INCLUDES
746 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55747 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28748 else:
brucedawson70fadb02015-06-30 17:47:55749 problem_linenums.append((line_num, previous_line_num,
750 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28751 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57752 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28753
754 warnings = []
brucedawson70fadb02015-06-30 17:47:55755 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57756 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55757 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28758 return warnings
759
760
[email protected]ac294a12012-12-06 16:38:43761def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28762 """Checks the #include order for the given file f."""
763
[email protected]2299dcf2012-11-15 19:56:24764 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30765 # Exclude the following includes from the check:
766 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
767 # specific order.
768 # 2) <atlbase.h>, "build/build_config.h"
769 excluded_include_pattern = input_api.re.compile(
770 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24771 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33772 # Match the final or penultimate token if it is xxxtest so we can ignore it
773 # when considering the special first include.
774 test_file_tag_pattern = input_api.re.compile(
775 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11776 if_pattern = input_api.re.compile(
777 r'\s*#\s*(if|elif|else|endif|define|undef).*')
778 # Some files need specialized order of includes; exclude such files from this
779 # check.
780 uncheckable_includes_pattern = input_api.re.compile(
781 r'\s*#include '
782 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28783
784 contents = f.NewContents()
785 warnings = []
786 line_num = 0
787
[email protected]ac294a12012-12-06 16:38:43788 # Handle the special first include. If the first include file is
789 # some/path/file.h, the corresponding including file can be some/path/file.cc,
790 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
791 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33792 # If the included file is some/path/file_platform.h the including file could
793 # also be some/path/file_xxxtest_platform.h.
794 including_file_base_name = test_file_tag_pattern.sub(
795 '', input_api.os_path.basename(f.LocalPath()))
796
[email protected]ac294a12012-12-06 16:38:43797 for line in contents:
798 line_num += 1
799 if system_include_pattern.match(line):
800 # No special first include -> process the line again along with normal
801 # includes.
802 line_num -= 1
803 break
804 match = custom_include_pattern.match(line)
805 if match:
806 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33807 header_basename = test_file_tag_pattern.sub(
808 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
809
810 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24811 # No special first include -> process the line again along with normal
812 # includes.
813 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43814 break
[email protected]cf9b78f2012-11-14 11:40:28815
816 # Split into scopes: Each region between #if and #endif is its own scope.
817 scopes = []
818 current_scope = []
819 for line in contents[line_num:]:
820 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11821 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54822 continue
[email protected]2309b0fa02012-11-16 12:18:27823 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28824 scopes.append(current_scope)
825 current_scope = []
[email protected]962f117e2012-11-22 18:11:56826 elif ((system_include_pattern.match(line) or
827 custom_include_pattern.match(line)) and
828 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28829 current_scope.append((line_num, line))
830 scopes.append(current_scope)
831
832 for scope in scopes:
833 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
834 changed_linenums))
835 return warnings
836
837
838def _CheckIncludeOrder(input_api, output_api):
839 """Checks that the #include order is correct.
840
841 1. The corresponding header for source files.
842 2. C system files in alphabetical order
843 3. C++ system files in alphabetical order
844 4. Project's .h files in alphabetical order
845
[email protected]ac294a12012-12-06 16:38:43846 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
847 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28848 """
[email protected]e120b012014-08-15 19:08:35849 def FileFilterIncludeOrder(affected_file):
850 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
851 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28852
853 warnings = []
[email protected]e120b012014-08-15 19:08:35854 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08855 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43856 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
857 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28858
859 results = []
860 if warnings:
[email protected]f7051d52013-04-02 18:31:42861 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53862 warnings))
[email protected]cf9b78f2012-11-14 11:40:28863 return results
864
865
[email protected]70ca77752012-11-20 03:45:03866def _CheckForVersionControlConflictsInFile(input_api, f):
867 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
868 errors = []
869 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23870 if f.LocalPath().endswith('.md'):
871 # First-level headers in markdown look a lot like version control
872 # conflict markers. http://daringfireball.net/projects/markdown/basics
873 continue
[email protected]70ca77752012-11-20 03:45:03874 if pattern.match(line):
875 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
876 return errors
877
878
879def _CheckForVersionControlConflicts(input_api, output_api):
880 """Usually this is not intentional and will cause a compile failure."""
881 errors = []
882 for f in input_api.AffectedFiles():
883 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
884
885 results = []
886 if errors:
887 results.append(output_api.PresubmitError(
888 'Version control conflict markers found, please resolve.', errors))
889 return results
890
891
[email protected]06e6d0ff2012-12-11 01:36:44892def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
893 def FilterFile(affected_file):
894 """Filter function for use with input_api.AffectedSourceFiles,
895 below. This filters out everything except non-test files from
896 top-level directories that generally speaking should not hard-code
897 service URLs (e.g. src/android_webview/, src/content/ and others).
898 """
899 return input_api.FilterSourceFile(
900 affected_file,
[email protected]78bb39d62012-12-11 15:11:56901 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44902 black_list=(_EXCLUDED_PATHS +
903 _TEST_CODE_EXCLUDED_PATHS +
904 input_api.DEFAULT_BLACK_LIST))
905
reillyi38965732015-11-16 18:27:33906 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
907 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46908 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
909 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44910 problems = [] # items are (filename, line_number, line)
911 for f in input_api.AffectedSourceFiles(FilterFile):
912 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46913 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44914 problems.append((f.LocalPath(), line_num, line))
915
916 if problems:
[email protected]f7051d52013-04-02 18:31:42917 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44918 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58919 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44920 [' %s:%d: %s' % (
921 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03922 else:
923 return []
[email protected]06e6d0ff2012-12-11 01:36:44924
925
[email protected]d2530012013-01-25 16:39:27926def _CheckNoAbbreviationInPngFileName(input_api, output_api):
927 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31928 The native_client_sdk directory is excluded because it has auto-generated PNG
929 files for documentation.
[email protected]d2530012013-01-25 16:39:27930 """
[email protected]d2530012013-01-25 16:39:27931 errors = []
binji0dcdf342014-12-12 18:32:31932 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
933 black_list = (r'^native_client_sdk[\\\/]',)
934 file_filter = lambda f: input_api.FilterSourceFile(
935 f, white_list=white_list, black_list=black_list)
936 for f in input_api.AffectedFiles(include_deletes=False,
937 file_filter=file_filter):
938 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27939
940 results = []
941 if errors:
942 results.append(output_api.PresubmitError(
943 'The name of PNG files should not have abbreviations. \n'
944 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
945 'Contact [email protected] if you have questions.', errors))
946 return results
947
948
[email protected]14a6131c2014-01-08 01:15:41949def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:08950 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:41951 a set of DEPS entries that we should look up.
952
953 For a directory (rather than a specific filename) we fake a path to
954 a specific filename by adding /DEPS. This is chosen as a file that
955 will seldom or never be subject to per-file include_rules.
956 """
[email protected]2b438d62013-11-14 17:54:14957 # We ignore deps entries on auto-generated directories.
958 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:08959
960 # This pattern grabs the path without basename in the first
961 # parentheses, and the basename (if present) in the second. It
962 # relies on the simple heuristic that if there is a basename it will
963 # be a header file ending in ".h".
964 pattern = re.compile(
965 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:14966 results = set()
[email protected]f32e2d1e2013-07-26 21:39:08967 for changed_line in changed_lines:
968 m = pattern.match(changed_line)
969 if m:
970 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:14971 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:41972 if m.group(2):
973 results.add('%s%s' % (path, m.group(2)))
974 else:
975 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:08976 return results
977
978
[email protected]e871964c2013-05-13 14:14:55979def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
980 """When a dependency prefixed with + is added to a DEPS file, we
981 want to make sure that the change is reviewed by an OWNER of the
982 target file or directory, to avoid layering violations from being
983 introduced. This check verifies that this happens.
984 """
985 changed_lines = set()
jochen53efcdd2016-01-29 05:09:24986
987 file_filter = lambda f: not input_api.re.match(
988 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
989 for f in input_api.AffectedFiles(include_deletes=False,
990 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:55991 filename = input_api.os_path.basename(f.LocalPath())
992 if filename == 'DEPS':
993 changed_lines |= set(line.strip()
994 for line_num, line
995 in f.ChangedContents())
996 if not changed_lines:
997 return []
998
[email protected]14a6131c2014-01-08 01:15:41999 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1000 changed_lines)
[email protected]e871964c2013-05-13 14:14:551001 if not virtual_depended_on_files:
1002 return []
1003
1004 if input_api.is_committing:
1005 if input_api.tbr:
1006 return [output_api.PresubmitNotifyResult(
1007 '--tbr was specified, skipping OWNERS check for DEPS additions')]
1008 if not input_api.change.issue:
1009 return [output_api.PresubmitError(
1010 "DEPS approval by OWNERS check failed: this change has "
1011 "no Rietveld issue number, so we can't check it for approvals.")]
1012 output = output_api.PresubmitError
1013 else:
1014 output = output_api.PresubmitNotifyResult
1015
1016 owners_db = input_api.owners_db
1017 owner_email, reviewers = input_api.canned_checks._RietveldOwnerAndReviewers(
1018 input_api,
1019 owners_db.email_regexp,
1020 approval_needed=input_api.is_committing)
1021
1022 owner_email = owner_email or input_api.change.author_email
1023
[email protected]de4f7d22013-05-23 14:27:461024 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511025 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461026 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551027 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1028 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411029
1030 # We strip the /DEPS part that was added by
1031 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1032 # directory.
1033 def StripDeps(path):
1034 start_deps = path.rfind('/DEPS')
1035 if start_deps != -1:
1036 return path[:start_deps]
1037 else:
1038 return path
1039 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551040 for path in missing_files]
1041
1042 if unapproved_dependencies:
1043 output_list = [
[email protected]14a6131c2014-01-08 01:15:411044 output('Missing LGTM from OWNERS of dependencies added to DEPS:\n %s' %
[email protected]e871964c2013-05-13 14:14:551045 '\n '.join(sorted(unapproved_dependencies)))]
1046 if not input_api.is_committing:
1047 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1048 output_list.append(output(
1049 'Suggested missing target path OWNERS:\n %s' %
1050 '\n '.join(suggested_owners or [])))
1051 return output_list
1052
1053 return []
1054
1055
[email protected]85218562013-11-22 07:41:401056def _CheckSpamLogging(input_api, output_api):
1057 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1058 black_list = (_EXCLUDED_PATHS +
1059 _TEST_CODE_EXCLUDED_PATHS +
1060 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501061 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191062 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481063 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461064 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121065 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1066 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581067 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161068 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031069 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151070 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1071 r"^chromecast[\\\/]",
1072 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311073 r"^components[\\\/]html_viewer[\\\/]"
1074 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461075 # TODO(peter): Remove this exception. https://crbug.com/534537
1076 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1077 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251078 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1079 r"gl_helper_benchmark\.cc$",
thestigc9e38a22014-09-13 01:02:111080 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151081 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111082 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521083 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501084 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361085 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311086 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131087 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441088 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451089 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021090 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441091 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401092 source_file_filter = lambda x: input_api.FilterSourceFile(
1093 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1094
1095 log_info = []
1096 printf = []
1097
1098 for f in input_api.AffectedSourceFiles(source_file_filter):
1099 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471100 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401101 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471102 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131103 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371104
mohan.reddyf21db962014-10-16 12:26:471105 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371106 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471107 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401108 printf.append(f.LocalPath())
1109
1110 if log_info:
1111 return [output_api.PresubmitError(
1112 'These files spam the console log with LOG(INFO):',
1113 items=log_info)]
1114 if printf:
1115 return [output_api.PresubmitError(
1116 'These files spam the console log with printf/fprintf:',
1117 items=printf)]
1118 return []
1119
1120
[email protected]49aa76a2013-12-04 06:59:161121def _CheckForAnonymousVariables(input_api, output_api):
1122 """These types are all expected to hold locks while in scope and
1123 so should never be anonymous (which causes them to be immediately
1124 destroyed)."""
1125 they_who_must_be_named = [
1126 'base::AutoLock',
1127 'base::AutoReset',
1128 'base::AutoUnlock',
1129 'SkAutoAlphaRestore',
1130 'SkAutoBitmapShaderInstall',
1131 'SkAutoBlitterChoose',
1132 'SkAutoBounderCommit',
1133 'SkAutoCallProc',
1134 'SkAutoCanvasRestore',
1135 'SkAutoCommentBlock',
1136 'SkAutoDescriptor',
1137 'SkAutoDisableDirectionCheck',
1138 'SkAutoDisableOvalCheck',
1139 'SkAutoFree',
1140 'SkAutoGlyphCache',
1141 'SkAutoHDC',
1142 'SkAutoLockColors',
1143 'SkAutoLockPixels',
1144 'SkAutoMalloc',
1145 'SkAutoMaskFreeImage',
1146 'SkAutoMutexAcquire',
1147 'SkAutoPathBoundsUpdate',
1148 'SkAutoPDFRelease',
1149 'SkAutoRasterClipValidate',
1150 'SkAutoRef',
1151 'SkAutoTime',
1152 'SkAutoTrace',
1153 'SkAutoUnref',
1154 ]
1155 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1156 # bad: base::AutoLock(lock.get());
1157 # not bad: base::AutoLock lock(lock.get());
1158 bad_pattern = input_api.re.compile(anonymous)
1159 # good: new base::AutoLock(lock.get())
1160 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1161 errors = []
1162
1163 for f in input_api.AffectedFiles():
1164 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1165 continue
1166 for linenum, line in f.ChangedContents():
1167 if bad_pattern.search(line) and not good_pattern.search(line):
1168 errors.append('%s:%d' % (f.LocalPath(), linenum))
1169
1170 if errors:
1171 return [output_api.PresubmitError(
1172 'These lines create anonymous variables that need to be named:',
1173 items=errors)]
1174 return []
1175
1176
[email protected]5fe0f8742013-11-29 01:04:591177def _CheckCygwinShell(input_api, output_api):
1178 source_file_filter = lambda x: input_api.FilterSourceFile(
1179 x, white_list=(r'.+\.(gyp|gypi)$',))
1180 cygwin_shell = []
1181
1182 for f in input_api.AffectedSourceFiles(source_file_filter):
1183 for linenum, line in f.ChangedContents():
1184 if 'msvs_cygwin_shell' in line:
1185 cygwin_shell.append(f.LocalPath())
1186 break
1187
1188 if cygwin_shell:
1189 return [output_api.PresubmitError(
1190 'These files should not use msvs_cygwin_shell (the default is 0):',
1191 items=cygwin_shell)]
1192 return []
1193
[email protected]85218562013-11-22 07:41:401194
[email protected]999261d2014-03-03 20:08:081195def _CheckUserActionUpdate(input_api, output_api):
1196 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521197 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081198 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521199 # If actions.xml is already included in the changelist, the PRESUBMIT
1200 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081201 return []
1202
[email protected]999261d2014-03-03 20:08:081203 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1204 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521205 current_actions = None
[email protected]999261d2014-03-03 20:08:081206 for f in input_api.AffectedFiles(file_filter=file_filter):
1207 for line_num, line in f.ChangedContents():
1208 match = input_api.re.search(action_re, line)
1209 if match:
[email protected]2f92dec2014-03-07 19:21:521210 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1211 # loaded only once.
1212 if not current_actions:
1213 with open('tools/metrics/actions/actions.xml') as actions_f:
1214 current_actions = actions_f.read()
1215 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081216 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521217 action = 'name="{0}"'.format(action_name)
1218 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081219 return [output_api.PresubmitPromptWarning(
1220 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521221 'tools/metrics/actions/actions.xml. Please run '
1222 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081223 % (f.LocalPath(), line_num, action_name))]
1224 return []
1225
1226
[email protected]99171a92014-06-03 08:44:471227def _GetJSONParseError(input_api, filename, eat_comments=True):
1228 try:
1229 contents = input_api.ReadFile(filename)
1230 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131231 import sys
1232 original_sys_path = sys.path
1233 try:
1234 sys.path = sys.path + [input_api.os_path.join(
1235 input_api.PresubmitLocalPath(),
1236 'tools', 'json_comment_eater')]
1237 import json_comment_eater
1238 finally:
1239 sys.path = original_sys_path
1240 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471241
1242 input_api.json.loads(contents)
1243 except ValueError as e:
1244 return e
1245 return None
1246
1247
1248def _GetIDLParseError(input_api, filename):
1249 try:
1250 contents = input_api.ReadFile(filename)
1251 idl_schema = input_api.os_path.join(
1252 input_api.PresubmitLocalPath(),
1253 'tools', 'json_schema_compiler', 'idl_schema.py')
1254 process = input_api.subprocess.Popen(
1255 [input_api.python_executable, idl_schema],
1256 stdin=input_api.subprocess.PIPE,
1257 stdout=input_api.subprocess.PIPE,
1258 stderr=input_api.subprocess.PIPE,
1259 universal_newlines=True)
1260 (_, error) = process.communicate(input=contents)
1261 return error or None
1262 except ValueError as e:
1263 return e
1264
1265
1266def _CheckParseErrors(input_api, output_api):
1267 """Check that IDL and JSON files do not contain syntax errors."""
1268 actions = {
1269 '.idl': _GetIDLParseError,
1270 '.json': _GetJSONParseError,
1271 }
1272 # These paths contain test data and other known invalid JSON files.
1273 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491274 r'test[\\\/]data[\\\/]',
1275 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471276 ]
1277 # Most JSON files are preprocessed and support comments, but these do not.
1278 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491279 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471280 ]
1281 # Only run IDL checker on files in these directories.
1282 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491283 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1284 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471285 ]
1286
1287 def get_action(affected_file):
1288 filename = affected_file.LocalPath()
1289 return actions.get(input_api.os_path.splitext(filename)[1])
1290
1291 def MatchesFile(patterns, path):
1292 for pattern in patterns:
1293 if input_api.re.search(pattern, path):
1294 return True
1295 return False
1296
1297 def FilterFile(affected_file):
1298 action = get_action(affected_file)
1299 if not action:
1300 return False
1301 path = affected_file.LocalPath()
1302
1303 if MatchesFile(excluded_patterns, path):
1304 return False
1305
1306 if (action == _GetIDLParseError and
1307 not MatchesFile(idl_included_patterns, path)):
1308 return False
1309 return True
1310
1311 results = []
1312 for affected_file in input_api.AffectedFiles(
1313 file_filter=FilterFile, include_deletes=False):
1314 action = get_action(affected_file)
1315 kwargs = {}
1316 if (action == _GetJSONParseError and
1317 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1318 kwargs['eat_comments'] = False
1319 parse_error = action(input_api,
1320 affected_file.AbsoluteLocalPath(),
1321 **kwargs)
1322 if parse_error:
1323 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1324 (affected_file.LocalPath(), parse_error)))
1325 return results
1326
1327
[email protected]760deea2013-12-10 19:33:491328def _CheckJavaStyle(input_api, output_api):
1329 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471330 import sys
[email protected]760deea2013-12-10 19:33:491331 original_sys_path = sys.path
1332 try:
1333 sys.path = sys.path + [input_api.os_path.join(
1334 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1335 import checkstyle
1336 finally:
1337 # Restore sys.path to what it was before.
1338 sys.path = original_sys_path
1339
1340 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091341 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511342 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491343
1344
dskiba88634f4e2015-08-14 23:03:291345def _CheckAndroidToastUsage(input_api, output_api):
1346 """Checks that code uses org.chromium.ui.widget.Toast instead of
1347 android.widget.Toast (Chromium Toast doesn't force hardware
1348 acceleration on low-end devices, saving memory).
1349 """
1350 toast_import_pattern = input_api.re.compile(
1351 r'^import android\.widget\.Toast;$')
1352
1353 errors = []
1354
1355 sources = lambda affected_file: input_api.FilterSourceFile(
1356 affected_file,
1357 black_list=(_EXCLUDED_PATHS +
1358 _TEST_CODE_EXCLUDED_PATHS +
1359 input_api.DEFAULT_BLACK_LIST +
1360 (r'^chromecast[\\\/].*',
1361 r'^remoting[\\\/].*')),
1362 white_list=(r'.*\.java$',))
1363
1364 for f in input_api.AffectedSourceFiles(sources):
1365 for line_num, line in f.ChangedContents():
1366 if toast_import_pattern.search(line):
1367 errors.append("%s:%d" % (f.LocalPath(), line_num))
1368
1369 results = []
1370
1371 if errors:
1372 results.append(output_api.PresubmitError(
1373 'android.widget.Toast usage is detected. Android toasts use hardware'
1374 ' acceleration, and can be\ncostly on low-end devices. Please use'
1375 ' org.chromium.ui.widget.Toast instead.\n'
1376 'Contact [email protected] if you have any questions.',
1377 errors))
1378
1379 return results
1380
1381
dgnaa68d5e2015-06-10 10:08:221382def _CheckAndroidCrLogUsage(input_api, output_api):
1383 """Checks that new logs using org.chromium.base.Log:
1384 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511385 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221386 """
1387 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121388 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1389 class_in_base_pattern = input_api.re.compile(
1390 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1391 has_some_log_import_pattern = input_api.re.compile(
1392 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221393 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121394 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221395 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511396 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221397 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221398
Vincent Scheib16d7b272015-09-15 18:09:071399 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221400 'or contact [email protected] for more info.')
1401 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',))
dgn87d9fb62015-06-12 09:15:121402
dgnaa68d5e2015-06-10 10:08:221403 tag_decl_errors = []
1404 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121405 tag_errors = []
dgn38736db2015-09-18 19:20:511406 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121407 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221408
1409 for f in input_api.AffectedSourceFiles(sources):
1410 file_content = input_api.ReadFile(f)
1411 has_modified_logs = False
1412
1413 # Per line checks
dgn87d9fb62015-06-12 09:15:121414 if (cr_log_import_pattern.search(file_content) or
1415 (class_in_base_pattern.search(file_content) and
1416 not has_some_log_import_pattern.search(file_content))):
1417 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221418 for line_num, line in f.ChangedContents():
1419
1420 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121421 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221422 if match:
1423 has_modified_logs = True
1424
1425 # Make sure it uses "TAG"
1426 if not match.group('tag') == 'TAG':
1427 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121428 else:
1429 # Report non cr Log function calls in changed lines
1430 for line_num, line in f.ChangedContents():
1431 if log_call_pattern.search(line):
1432 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221433
1434 # Per file checks
1435 if has_modified_logs:
1436 # Make sure the tag is using the "cr" prefix and is not too long
1437 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511438 tag_name = match.group('name') if match else None
1439 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221440 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511441 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221442 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511443 elif '.' in tag_name:
1444 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221445
1446 results = []
1447 if tag_decl_errors:
1448 results.append(output_api.PresubmitPromptWarning(
1449 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511450 '"private static final String TAG = "<package tag>".\n'
1451 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221452 tag_decl_errors))
1453
1454 if tag_length_errors:
1455 results.append(output_api.PresubmitError(
1456 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511457 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221458 tag_length_errors))
1459
1460 if tag_errors:
1461 results.append(output_api.PresubmitPromptWarning(
1462 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1463 tag_errors))
1464
dgn87d9fb62015-06-12 09:15:121465 if util_log_errors:
dgn4401aa52015-04-29 16:26:171466 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121467 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1468 util_log_errors))
1469
dgn38736db2015-09-18 19:20:511470 if tag_with_dot_errors:
1471 results.append(output_api.PresubmitPromptWarning(
1472 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1473 tag_with_dot_errors))
1474
dgn4401aa52015-04-29 16:26:171475 return results
1476
1477
agrieve7b6479d82015-10-07 14:24:221478def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1479 """Checks if MDPI assets are placed in a correct directory."""
1480 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1481 ('/res/drawable/' in f.LocalPath() or
1482 '/res/drawable-ldrtl/' in f.LocalPath()))
1483 errors = []
1484 for f in input_api.AffectedFiles(include_deletes=False,
1485 file_filter=file_filter):
1486 errors.append(' %s' % f.LocalPath())
1487
1488 results = []
1489 if errors:
1490 results.append(output_api.PresubmitError(
1491 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1492 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1493 '/res/drawable-ldrtl/.\n'
1494 'Contact [email protected] if you have questions.', errors))
1495 return results
1496
1497
mnaganov9b9b1fe82014-12-11 16:30:361498def _CheckForCopyrightedCode(input_api, output_api):
1499 """Verifies that newly added code doesn't contain copyrighted material
1500 and is properly licensed under the standard Chromium license.
1501
1502 As there can be false positives, we maintain a whitelist file. This check
1503 also verifies that the whitelist file is up to date.
1504 """
1505 import sys
1506 original_sys_path = sys.path
1507 try:
1508 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221509 input_api.PresubmitLocalPath(), 'tools')]
1510 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361511 finally:
1512 # Restore sys.path to what it was before.
1513 sys.path = original_sys_path
1514
1515 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1516
1517
glidere61efad2015-02-18 17:39:431518def _CheckSingletonInHeaders(input_api, output_api):
1519 """Checks to make sure no header files have |Singleton<|."""
1520 def FileFilter(affected_file):
1521 # It's ok for base/memory/singleton.h to have |Singleton<|.
1522 black_list = (_EXCLUDED_PATHS +
1523 input_api.DEFAULT_BLACK_LIST +
1524 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1525 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1526
sergeyu34d21222015-09-16 00:11:441527 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431528 files = []
1529 for f in input_api.AffectedSourceFiles(FileFilter):
1530 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1531 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1532 contents = input_api.ReadFile(f)
1533 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241534 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431535 pattern.search(line)):
1536 files.append(f)
1537 break
1538
1539 if files:
1540 return [ output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441541 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431542 'Please move them to an appropriate source file so that the ' +
1543 'template gets instantiated in a single compilation unit.',
1544 files) ]
1545 return []
1546
1547
dbeam37e8e7402016-02-10 22:58:201548def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1549 """Checks for old style compiled_resources.gyp files."""
1550 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1551
1552 added_compiled_resources = filter(is_compiled_resource, [
1553 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1554 ])
1555
1556 if not added_compiled_resources:
1557 return []
1558
1559 return [output_api.PresubmitError(
1560 "Found new compiled_resources.gyp files:\n%s\n\n"
1561 "compiled_resources.gyp files are deprecated,\n"
1562 "please use compiled_resources2.gyp instead" %
1563 "\n".join(added_compiled_resources))]
1564
1565
[email protected]fd20b902014-05-09 02:14:531566_DEPRECATED_CSS = [
1567 # Values
1568 ( "-webkit-box", "flex" ),
1569 ( "-webkit-inline-box", "inline-flex" ),
1570 ( "-webkit-flex", "flex" ),
1571 ( "-webkit-inline-flex", "inline-flex" ),
1572 ( "-webkit-min-content", "min-content" ),
1573 ( "-webkit-max-content", "max-content" ),
1574
1575 # Properties
1576 ( "-webkit-background-clip", "background-clip" ),
1577 ( "-webkit-background-origin", "background-origin" ),
1578 ( "-webkit-background-size", "background-size" ),
1579 ( "-webkit-box-shadow", "box-shadow" ),
1580
1581 # Functions
1582 ( "-webkit-gradient", "gradient" ),
1583 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1584 ( "-webkit-linear-gradient", "linear-gradient" ),
1585 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1586 ( "-webkit-radial-gradient", "radial-gradient" ),
1587 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1588]
1589
1590def _CheckNoDeprecatedCSS(input_api, output_api):
1591 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251592 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341593 documentation and iOS CSS for dom distiller
1594 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251595 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531596 results = []
dbeam070cfe62014-10-22 06:44:021597 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251598 black_list = (_EXCLUDED_PATHS +
1599 _TEST_CODE_EXCLUDED_PATHS +
1600 input_api.DEFAULT_BLACK_LIST +
1601 (r"^chrome/common/extensions/docs",
1602 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341603 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051604 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441605 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251606 r"^native_client_sdk"))
1607 file_filter = lambda f: input_api.FilterSourceFile(
1608 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531609 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1610 for line_num, line in fpath.ChangedContents():
1611 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021612 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531613 results.append(output_api.PresubmitError(
1614 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1615 (fpath.LocalPath(), line_num, deprecated_value, value)))
1616 return results
1617
mohan.reddyf21db962014-10-16 12:26:471618
dbeam070cfe62014-10-22 06:44:021619_DEPRECATED_JS = [
1620 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1621 ( "__defineGetter__", "Object.defineProperty" ),
1622 ( "__defineSetter__", "Object.defineProperty" ),
1623]
1624
1625def _CheckNoDeprecatedJS(input_api, output_api):
1626 """Make sure that we don't use deprecated JS in Chrome code."""
1627 results = []
1628 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1629 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1630 input_api.DEFAULT_BLACK_LIST)
1631 file_filter = lambda f: input_api.FilterSourceFile(
1632 f, white_list=file_inclusion_pattern, black_list=black_list)
1633 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1634 for lnum, line in fpath.ChangedContents():
1635 for (deprecated, replacement) in _DEPRECATED_JS:
1636 if deprecated in line:
1637 results.append(output_api.PresubmitError(
1638 "%s:%d: Use of deprecated JS %s, use %s instead" %
1639 (fpath.LocalPath(), lnum, deprecated, replacement)))
1640 return results
1641
1642
dgnaa68d5e2015-06-10 10:08:221643def _AndroidSpecificOnUploadChecks(input_api, output_api):
1644 """Groups checks that target android code."""
1645 results = []
dgnaa68d5e2015-06-10 10:08:221646 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221647 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291648 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221649 return results
1650
1651
[email protected]22c9bd72011-03-27 16:47:391652def _CommonChecks(input_api, output_api):
1653 """Checks common to both upload and commit."""
1654 results = []
1655 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381656 input_api, output_api,
1657 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461658 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191659 results.extend(
[email protected]760deea2013-12-10 19:33:491660 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541661 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181662 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521663 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221664 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441665 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591666 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061667 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121668 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181669 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221670 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491671 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271672 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031673 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491674 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441675 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271676 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541677 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441678 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
danakj3c84d0c2014-10-06 15:35:461679 # TODO(danakj): Remove this when base/move.h is removed.
dchengcf95c122015-12-18 08:29:161680 results.extend(_CheckForUsingPass(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551681 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041682 results.extend(
1683 input_api.canned_checks.CheckChangeHasNoTabs(
1684 input_api,
1685 output_api,
1686 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401687 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161688 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591689 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081690 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531691 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021692 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471693 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041694 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361695 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231696 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431697 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201698 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241699
1700 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1701 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1702 input_api, output_api,
1703 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381704 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391705 return results
[email protected]1f7b4172010-01-28 01:17:341706
[email protected]b337cb5b2011-01-23 21:24:051707
[email protected]66daa702011-05-28 14:41:461708def _CheckAuthorizedAuthor(input_api, output_api):
1709 """For non-googler/chromites committers, verify the author's email address is
1710 in AUTHORS.
1711 """
[email protected]9bb9cb82011-06-13 20:43:011712 # TODO(maruel): Add it to input_api?
1713 import fnmatch
1714
[email protected]66daa702011-05-28 14:41:461715 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011716 if not author:
1717 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461718 return []
[email protected]c99663292011-05-31 19:46:081719 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461720 input_api.PresubmitLocalPath(), 'AUTHORS')
1721 valid_authors = (
1722 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1723 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181724 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]d8b50be2011-06-15 14:19:441725 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231726 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461727 return [output_api.PresubmitPromptWarning(
1728 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1729 '\n'
1730 'http://www.chromium.org/developers/contributing-code and read the '
1731 '"Legal" section\n'
1732 'If you are a chromite, verify the contributor signed the CLA.') %
1733 author)]
1734 return []
1735
1736
[email protected]b8079ae4a2012-12-05 19:56:491737def _CheckPatchFiles(input_api, output_api):
1738 problems = [f.LocalPath() for f in input_api.AffectedFiles()
1739 if f.LocalPath().endswith(('.orig', '.rej'))]
1740 if problems:
1741 return [output_api.PresubmitError(
1742 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:031743 else:
1744 return []
[email protected]b8079ae4a2012-12-05 19:56:491745
1746
[email protected]b00342e7f2013-03-26 16:21:541747def _DidYouMeanOSMacro(bad_macro):
1748 try:
1749 return {'A': 'OS_ANDROID',
1750 'B': 'OS_BSD',
1751 'C': 'OS_CHROMEOS',
1752 'F': 'OS_FREEBSD',
1753 'L': 'OS_LINUX',
1754 'M': 'OS_MACOSX',
1755 'N': 'OS_NACL',
1756 'O': 'OS_OPENBSD',
1757 'P': 'OS_POSIX',
1758 'S': 'OS_SOLARIS',
1759 'W': 'OS_WIN'}[bad_macro[3].upper()]
1760 except KeyError:
1761 return ''
1762
1763
1764def _CheckForInvalidOSMacrosInFile(input_api, f):
1765 """Check for sensible looking, totally invalid OS macros."""
1766 preprocessor_statement = input_api.re.compile(r'^\s*#')
1767 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
1768 results = []
1769 for lnum, line in f.ChangedContents():
1770 if preprocessor_statement.search(line):
1771 for match in os_macro.finditer(line):
1772 if not match.group(1) in _VALID_OS_MACROS:
1773 good = _DidYouMeanOSMacro(match.group(1))
1774 did_you_mean = ' (did you mean %s?)' % good if good else ''
1775 results.append(' %s:%d %s%s' % (f.LocalPath(),
1776 lnum,
1777 match.group(1),
1778 did_you_mean))
1779 return results
1780
1781
1782def _CheckForInvalidOSMacros(input_api, output_api):
1783 """Check all affected files for invalid OS macros."""
1784 bad_macros = []
1785 for f in input_api.AffectedFiles():
1786 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
1787 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
1788
1789 if not bad_macros:
1790 return []
1791
1792 return [output_api.PresubmitError(
1793 'Possibly invalid OS macro[s] found. Please fix your code\n'
1794 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
1795
lliabraa35bab3932014-10-01 12:16:441796
1797def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
1798 """Check all affected files for invalid "if defined" macros."""
1799 ALWAYS_DEFINED_MACROS = (
1800 "TARGET_CPU_PPC",
1801 "TARGET_CPU_PPC64",
1802 "TARGET_CPU_68K",
1803 "TARGET_CPU_X86",
1804 "TARGET_CPU_ARM",
1805 "TARGET_CPU_MIPS",
1806 "TARGET_CPU_SPARC",
1807 "TARGET_CPU_ALPHA",
1808 "TARGET_IPHONE_SIMULATOR",
1809 "TARGET_OS_EMBEDDED",
1810 "TARGET_OS_IPHONE",
1811 "TARGET_OS_MAC",
1812 "TARGET_OS_UNIX",
1813 "TARGET_OS_WIN32",
1814 )
1815 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
1816 results = []
1817 for lnum, line in f.ChangedContents():
1818 for match in ifdef_macro.finditer(line):
1819 if match.group(1) in ALWAYS_DEFINED_MACROS:
1820 always_defined = ' %s is always defined. ' % match.group(1)
1821 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
1822 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
1823 lnum,
1824 always_defined,
1825 did_you_mean))
1826 return results
1827
1828
1829def _CheckForInvalidIfDefinedMacros(input_api, output_api):
1830 """Check all affected files for invalid "if defined" macros."""
1831 bad_macros = []
1832 for f in input_api.AffectedFiles():
1833 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1834 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
1835
1836 if not bad_macros:
1837 return []
1838
1839 return [output_api.PresubmitError(
1840 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
1841 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
1842 bad_macros)]
1843
1844
dchengcf95c122015-12-18 08:29:161845def _CheckForUsingPass(input_api, output_api):
danakj3c84d0c2014-10-06 15:35:461846 """Check all affected files for using side effects of Pass."""
1847 errors = []
1848 for f in input_api.AffectedFiles():
1849 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1850 for lnum, line in f.ChangedContents():
dchengcf95c122015-12-18 08:29:161851 # Warn on any use of foo.Pass().
1852 if input_api.re.search(r'[a-zA-Z0-9_]+\.Pass\(\)', line):
danakj3c84d0c2014-10-06 15:35:461853 errors.append(output_api.PresubmitError(
dchengcf95c122015-12-18 08:29:161854 ('%s:%d uses Pass(); please use std::move() instead. ' +
1855 'See crbug.com/557422.') % (f.LocalPath(), lnum)))
danakj3c84d0c2014-10-06 15:35:461856 return errors
1857
1858
mlamouria82272622014-09-16 18:45:041859def _CheckForIPCRules(input_api, output_api):
1860 """Check for same IPC rules described in
1861 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
1862 """
1863 base_pattern = r'IPC_ENUM_TRAITS\('
1864 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
1865 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
1866
1867 problems = []
1868 for f in input_api.AffectedSourceFiles(None):
1869 local_path = f.LocalPath()
1870 if not local_path.endswith('.h'):
1871 continue
1872 for line_number, line in f.ChangedContents():
1873 if inclusion_pattern.search(line) and not comment_pattern.search(line):
1874 problems.append(
1875 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1876
1877 if problems:
1878 return [output_api.PresubmitPromptWarning(
1879 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
1880 else:
1881 return []
1882
[email protected]b00342e7f2013-03-26 16:21:541883
mostynbb639aca52015-01-07 20:31:231884def _CheckForWindowsLineEndings(input_api, output_api):
1885 """Check source code and known ascii text files for Windows style line
1886 endings.
1887 """
earthdok1b5e0ee2015-03-10 15:19:101888 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:231889
1890 file_inclusion_pattern = (
1891 known_text_files,
1892 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1893 )
1894
1895 filter = lambda f: input_api.FilterSourceFile(
1896 f, white_list=file_inclusion_pattern, black_list=None)
1897 files = [f.LocalPath() for f in
1898 input_api.AffectedSourceFiles(filter)]
1899
1900 problems = []
1901
1902 for file in files:
1903 fp = open(file, 'r')
1904 for line in fp:
1905 if line.endswith('\r\n'):
1906 problems.append(file)
1907 break
1908 fp.close()
1909
1910 if problems:
1911 return [output_api.PresubmitPromptWarning('Are you sure that you want '
1912 'these files to contain Windows style line endings?\n' +
1913 '\n'.join(problems))]
1914
1915 return []
1916
1917
[email protected]1f7b4172010-01-28 01:17:341918def CheckChangeOnUpload(input_api, output_api):
1919 results = []
1920 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:471921 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
aurimas8d3bc1c52014-10-15 01:02:171922 results.extend(_CheckJavaStyle(input_api, output_api))
scottmg39b29952014-12-08 18:31:281923 results.extend(
1924 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:191925 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221926 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541927 return results
[email protected]ca8d1982009-02-19 16:33:121928
1929
[email protected]1bfb8322014-04-23 01:02:411930def GetTryServerMasterForBot(bot):
1931 """Returns the Try Server master for the given bot.
1932
[email protected]0bb112362014-07-26 04:38:321933 It tries to guess the master from the bot name, but may still fail
1934 and return None. There is no longer a default master.
1935 """
1936 # Potentially ambiguous bot names are listed explicitly.
1937 master_map = {
[email protected]0bb112362014-07-26 04:38:321938 'chromium_presubmit': 'tryserver.chromium.linux',
1939 'blink_presubmit': 'tryserver.chromium.linux',
1940 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:411941 }
[email protected]0bb112362014-07-26 04:38:321942 master = master_map.get(bot)
1943 if not master:
sergiyb37fd293f2015-02-26 06:55:011944 if 'linux' in bot or 'android' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:321945 master = 'tryserver.chromium.linux'
1946 elif 'win' in bot:
1947 master = 'tryserver.chromium.win'
1948 elif 'mac' in bot or 'ios' in bot:
1949 master = 'tryserver.chromium.mac'
1950 return master
[email protected]1bfb8322014-04-23 01:02:411951
1952
Paweł Hajdan, Jr55083782014-12-19 20:32:561953def GetDefaultTryConfigs(bots):
1954 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:011955 """
1956
Paweł Hajdan, Jr55083782014-12-19 20:32:561957 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:411958
1959 # Build up the mapping from tryserver master to bot/test.
1960 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:561961 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:411962 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
1963 return out
[email protected]38c6a512013-12-18 23:48:011964
1965
[email protected]ca8d1982009-02-19 16:33:121966def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:541967 results = []
[email protected]1f7b4172010-01-28 01:17:341968 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541969 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:271970 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:341971 input_api,
1972 output_api,
[email protected]2fdd1f362013-01-16 03:56:031973 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:271974
[email protected]3e4eb112011-01-18 03:29:541975 results.extend(input_api.canned_checks.CheckChangeHasBugField(
1976 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:411977 results.extend(input_api.canned_checks.CheckChangeHasDescription(
1978 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541979 return results