blob: 38dbcd7446c1679d056153429488ec877e24302a [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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$",
marcinjb446acf652016-01-15 22:18:36169 r"^blimp[\\\/]engine[\\\/]browser[\\\/]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$",
sergeyu34d21222015-09-16 00:11:44180 r"^remoting[\\\/]host[\\\/]gnubby_auth_handler_posix\.cc$",
dnicoara171d8c82015-03-05 20:46:18181 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
rjkroegeade43287c2016-01-14 22:12:07182 "drm_display_host_manager_core\.cc$",
[email protected]7345da02012-11-27 14:31:49183 ),
[email protected]23e6cbc2012-06-16 18:51:20184 ),
[email protected]52657f62013-05-20 05:30:31185 (
186 'SkRefPtr',
187 (
188 'The use of SkRefPtr is prohibited. ',
189 'Please use skia::RefPtr instead.'
190 ),
191 True,
192 (),
193 ),
194 (
195 'SkAutoRef',
196 (
197 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
198 'Please use skia::RefPtr instead.'
199 ),
200 True,
201 (),
202 ),
203 (
204 'SkAutoTUnref',
205 (
206 'The use of SkAutoTUnref is dangerous because it implicitly ',
207 'converts to a raw pointer. Please use skia::RefPtr instead.'
208 ),
209 True,
210 (),
211 ),
212 (
213 'SkAutoUnref',
214 (
215 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
216 'because it implicitly converts to a raw pointer. ',
217 'Please use skia::RefPtr instead.'
218 ),
219 True,
220 (),
221 ),
[email protected]d89eec82013-12-03 14:10:59222 (
223 r'/HANDLE_EINTR\(.*close',
224 (
225 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
226 'descriptor will be closed, and it is incorrect to retry the close.',
227 'Either call close directly and ignore its return value, or wrap close',
228 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
229 ),
230 True,
231 (),
232 ),
233 (
234 r'/IGNORE_EINTR\((?!.*close)',
235 (
236 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
237 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
238 ),
239 True,
240 (
241 # Files that #define IGNORE_EINTR.
242 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
243 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
244 ),
245 ),
[email protected]ec5b3f02014-04-04 18:43:43246 (
247 r'/v8::Extension\(',
248 (
249 'Do not introduce new v8::Extensions into the code base, use',
250 'gin::Wrappable instead. See http://crbug.com/334679',
251 ),
252 True,
[email protected]f55c90ee62014-04-12 00:50:03253 (
joaodasilva718f87672014-08-30 09:25:49254 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03255 ),
[email protected]ec5b3f02014-04-04 18:43:43256 ),
skyostilf9469f72015-04-20 10:38:52257 (
sdefresneeaeccc52015-04-22 08:18:32258 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52259 (
260 'MessageLoopProxy is deprecated. ',
261 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
262 ),
263 True,
kinuko59024ce2015-04-21 22:18:30264 (
265 # Internal message_loop related code may still use it.
266 r'^base[\\\/]message_loop[\\\/].*',
267 ),
skyostilf9469f72015-04-20 10:38:52268 ),
[email protected]127f18ec2012-06-16 05:05:59269)
270
mlamouria82272622014-09-16 18:45:04271_IPC_ENUM_TRAITS_DEPRECATED = (
272 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
273 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
274
[email protected]127f18ec2012-06-16 05:05:59275
[email protected]b00342e7f2013-03-26 16:21:54276_VALID_OS_MACROS = (
277 # Please keep sorted.
278 'OS_ANDROID',
279 'OS_BSD',
280 'OS_CAT', # For testing.
281 'OS_CHROMEOS',
282 'OS_FREEBSD',
283 'OS_IOS',
284 'OS_LINUX',
285 'OS_MACOSX',
286 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21287 'OS_NACL_NONSFI',
288 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54289 'OS_OPENBSD',
290 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37291 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54292 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54293 'OS_WIN',
294)
295
296
[email protected]55459852011-08-10 15:17:19297def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
298 """Attempts to prevent use of functions intended only for testing in
299 non-testing code. For now this is just a best-effort implementation
300 that ignores header files and may have some false positives. A
301 better implementation would probably need a proper C++ parser.
302 """
303 # We only scan .cc files and the like, as the declaration of
304 # for-testing functions in header files are hard to distinguish from
305 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44306 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19307
jochenc0d4808c2015-07-27 09:25:42308 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19309 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09310 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19311 exclusion_pattern = input_api.re.compile(
312 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
313 base_function_pattern, base_function_pattern))
314
315 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44316 black_list = (_EXCLUDED_PATHS +
317 _TEST_CODE_EXCLUDED_PATHS +
318 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19319 return input_api.FilterSourceFile(
320 affected_file,
321 white_list=(file_inclusion_pattern, ),
322 black_list=black_list)
323
324 problems = []
325 for f in input_api.AffectedSourceFiles(FilterFile):
326 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24327 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03328 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46329 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03330 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19331 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03332 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19333
334 if problems:
[email protected]f7051d52013-04-02 18:31:42335 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03336 else:
337 return []
[email protected]55459852011-08-10 15:17:19338
339
[email protected]10689ca2011-09-02 02:31:54340def _CheckNoIOStreamInHeaders(input_api, output_api):
341 """Checks to make sure no .h files include <iostream>."""
342 files = []
343 pattern = input_api.re.compile(r'^#include\s*<iostream>',
344 input_api.re.MULTILINE)
345 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
346 if not f.LocalPath().endswith('.h'):
347 continue
348 contents = input_api.ReadFile(f)
349 if pattern.search(contents):
350 files.append(f)
351
352 if len(files):
353 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06354 'Do not #include <iostream> in header files, since it inserts static '
355 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54356 '#include <ostream>. See http://crbug.com/94794',
357 files) ]
358 return []
359
360
[email protected]72df4e782012-06-21 16:28:18361def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52362 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18363 problems = []
364 for f in input_api.AffectedFiles():
365 if (not f.LocalPath().endswith(('.cc', '.mm'))):
366 continue
367
368 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04369 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18370 problems.append(' %s:%d' % (f.LocalPath(), line_num))
371
372 if not problems:
373 return []
374 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
375 '\n'.join(problems))]
376
377
danakj61c1aa22015-10-26 19:55:52378def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
379 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
380 errors = []
381 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
382 input_api.re.MULTILINE)
383 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
384 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
385 continue
386 for lnum, line in f.ChangedContents():
387 if input_api.re.search(pattern, line):
388 errors.append(output_api.PresubmitError(
389 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
390 'DCHECK_IS_ON()", not forgetting the braces.')
391 % (f.LocalPath(), lnum)))
392 return errors
393
394
mcasasb7440c282015-02-04 14:52:19395def _FindHistogramNameInLine(histogram_name, line):
396 """Tries to find a histogram name or prefix in a line."""
397 if not "affected-histogram" in line:
398 return histogram_name in line
399 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
400 # the histogram_name.
401 if not '"' in line:
402 return False
403 histogram_prefix = line.split('\"')[1]
404 return histogram_prefix in histogram_name
405
406
407def _CheckUmaHistogramChanges(input_api, output_api):
408 """Check that UMA histogram names in touched lines can still be found in other
409 lines of the patch or in histograms.xml. Note that this check would not catch
410 the reverse: changes in histograms.xml not matched in the code itself."""
411 touched_histograms = []
412 histograms_xml_modifications = []
413 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
414 for f in input_api.AffectedFiles():
415 # If histograms.xml itself is modified, keep the modified lines for later.
416 if f.LocalPath().endswith(('histograms.xml')):
417 histograms_xml_modifications = f.ChangedContents()
418 continue
419 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
420 continue
421 for line_num, line in f.ChangedContents():
422 found = pattern.search(line)
423 if found:
424 touched_histograms.append([found.group(1), f, line_num])
425
426 # Search for the touched histogram names in the local modifications to
427 # histograms.xml, and, if not found, on the base histograms.xml file.
428 unmatched_histograms = []
429 for histogram_info in touched_histograms:
430 histogram_name_found = False
431 for line_num, line in histograms_xml_modifications:
432 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
433 if histogram_name_found:
434 break
435 if not histogram_name_found:
436 unmatched_histograms.append(histogram_info)
437
eromanb90c82e7e32015-04-01 15:13:49438 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19439 problems = []
440 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49441 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19442 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45443 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19444 histogram_name_found = False
445 for line in histograms_xml:
446 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
447 if histogram_name_found:
448 break
449 if not histogram_name_found:
450 problems.append(' [%s:%d] %s' %
451 (f.LocalPath(), line_num, histogram_name))
452
453 if not problems:
454 return []
455 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
456 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49457 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19458
459
[email protected]8ea5d4b2011-09-13 21:49:22460def _CheckNoNewWStrings(input_api, output_api):
461 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27462 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22463 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20464 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57465 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
466 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20467 continue
[email protected]8ea5d4b2011-09-13 21:49:22468
[email protected]a11dbe9b2012-08-07 01:32:58469 allowWString = False
[email protected]b5c24292011-11-28 14:38:20470 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58471 if 'presubmit: allow wstring' in line:
472 allowWString = True
473 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27474 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58475 allowWString = False
476 else:
477 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22478
[email protected]55463aa62011-10-12 00:48:27479 if not problems:
480 return []
481 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58482 ' If you are calling a cross-platform API that accepts a wstring, '
483 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27484 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22485
486
[email protected]2a8ac9c2011-10-19 17:20:44487def _CheckNoDEPSGIT(input_api, output_api):
488 """Make sure .DEPS.git is never modified manually."""
489 if any(f.LocalPath().endswith('.DEPS.git') for f in
490 input_api.AffectedFiles()):
491 return [output_api.PresubmitError(
492 'Never commit changes to .DEPS.git. This file is maintained by an\n'
493 'automated system based on what\'s in DEPS and your changes will be\n'
494 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34495 '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:44496 'for more information')]
497 return []
498
499
tandriief664692014-09-23 14:51:47500def _CheckValidHostsInDEPS(input_api, output_api):
501 """Checks that DEPS file deps are from allowed_hosts."""
502 # Run only if DEPS file has been modified to annoy fewer bystanders.
503 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
504 return []
505 # Outsource work to gclient verify
506 try:
507 input_api.subprocess.check_output(['gclient', 'verify'])
508 return []
509 except input_api.subprocess.CalledProcessError, error:
510 return [output_api.PresubmitError(
511 'DEPS file must have only git dependencies.',
512 long_text=error.output)]
513
514
[email protected]127f18ec2012-06-16 05:05:59515def _CheckNoBannedFunctions(input_api, output_api):
516 """Make sure that banned functions are not used."""
517 warnings = []
518 errors = []
519
520 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
521 for f in input_api.AffectedFiles(file_filter=file_filter):
522 for line_num, line in f.ChangedContents():
523 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
[email protected]eaae1972014-04-16 04:17:26524 matched = False
525 if func_name[0:1] == '/':
526 regex = func_name[1:]
527 if input_api.re.search(regex, line):
528 matched = True
529 elif func_name in line:
530 matched = True
531 if matched:
[email protected]127f18ec2012-06-16 05:05:59532 problems = warnings;
533 if error:
534 problems = errors;
535 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
536 for message_line in message:
537 problems.append(' %s' % message_line)
538
539 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
540 for f in input_api.AffectedFiles(file_filter=file_filter):
541 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49542 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
543 def IsBlacklisted(affected_file, blacklist):
544 local_path = affected_file.LocalPath()
545 for item in blacklist:
546 if input_api.re.match(item, local_path):
547 return True
548 return False
549 if IsBlacklisted(f, excluded_paths):
550 continue
[email protected]d89eec82013-12-03 14:10:59551 matched = False
552 if func_name[0:1] == '/':
553 regex = func_name[1:]
554 if input_api.re.search(regex, line):
555 matched = True
556 elif func_name in line:
557 matched = True
558 if matched:
[email protected]127f18ec2012-06-16 05:05:59559 problems = warnings;
560 if error:
561 problems = errors;
562 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
563 for message_line in message:
564 problems.append(' %s' % message_line)
565
566 result = []
567 if (warnings):
568 result.append(output_api.PresubmitPromptWarning(
569 'Banned functions were used.\n' + '\n'.join(warnings)))
570 if (errors):
571 result.append(output_api.PresubmitError(
572 'Banned functions were used.\n' + '\n'.join(errors)))
573 return result
574
575
[email protected]6c063c62012-07-11 19:11:06576def _CheckNoPragmaOnce(input_api, output_api):
577 """Make sure that banned functions are not used."""
578 files = []
579 pattern = input_api.re.compile(r'^#pragma\s+once',
580 input_api.re.MULTILINE)
581 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
582 if not f.LocalPath().endswith('.h'):
583 continue
584 contents = input_api.ReadFile(f)
585 if pattern.search(contents):
586 files.append(f)
587
588 if files:
589 return [output_api.PresubmitError(
590 'Do not use #pragma once in header files.\n'
591 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
592 files)]
593 return []
594
[email protected]127f18ec2012-06-16 05:05:59595
[email protected]e7479052012-09-19 00:26:12596def _CheckNoTrinaryTrueFalse(input_api, output_api):
597 """Checks to make sure we don't introduce use of foo ? true : false."""
598 problems = []
599 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
600 for f in input_api.AffectedFiles():
601 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
602 continue
603
604 for line_num, line in f.ChangedContents():
605 if pattern.match(line):
606 problems.append(' %s:%d' % (f.LocalPath(), line_num))
607
608 if not problems:
609 return []
610 return [output_api.PresubmitPromptWarning(
611 'Please consider avoiding the "? true : false" pattern if possible.\n' +
612 '\n'.join(problems))]
613
614
[email protected]55f9f382012-07-31 11:02:18615def _CheckUnwantedDependencies(input_api, output_api):
616 """Runs checkdeps on #include statements added in this
617 change. Breaking - rules is an error, breaking ! rules is a
618 warning.
619 """
mohan.reddyf21db962014-10-16 12:26:47620 import sys
[email protected]55f9f382012-07-31 11:02:18621 # We need to wait until we have an input_api object and use this
622 # roundabout construct to import checkdeps because this file is
623 # eval-ed and thus doesn't have __file__.
624 original_sys_path = sys.path
625 try:
626 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47627 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18628 import checkdeps
629 from cpp_checker import CppChecker
630 from rules import Rule
631 finally:
632 # Restore sys.path to what it was before.
633 sys.path = original_sys_path
634
635 added_includes = []
636 for f in input_api.AffectedFiles():
637 if not CppChecker.IsCppFile(f.LocalPath()):
638 continue
639
640 changed_lines = [line for line_num, line in f.ChangedContents()]
641 added_includes.append([f.LocalPath(), changed_lines])
642
[email protected]26385172013-05-09 23:11:35643 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18644
645 error_descriptions = []
646 warning_descriptions = []
647 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
648 added_includes):
649 description_with_path = '%s\n %s' % (path, rule_description)
650 if rule_type == Rule.DISALLOW:
651 error_descriptions.append(description_with_path)
652 else:
653 warning_descriptions.append(description_with_path)
654
655 results = []
656 if error_descriptions:
657 results.append(output_api.PresubmitError(
658 'You added one or more #includes that violate checkdeps rules.',
659 error_descriptions))
660 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42661 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18662 'You added one or more #includes of files that are temporarily\n'
663 'allowed but being removed. Can you avoid introducing the\n'
664 '#include? See relevant DEPS file(s) for details and contacts.',
665 warning_descriptions))
666 return results
667
668
[email protected]fbcafe5a2012-08-08 15:31:22669def _CheckFilePermissions(input_api, output_api):
670 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15671 if input_api.platform == 'win32':
672 return []
mohan.reddyf21db962014-10-16 12:26:47673 args = [input_api.python_executable, 'tools/checkperms/checkperms.py',
674 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22675 for f in input_api.AffectedFiles():
676 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11677 try:
678 input_api.subprocess.check_output(args)
679 return []
680 except input_api.subprocess.CalledProcessError as error:
681 return [output_api.PresubmitError(
682 'checkperms.py failed:',
683 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22684
685
[email protected]c8278b32012-10-30 20:35:49686def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
687 """Makes sure we don't include ui/aura/window_property.h
688 in header files.
689 """
690 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
691 errors = []
692 for f in input_api.AffectedFiles():
693 if not f.LocalPath().endswith('.h'):
694 continue
695 for line_num, line in f.ChangedContents():
696 if pattern.match(line):
697 errors.append(' %s:%d' % (f.LocalPath(), line_num))
698
699 results = []
700 if errors:
701 results.append(output_api.PresubmitError(
702 'Header files should not include ui/aura/window_property.h', errors))
703 return results
704
705
[email protected]cf9b78f2012-11-14 11:40:28706def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
707 """Checks that the lines in scope occur in the right order.
708
709 1. C system files in alphabetical order
710 2. C++ system files in alphabetical order
711 3. Project's .h files
712 """
713
714 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
715 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
716 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
717
718 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
719
720 state = C_SYSTEM_INCLUDES
721
722 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57723 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28724 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55725 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28726 for line_num, line in scope:
727 if c_system_include_pattern.match(line):
728 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55729 problem_linenums.append((line_num, previous_line_num,
730 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28731 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55732 problem_linenums.append((line_num, previous_line_num,
733 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28734 elif cpp_system_include_pattern.match(line):
735 if state == C_SYSTEM_INCLUDES:
736 state = CPP_SYSTEM_INCLUDES
737 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55738 problem_linenums.append((line_num, previous_line_num,
739 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28740 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55741 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28742 elif custom_include_pattern.match(line):
743 if state != CUSTOM_INCLUDES:
744 state = CUSTOM_INCLUDES
745 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55746 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28747 else:
brucedawson70fadb02015-06-30 17:47:55748 problem_linenums.append((line_num, previous_line_num,
749 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28750 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57751 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28752
753 warnings = []
brucedawson70fadb02015-06-30 17:47:55754 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57755 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55756 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28757 return warnings
758
759
[email protected]ac294a12012-12-06 16:38:43760def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28761 """Checks the #include order for the given file f."""
762
[email protected]2299dcf2012-11-15 19:56:24763 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30764 # Exclude the following includes from the check:
765 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
766 # specific order.
767 # 2) <atlbase.h>, "build/build_config.h"
768 excluded_include_pattern = input_api.re.compile(
769 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24770 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33771 # Match the final or penultimate token if it is xxxtest so we can ignore it
772 # when considering the special first include.
773 test_file_tag_pattern = input_api.re.compile(
774 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11775 if_pattern = input_api.re.compile(
776 r'\s*#\s*(if|elif|else|endif|define|undef).*')
777 # Some files need specialized order of includes; exclude such files from this
778 # check.
779 uncheckable_includes_pattern = input_api.re.compile(
780 r'\s*#include '
781 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28782
783 contents = f.NewContents()
784 warnings = []
785 line_num = 0
786
[email protected]ac294a12012-12-06 16:38:43787 # Handle the special first include. If the first include file is
788 # some/path/file.h, the corresponding including file can be some/path/file.cc,
789 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
790 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33791 # If the included file is some/path/file_platform.h the including file could
792 # also be some/path/file_xxxtest_platform.h.
793 including_file_base_name = test_file_tag_pattern.sub(
794 '', input_api.os_path.basename(f.LocalPath()))
795
[email protected]ac294a12012-12-06 16:38:43796 for line in contents:
797 line_num += 1
798 if system_include_pattern.match(line):
799 # No special first include -> process the line again along with normal
800 # includes.
801 line_num -= 1
802 break
803 match = custom_include_pattern.match(line)
804 if match:
805 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33806 header_basename = test_file_tag_pattern.sub(
807 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
808
809 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24810 # No special first include -> process the line again along with normal
811 # includes.
812 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43813 break
[email protected]cf9b78f2012-11-14 11:40:28814
815 # Split into scopes: Each region between #if and #endif is its own scope.
816 scopes = []
817 current_scope = []
818 for line in contents[line_num:]:
819 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11820 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54821 continue
[email protected]2309b0fa02012-11-16 12:18:27822 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28823 scopes.append(current_scope)
824 current_scope = []
[email protected]962f117e2012-11-22 18:11:56825 elif ((system_include_pattern.match(line) or
826 custom_include_pattern.match(line)) and
827 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28828 current_scope.append((line_num, line))
829 scopes.append(current_scope)
830
831 for scope in scopes:
832 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
833 changed_linenums))
834 return warnings
835
836
837def _CheckIncludeOrder(input_api, output_api):
838 """Checks that the #include order is correct.
839
840 1. The corresponding header for source files.
841 2. C system files in alphabetical order
842 3. C++ system files in alphabetical order
843 4. Project's .h files in alphabetical order
844
[email protected]ac294a12012-12-06 16:38:43845 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
846 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28847 """
[email protected]e120b012014-08-15 19:08:35848 def FileFilterIncludeOrder(affected_file):
849 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
850 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28851
852 warnings = []
[email protected]e120b012014-08-15 19:08:35853 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08854 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43855 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
856 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28857
858 results = []
859 if warnings:
[email protected]f7051d52013-04-02 18:31:42860 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53861 warnings))
[email protected]cf9b78f2012-11-14 11:40:28862 return results
863
864
[email protected]70ca77752012-11-20 03:45:03865def _CheckForVersionControlConflictsInFile(input_api, f):
866 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
867 errors = []
868 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23869 if f.LocalPath().endswith('.md'):
870 # First-level headers in markdown look a lot like version control
871 # conflict markers. http://daringfireball.net/projects/markdown/basics
872 continue
[email protected]70ca77752012-11-20 03:45:03873 if pattern.match(line):
874 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
875 return errors
876
877
878def _CheckForVersionControlConflicts(input_api, output_api):
879 """Usually this is not intentional and will cause a compile failure."""
880 errors = []
881 for f in input_api.AffectedFiles():
882 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
883
884 results = []
885 if errors:
886 results.append(output_api.PresubmitError(
887 'Version control conflict markers found, please resolve.', errors))
888 return results
889
890
[email protected]06e6d0ff2012-12-11 01:36:44891def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
892 def FilterFile(affected_file):
893 """Filter function for use with input_api.AffectedSourceFiles,
894 below. This filters out everything except non-test files from
895 top-level directories that generally speaking should not hard-code
896 service URLs (e.g. src/android_webview/, src/content/ and others).
897 """
898 return input_api.FilterSourceFile(
899 affected_file,
[email protected]78bb39d62012-12-11 15:11:56900 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44901 black_list=(_EXCLUDED_PATHS +
902 _TEST_CODE_EXCLUDED_PATHS +
903 input_api.DEFAULT_BLACK_LIST))
904
reillyi38965732015-11-16 18:27:33905 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
906 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46907 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
908 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44909 problems = [] # items are (filename, line_number, line)
910 for f in input_api.AffectedSourceFiles(FilterFile):
911 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46912 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44913 problems.append((f.LocalPath(), line_num, line))
914
915 if problems:
[email protected]f7051d52013-04-02 18:31:42916 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44917 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58918 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44919 [' %s:%d: %s' % (
920 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03921 else:
922 return []
[email protected]06e6d0ff2012-12-11 01:36:44923
924
[email protected]d2530012013-01-25 16:39:27925def _CheckNoAbbreviationInPngFileName(input_api, output_api):
926 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31927 The native_client_sdk directory is excluded because it has auto-generated PNG
928 files for documentation.
[email protected]d2530012013-01-25 16:39:27929 """
[email protected]d2530012013-01-25 16:39:27930 errors = []
binji0dcdf342014-12-12 18:32:31931 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
932 black_list = (r'^native_client_sdk[\\\/]',)
933 file_filter = lambda f: input_api.FilterSourceFile(
934 f, white_list=white_list, black_list=black_list)
935 for f in input_api.AffectedFiles(include_deletes=False,
936 file_filter=file_filter):
937 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27938
939 results = []
940 if errors:
941 results.append(output_api.PresubmitError(
942 'The name of PNG files should not have abbreviations. \n'
943 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
944 'Contact [email protected] if you have questions.', errors))
945 return results
946
947
[email protected]14a6131c2014-01-08 01:15:41948def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:08949 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:41950 a set of DEPS entries that we should look up.
951
952 For a directory (rather than a specific filename) we fake a path to
953 a specific filename by adding /DEPS. This is chosen as a file that
954 will seldom or never be subject to per-file include_rules.
955 """
[email protected]2b438d62013-11-14 17:54:14956 # We ignore deps entries on auto-generated directories.
957 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:08958
959 # This pattern grabs the path without basename in the first
960 # parentheses, and the basename (if present) in the second. It
961 # relies on the simple heuristic that if there is a basename it will
962 # be a header file ending in ".h".
963 pattern = re.compile(
964 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:14965 results = set()
[email protected]f32e2d1e2013-07-26 21:39:08966 for changed_line in changed_lines:
967 m = pattern.match(changed_line)
968 if m:
969 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:14970 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:41971 if m.group(2):
972 results.add('%s%s' % (path, m.group(2)))
973 else:
974 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:08975 return results
976
977
[email protected]e871964c2013-05-13 14:14:55978def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
979 """When a dependency prefixed with + is added to a DEPS file, we
980 want to make sure that the change is reviewed by an OWNER of the
981 target file or directory, to avoid layering violations from being
982 introduced. This check verifies that this happens.
983 """
984 changed_lines = set()
jochen53efcdd2016-01-29 05:09:24985
986 file_filter = lambda f: not input_api.re.match(
987 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
988 for f in input_api.AffectedFiles(include_deletes=False,
989 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:55990 filename = input_api.os_path.basename(f.LocalPath())
991 if filename == 'DEPS':
992 changed_lines |= set(line.strip()
993 for line_num, line
994 in f.ChangedContents())
995 if not changed_lines:
996 return []
997
[email protected]14a6131c2014-01-08 01:15:41998 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
999 changed_lines)
[email protected]e871964c2013-05-13 14:14:551000 if not virtual_depended_on_files:
1001 return []
1002
1003 if input_api.is_committing:
1004 if input_api.tbr:
1005 return [output_api.PresubmitNotifyResult(
1006 '--tbr was specified, skipping OWNERS check for DEPS additions')]
1007 if not input_api.change.issue:
1008 return [output_api.PresubmitError(
1009 "DEPS approval by OWNERS check failed: this change has "
1010 "no Rietveld issue number, so we can't check it for approvals.")]
1011 output = output_api.PresubmitError
1012 else:
1013 output = output_api.PresubmitNotifyResult
1014
1015 owners_db = input_api.owners_db
1016 owner_email, reviewers = input_api.canned_checks._RietveldOwnerAndReviewers(
1017 input_api,
1018 owners_db.email_regexp,
1019 approval_needed=input_api.is_committing)
1020
1021 owner_email = owner_email or input_api.change.author_email
1022
[email protected]de4f7d22013-05-23 14:27:461023 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511024 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461025 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551026 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1027 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411028
1029 # We strip the /DEPS part that was added by
1030 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1031 # directory.
1032 def StripDeps(path):
1033 start_deps = path.rfind('/DEPS')
1034 if start_deps != -1:
1035 return path[:start_deps]
1036 else:
1037 return path
1038 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551039 for path in missing_files]
1040
1041 if unapproved_dependencies:
1042 output_list = [
[email protected]14a6131c2014-01-08 01:15:411043 output('Missing LGTM from OWNERS of dependencies added to DEPS:\n %s' %
[email protected]e871964c2013-05-13 14:14:551044 '\n '.join(sorted(unapproved_dependencies)))]
1045 if not input_api.is_committing:
1046 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1047 output_list.append(output(
1048 'Suggested missing target path OWNERS:\n %s' %
1049 '\n '.join(suggested_owners or [])))
1050 return output_list
1051
1052 return []
1053
1054
[email protected]85218562013-11-22 07:41:401055def _CheckSpamLogging(input_api, output_api):
1056 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1057 black_list = (_EXCLUDED_PATHS +
1058 _TEST_CODE_EXCLUDED_PATHS +
1059 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501060 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191061 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481062 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461063 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121064 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1065 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581066 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161067 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031068 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151069 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1070 r"^chromecast[\\\/]",
1071 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311072 r"^components[\\\/]html_viewer[\\\/]"
1073 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461074 # TODO(peter): Remove this exception. https://crbug.com/534537
1075 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1076 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251077 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1078 r"gl_helper_benchmark\.cc$",
thestigc9e38a22014-09-13 01:02:111079 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151080 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111081 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521082 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501083 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361084 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311085 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131086 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441087 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451088 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021089 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441090 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401091 source_file_filter = lambda x: input_api.FilterSourceFile(
1092 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1093
1094 log_info = []
1095 printf = []
1096
1097 for f in input_api.AffectedSourceFiles(source_file_filter):
1098 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471099 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401100 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471101 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131102 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371103
mohan.reddyf21db962014-10-16 12:26:471104 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371105 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471106 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401107 printf.append(f.LocalPath())
1108
1109 if log_info:
1110 return [output_api.PresubmitError(
1111 'These files spam the console log with LOG(INFO):',
1112 items=log_info)]
1113 if printf:
1114 return [output_api.PresubmitError(
1115 'These files spam the console log with printf/fprintf:',
1116 items=printf)]
1117 return []
1118
1119
[email protected]49aa76a2013-12-04 06:59:161120def _CheckForAnonymousVariables(input_api, output_api):
1121 """These types are all expected to hold locks while in scope and
1122 so should never be anonymous (which causes them to be immediately
1123 destroyed)."""
1124 they_who_must_be_named = [
1125 'base::AutoLock',
1126 'base::AutoReset',
1127 'base::AutoUnlock',
1128 'SkAutoAlphaRestore',
1129 'SkAutoBitmapShaderInstall',
1130 'SkAutoBlitterChoose',
1131 'SkAutoBounderCommit',
1132 'SkAutoCallProc',
1133 'SkAutoCanvasRestore',
1134 'SkAutoCommentBlock',
1135 'SkAutoDescriptor',
1136 'SkAutoDisableDirectionCheck',
1137 'SkAutoDisableOvalCheck',
1138 'SkAutoFree',
1139 'SkAutoGlyphCache',
1140 'SkAutoHDC',
1141 'SkAutoLockColors',
1142 'SkAutoLockPixels',
1143 'SkAutoMalloc',
1144 'SkAutoMaskFreeImage',
1145 'SkAutoMutexAcquire',
1146 'SkAutoPathBoundsUpdate',
1147 'SkAutoPDFRelease',
1148 'SkAutoRasterClipValidate',
1149 'SkAutoRef',
1150 'SkAutoTime',
1151 'SkAutoTrace',
1152 'SkAutoUnref',
1153 ]
1154 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1155 # bad: base::AutoLock(lock.get());
1156 # not bad: base::AutoLock lock(lock.get());
1157 bad_pattern = input_api.re.compile(anonymous)
1158 # good: new base::AutoLock(lock.get())
1159 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1160 errors = []
1161
1162 for f in input_api.AffectedFiles():
1163 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1164 continue
1165 for linenum, line in f.ChangedContents():
1166 if bad_pattern.search(line) and not good_pattern.search(line):
1167 errors.append('%s:%d' % (f.LocalPath(), linenum))
1168
1169 if errors:
1170 return [output_api.PresubmitError(
1171 'These lines create anonymous variables that need to be named:',
1172 items=errors)]
1173 return []
1174
1175
[email protected]5fe0f8742013-11-29 01:04:591176def _CheckCygwinShell(input_api, output_api):
1177 source_file_filter = lambda x: input_api.FilterSourceFile(
1178 x, white_list=(r'.+\.(gyp|gypi)$',))
1179 cygwin_shell = []
1180
1181 for f in input_api.AffectedSourceFiles(source_file_filter):
1182 for linenum, line in f.ChangedContents():
1183 if 'msvs_cygwin_shell' in line:
1184 cygwin_shell.append(f.LocalPath())
1185 break
1186
1187 if cygwin_shell:
1188 return [output_api.PresubmitError(
1189 'These files should not use msvs_cygwin_shell (the default is 0):',
1190 items=cygwin_shell)]
1191 return []
1192
[email protected]85218562013-11-22 07:41:401193
[email protected]999261d2014-03-03 20:08:081194def _CheckUserActionUpdate(input_api, output_api):
1195 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521196 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081197 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521198 # If actions.xml is already included in the changelist, the PRESUBMIT
1199 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081200 return []
1201
[email protected]999261d2014-03-03 20:08:081202 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1203 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521204 current_actions = None
[email protected]999261d2014-03-03 20:08:081205 for f in input_api.AffectedFiles(file_filter=file_filter):
1206 for line_num, line in f.ChangedContents():
1207 match = input_api.re.search(action_re, line)
1208 if match:
[email protected]2f92dec2014-03-07 19:21:521209 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1210 # loaded only once.
1211 if not current_actions:
1212 with open('tools/metrics/actions/actions.xml') as actions_f:
1213 current_actions = actions_f.read()
1214 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081215 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521216 action = 'name="{0}"'.format(action_name)
1217 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081218 return [output_api.PresubmitPromptWarning(
1219 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521220 'tools/metrics/actions/actions.xml. Please run '
1221 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081222 % (f.LocalPath(), line_num, action_name))]
1223 return []
1224
1225
[email protected]99171a92014-06-03 08:44:471226def _GetJSONParseError(input_api, filename, eat_comments=True):
1227 try:
1228 contents = input_api.ReadFile(filename)
1229 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131230 import sys
1231 original_sys_path = sys.path
1232 try:
1233 sys.path = sys.path + [input_api.os_path.join(
1234 input_api.PresubmitLocalPath(),
1235 'tools', 'json_comment_eater')]
1236 import json_comment_eater
1237 finally:
1238 sys.path = original_sys_path
1239 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471240
1241 input_api.json.loads(contents)
1242 except ValueError as e:
1243 return e
1244 return None
1245
1246
1247def _GetIDLParseError(input_api, filename):
1248 try:
1249 contents = input_api.ReadFile(filename)
1250 idl_schema = input_api.os_path.join(
1251 input_api.PresubmitLocalPath(),
1252 'tools', 'json_schema_compiler', 'idl_schema.py')
1253 process = input_api.subprocess.Popen(
1254 [input_api.python_executable, idl_schema],
1255 stdin=input_api.subprocess.PIPE,
1256 stdout=input_api.subprocess.PIPE,
1257 stderr=input_api.subprocess.PIPE,
1258 universal_newlines=True)
1259 (_, error) = process.communicate(input=contents)
1260 return error or None
1261 except ValueError as e:
1262 return e
1263
1264
1265def _CheckParseErrors(input_api, output_api):
1266 """Check that IDL and JSON files do not contain syntax errors."""
1267 actions = {
1268 '.idl': _GetIDLParseError,
1269 '.json': _GetJSONParseError,
1270 }
1271 # These paths contain test data and other known invalid JSON files.
1272 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491273 r'test[\\\/]data[\\\/]',
1274 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471275 ]
1276 # Most JSON files are preprocessed and support comments, but these do not.
1277 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491278 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471279 ]
1280 # Only run IDL checker on files in these directories.
1281 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491282 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1283 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471284 ]
1285
1286 def get_action(affected_file):
1287 filename = affected_file.LocalPath()
1288 return actions.get(input_api.os_path.splitext(filename)[1])
1289
1290 def MatchesFile(patterns, path):
1291 for pattern in patterns:
1292 if input_api.re.search(pattern, path):
1293 return True
1294 return False
1295
1296 def FilterFile(affected_file):
1297 action = get_action(affected_file)
1298 if not action:
1299 return False
1300 path = affected_file.LocalPath()
1301
1302 if MatchesFile(excluded_patterns, path):
1303 return False
1304
1305 if (action == _GetIDLParseError and
1306 not MatchesFile(idl_included_patterns, path)):
1307 return False
1308 return True
1309
1310 results = []
1311 for affected_file in input_api.AffectedFiles(
1312 file_filter=FilterFile, include_deletes=False):
1313 action = get_action(affected_file)
1314 kwargs = {}
1315 if (action == _GetJSONParseError and
1316 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1317 kwargs['eat_comments'] = False
1318 parse_error = action(input_api,
1319 affected_file.AbsoluteLocalPath(),
1320 **kwargs)
1321 if parse_error:
1322 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1323 (affected_file.LocalPath(), parse_error)))
1324 return results
1325
1326
[email protected]760deea2013-12-10 19:33:491327def _CheckJavaStyle(input_api, output_api):
1328 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471329 import sys
[email protected]760deea2013-12-10 19:33:491330 original_sys_path = sys.path
1331 try:
1332 sys.path = sys.path + [input_api.os_path.join(
1333 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1334 import checkstyle
1335 finally:
1336 # Restore sys.path to what it was before.
1337 sys.path = original_sys_path
1338
1339 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091340 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511341 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491342
1343
dskiba88634f4e2015-08-14 23:03:291344def _CheckAndroidToastUsage(input_api, output_api):
1345 """Checks that code uses org.chromium.ui.widget.Toast instead of
1346 android.widget.Toast (Chromium Toast doesn't force hardware
1347 acceleration on low-end devices, saving memory).
1348 """
1349 toast_import_pattern = input_api.re.compile(
1350 r'^import android\.widget\.Toast;$')
1351
1352 errors = []
1353
1354 sources = lambda affected_file: input_api.FilterSourceFile(
1355 affected_file,
1356 black_list=(_EXCLUDED_PATHS +
1357 _TEST_CODE_EXCLUDED_PATHS +
1358 input_api.DEFAULT_BLACK_LIST +
1359 (r'^chromecast[\\\/].*',
1360 r'^remoting[\\\/].*')),
1361 white_list=(r'.*\.java$',))
1362
1363 for f in input_api.AffectedSourceFiles(sources):
1364 for line_num, line in f.ChangedContents():
1365 if toast_import_pattern.search(line):
1366 errors.append("%s:%d" % (f.LocalPath(), line_num))
1367
1368 results = []
1369
1370 if errors:
1371 results.append(output_api.PresubmitError(
1372 'android.widget.Toast usage is detected. Android toasts use hardware'
1373 ' acceleration, and can be\ncostly on low-end devices. Please use'
1374 ' org.chromium.ui.widget.Toast instead.\n'
1375 'Contact [email protected] if you have any questions.',
1376 errors))
1377
1378 return results
1379
1380
dgnaa68d5e2015-06-10 10:08:221381def _CheckAndroidCrLogUsage(input_api, output_api):
1382 """Checks that new logs using org.chromium.base.Log:
1383 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511384 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221385 """
1386 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121387 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1388 class_in_base_pattern = input_api.re.compile(
1389 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1390 has_some_log_import_pattern = input_api.re.compile(
1391 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221392 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121393 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221394 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511395 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221396 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221397
Vincent Scheib16d7b272015-09-15 18:09:071398 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221399 'or contact [email protected] for more info.')
1400 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',))
dgn87d9fb62015-06-12 09:15:121401
dgnaa68d5e2015-06-10 10:08:221402 tag_decl_errors = []
1403 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121404 tag_errors = []
dgn38736db2015-09-18 19:20:511405 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121406 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221407
1408 for f in input_api.AffectedSourceFiles(sources):
1409 file_content = input_api.ReadFile(f)
1410 has_modified_logs = False
1411
1412 # Per line checks
dgn87d9fb62015-06-12 09:15:121413 if (cr_log_import_pattern.search(file_content) or
1414 (class_in_base_pattern.search(file_content) and
1415 not has_some_log_import_pattern.search(file_content))):
1416 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221417 for line_num, line in f.ChangedContents():
1418
1419 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121420 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221421 if match:
1422 has_modified_logs = True
1423
1424 # Make sure it uses "TAG"
1425 if not match.group('tag') == 'TAG':
1426 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121427 else:
1428 # Report non cr Log function calls in changed lines
1429 for line_num, line in f.ChangedContents():
1430 if log_call_pattern.search(line):
1431 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221432
1433 # Per file checks
1434 if has_modified_logs:
1435 # Make sure the tag is using the "cr" prefix and is not too long
1436 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511437 tag_name = match.group('name') if match else None
1438 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221439 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511440 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221441 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511442 elif '.' in tag_name:
1443 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221444
1445 results = []
1446 if tag_decl_errors:
1447 results.append(output_api.PresubmitPromptWarning(
1448 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511449 '"private static final String TAG = "<package tag>".\n'
1450 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221451 tag_decl_errors))
1452
1453 if tag_length_errors:
1454 results.append(output_api.PresubmitError(
1455 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511456 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221457 tag_length_errors))
1458
1459 if tag_errors:
1460 results.append(output_api.PresubmitPromptWarning(
1461 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1462 tag_errors))
1463
dgn87d9fb62015-06-12 09:15:121464 if util_log_errors:
dgn4401aa52015-04-29 16:26:171465 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121466 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1467 util_log_errors))
1468
dgn38736db2015-09-18 19:20:511469 if tag_with_dot_errors:
1470 results.append(output_api.PresubmitPromptWarning(
1471 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1472 tag_with_dot_errors))
1473
dgn4401aa52015-04-29 16:26:171474 return results
1475
1476
agrieve7b6479d82015-10-07 14:24:221477def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1478 """Checks if MDPI assets are placed in a correct directory."""
1479 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1480 ('/res/drawable/' in f.LocalPath() or
1481 '/res/drawable-ldrtl/' in f.LocalPath()))
1482 errors = []
1483 for f in input_api.AffectedFiles(include_deletes=False,
1484 file_filter=file_filter):
1485 errors.append(' %s' % f.LocalPath())
1486
1487 results = []
1488 if errors:
1489 results.append(output_api.PresubmitError(
1490 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1491 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1492 '/res/drawable-ldrtl/.\n'
1493 'Contact [email protected] if you have questions.', errors))
1494 return results
1495
1496
mnaganov9b9b1fe82014-12-11 16:30:361497def _CheckForCopyrightedCode(input_api, output_api):
1498 """Verifies that newly added code doesn't contain copyrighted material
1499 and is properly licensed under the standard Chromium license.
1500
1501 As there can be false positives, we maintain a whitelist file. This check
1502 also verifies that the whitelist file is up to date.
1503 """
1504 import sys
1505 original_sys_path = sys.path
1506 try:
1507 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221508 input_api.PresubmitLocalPath(), 'tools')]
1509 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361510 finally:
1511 # Restore sys.path to what it was before.
1512 sys.path = original_sys_path
1513
1514 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1515
1516
glidere61efad2015-02-18 17:39:431517def _CheckSingletonInHeaders(input_api, output_api):
1518 """Checks to make sure no header files have |Singleton<|."""
1519 def FileFilter(affected_file):
1520 # It's ok for base/memory/singleton.h to have |Singleton<|.
1521 black_list = (_EXCLUDED_PATHS +
1522 input_api.DEFAULT_BLACK_LIST +
1523 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1524 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1525
sergeyu34d21222015-09-16 00:11:441526 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431527 files = []
1528 for f in input_api.AffectedSourceFiles(FileFilter):
1529 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1530 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1531 contents = input_api.ReadFile(f)
1532 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241533 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431534 pattern.search(line)):
1535 files.append(f)
1536 break
1537
1538 if files:
1539 return [ output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441540 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431541 'Please move them to an appropriate source file so that the ' +
1542 'template gets instantiated in a single compilation unit.',
1543 files) ]
1544 return []
1545
1546
[email protected]fd20b902014-05-09 02:14:531547_DEPRECATED_CSS = [
1548 # Values
1549 ( "-webkit-box", "flex" ),
1550 ( "-webkit-inline-box", "inline-flex" ),
1551 ( "-webkit-flex", "flex" ),
1552 ( "-webkit-inline-flex", "inline-flex" ),
1553 ( "-webkit-min-content", "min-content" ),
1554 ( "-webkit-max-content", "max-content" ),
1555
1556 # Properties
1557 ( "-webkit-background-clip", "background-clip" ),
1558 ( "-webkit-background-origin", "background-origin" ),
1559 ( "-webkit-background-size", "background-size" ),
1560 ( "-webkit-box-shadow", "box-shadow" ),
1561
1562 # Functions
1563 ( "-webkit-gradient", "gradient" ),
1564 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1565 ( "-webkit-linear-gradient", "linear-gradient" ),
1566 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1567 ( "-webkit-radial-gradient", "radial-gradient" ),
1568 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1569]
1570
1571def _CheckNoDeprecatedCSS(input_api, output_api):
1572 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251573 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341574 documentation and iOS CSS for dom distiller
1575 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251576 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531577 results = []
dbeam070cfe62014-10-22 06:44:021578 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251579 black_list = (_EXCLUDED_PATHS +
1580 _TEST_CODE_EXCLUDED_PATHS +
1581 input_api.DEFAULT_BLACK_LIST +
1582 (r"^chrome/common/extensions/docs",
1583 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341584 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051585 r"^components/flags_ui/resources/apple_flags.css",
[email protected]9a48e3f82014-05-22 00:06:251586 r"^native_client_sdk"))
1587 file_filter = lambda f: input_api.FilterSourceFile(
1588 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531589 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1590 for line_num, line in fpath.ChangedContents():
1591 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021592 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531593 results.append(output_api.PresubmitError(
1594 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1595 (fpath.LocalPath(), line_num, deprecated_value, value)))
1596 return results
1597
mohan.reddyf21db962014-10-16 12:26:471598
dbeam070cfe62014-10-22 06:44:021599_DEPRECATED_JS = [
1600 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1601 ( "__defineGetter__", "Object.defineProperty" ),
1602 ( "__defineSetter__", "Object.defineProperty" ),
1603]
1604
1605def _CheckNoDeprecatedJS(input_api, output_api):
1606 """Make sure that we don't use deprecated JS in Chrome code."""
1607 results = []
1608 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1609 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1610 input_api.DEFAULT_BLACK_LIST)
1611 file_filter = lambda f: input_api.FilterSourceFile(
1612 f, white_list=file_inclusion_pattern, black_list=black_list)
1613 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1614 for lnum, line in fpath.ChangedContents():
1615 for (deprecated, replacement) in _DEPRECATED_JS:
1616 if deprecated in line:
1617 results.append(output_api.PresubmitError(
1618 "%s:%d: Use of deprecated JS %s, use %s instead" %
1619 (fpath.LocalPath(), lnum, deprecated, replacement)))
1620 return results
1621
1622
dgnaa68d5e2015-06-10 10:08:221623def _AndroidSpecificOnUploadChecks(input_api, output_api):
1624 """Groups checks that target android code."""
1625 results = []
dgnaa68d5e2015-06-10 10:08:221626 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221627 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291628 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221629 return results
1630
1631
[email protected]22c9bd72011-03-27 16:47:391632def _CommonChecks(input_api, output_api):
1633 """Checks common to both upload and commit."""
1634 results = []
1635 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381636 input_api, output_api,
1637 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461638 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191639 results.extend(
[email protected]760deea2013-12-10 19:33:491640 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541641 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181642 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521643 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221644 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441645 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591646 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061647 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121648 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181649 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221650 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491651 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271652 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031653 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491654 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441655 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271656 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541657 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441658 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
danakj3c84d0c2014-10-06 15:35:461659 # TODO(danakj): Remove this when base/move.h is removed.
dchengcf95c122015-12-18 08:29:161660 results.extend(_CheckForUsingPass(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551661 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041662 results.extend(
1663 input_api.canned_checks.CheckChangeHasNoTabs(
1664 input_api,
1665 output_api,
1666 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401667 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161668 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591669 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081670 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531671 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021672 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471673 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041674 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361675 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231676 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431677 results.extend(_CheckSingletonInHeaders(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241678
1679 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1680 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1681 input_api, output_api,
1682 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381683 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391684 return results
[email protected]1f7b4172010-01-28 01:17:341685
[email protected]b337cb5b2011-01-23 21:24:051686
[email protected]66daa702011-05-28 14:41:461687def _CheckAuthorizedAuthor(input_api, output_api):
1688 """For non-googler/chromites committers, verify the author's email address is
1689 in AUTHORS.
1690 """
[email protected]9bb9cb82011-06-13 20:43:011691 # TODO(maruel): Add it to input_api?
1692 import fnmatch
1693
[email protected]66daa702011-05-28 14:41:461694 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011695 if not author:
1696 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461697 return []
[email protected]c99663292011-05-31 19:46:081698 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461699 input_api.PresubmitLocalPath(), 'AUTHORS')
1700 valid_authors = (
1701 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1702 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181703 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]d8b50be2011-06-15 14:19:441704 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231705 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461706 return [output_api.PresubmitPromptWarning(
1707 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1708 '\n'
1709 'http://www.chromium.org/developers/contributing-code and read the '
1710 '"Legal" section\n'
1711 'If you are a chromite, verify the contributor signed the CLA.') %
1712 author)]
1713 return []
1714
1715
[email protected]b8079ae4a2012-12-05 19:56:491716def _CheckPatchFiles(input_api, output_api):
1717 problems = [f.LocalPath() for f in input_api.AffectedFiles()
1718 if f.LocalPath().endswith(('.orig', '.rej'))]
1719 if problems:
1720 return [output_api.PresubmitError(
1721 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:031722 else:
1723 return []
[email protected]b8079ae4a2012-12-05 19:56:491724
1725
[email protected]b00342e7f2013-03-26 16:21:541726def _DidYouMeanOSMacro(bad_macro):
1727 try:
1728 return {'A': 'OS_ANDROID',
1729 'B': 'OS_BSD',
1730 'C': 'OS_CHROMEOS',
1731 'F': 'OS_FREEBSD',
1732 'L': 'OS_LINUX',
1733 'M': 'OS_MACOSX',
1734 'N': 'OS_NACL',
1735 'O': 'OS_OPENBSD',
1736 'P': 'OS_POSIX',
1737 'S': 'OS_SOLARIS',
1738 'W': 'OS_WIN'}[bad_macro[3].upper()]
1739 except KeyError:
1740 return ''
1741
1742
1743def _CheckForInvalidOSMacrosInFile(input_api, f):
1744 """Check for sensible looking, totally invalid OS macros."""
1745 preprocessor_statement = input_api.re.compile(r'^\s*#')
1746 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
1747 results = []
1748 for lnum, line in f.ChangedContents():
1749 if preprocessor_statement.search(line):
1750 for match in os_macro.finditer(line):
1751 if not match.group(1) in _VALID_OS_MACROS:
1752 good = _DidYouMeanOSMacro(match.group(1))
1753 did_you_mean = ' (did you mean %s?)' % good if good else ''
1754 results.append(' %s:%d %s%s' % (f.LocalPath(),
1755 lnum,
1756 match.group(1),
1757 did_you_mean))
1758 return results
1759
1760
1761def _CheckForInvalidOSMacros(input_api, output_api):
1762 """Check all affected files for invalid OS macros."""
1763 bad_macros = []
1764 for f in input_api.AffectedFiles():
1765 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
1766 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
1767
1768 if not bad_macros:
1769 return []
1770
1771 return [output_api.PresubmitError(
1772 'Possibly invalid OS macro[s] found. Please fix your code\n'
1773 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
1774
lliabraa35bab3932014-10-01 12:16:441775
1776def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
1777 """Check all affected files for invalid "if defined" macros."""
1778 ALWAYS_DEFINED_MACROS = (
1779 "TARGET_CPU_PPC",
1780 "TARGET_CPU_PPC64",
1781 "TARGET_CPU_68K",
1782 "TARGET_CPU_X86",
1783 "TARGET_CPU_ARM",
1784 "TARGET_CPU_MIPS",
1785 "TARGET_CPU_SPARC",
1786 "TARGET_CPU_ALPHA",
1787 "TARGET_IPHONE_SIMULATOR",
1788 "TARGET_OS_EMBEDDED",
1789 "TARGET_OS_IPHONE",
1790 "TARGET_OS_MAC",
1791 "TARGET_OS_UNIX",
1792 "TARGET_OS_WIN32",
1793 )
1794 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
1795 results = []
1796 for lnum, line in f.ChangedContents():
1797 for match in ifdef_macro.finditer(line):
1798 if match.group(1) in ALWAYS_DEFINED_MACROS:
1799 always_defined = ' %s is always defined. ' % match.group(1)
1800 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
1801 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
1802 lnum,
1803 always_defined,
1804 did_you_mean))
1805 return results
1806
1807
1808def _CheckForInvalidIfDefinedMacros(input_api, output_api):
1809 """Check all affected files for invalid "if defined" macros."""
1810 bad_macros = []
1811 for f in input_api.AffectedFiles():
1812 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1813 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
1814
1815 if not bad_macros:
1816 return []
1817
1818 return [output_api.PresubmitError(
1819 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
1820 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
1821 bad_macros)]
1822
1823
dchengcf95c122015-12-18 08:29:161824def _CheckForUsingPass(input_api, output_api):
danakj3c84d0c2014-10-06 15:35:461825 """Check all affected files for using side effects of Pass."""
1826 errors = []
1827 for f in input_api.AffectedFiles():
1828 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1829 for lnum, line in f.ChangedContents():
dchengcf95c122015-12-18 08:29:161830 # Warn on any use of foo.Pass().
1831 if input_api.re.search(r'[a-zA-Z0-9_]+\.Pass\(\)', line):
danakj3c84d0c2014-10-06 15:35:461832 errors.append(output_api.PresubmitError(
dchengcf95c122015-12-18 08:29:161833 ('%s:%d uses Pass(); please use std::move() instead. ' +
1834 'See crbug.com/557422.') % (f.LocalPath(), lnum)))
danakj3c84d0c2014-10-06 15:35:461835 return errors
1836
1837
mlamouria82272622014-09-16 18:45:041838def _CheckForIPCRules(input_api, output_api):
1839 """Check for same IPC rules described in
1840 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
1841 """
1842 base_pattern = r'IPC_ENUM_TRAITS\('
1843 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
1844 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
1845
1846 problems = []
1847 for f in input_api.AffectedSourceFiles(None):
1848 local_path = f.LocalPath()
1849 if not local_path.endswith('.h'):
1850 continue
1851 for line_number, line in f.ChangedContents():
1852 if inclusion_pattern.search(line) and not comment_pattern.search(line):
1853 problems.append(
1854 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1855
1856 if problems:
1857 return [output_api.PresubmitPromptWarning(
1858 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
1859 else:
1860 return []
1861
[email protected]b00342e7f2013-03-26 16:21:541862
mostynbb639aca52015-01-07 20:31:231863def _CheckForWindowsLineEndings(input_api, output_api):
1864 """Check source code and known ascii text files for Windows style line
1865 endings.
1866 """
earthdok1b5e0ee2015-03-10 15:19:101867 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:231868
1869 file_inclusion_pattern = (
1870 known_text_files,
1871 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1872 )
1873
1874 filter = lambda f: input_api.FilterSourceFile(
1875 f, white_list=file_inclusion_pattern, black_list=None)
1876 files = [f.LocalPath() for f in
1877 input_api.AffectedSourceFiles(filter)]
1878
1879 problems = []
1880
1881 for file in files:
1882 fp = open(file, 'r')
1883 for line in fp:
1884 if line.endswith('\r\n'):
1885 problems.append(file)
1886 break
1887 fp.close()
1888
1889 if problems:
1890 return [output_api.PresubmitPromptWarning('Are you sure that you want '
1891 'these files to contain Windows style line endings?\n' +
1892 '\n'.join(problems))]
1893
1894 return []
1895
1896
[email protected]1f7b4172010-01-28 01:17:341897def CheckChangeOnUpload(input_api, output_api):
1898 results = []
1899 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:471900 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
aurimas8d3bc1c52014-10-15 01:02:171901 results.extend(_CheckJavaStyle(input_api, output_api))
scottmg39b29952014-12-08 18:31:281902 results.extend(
1903 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:191904 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221905 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541906 return results
[email protected]ca8d19842009-02-19 16:33:121907
1908
[email protected]1bfb8322014-04-23 01:02:411909def GetTryServerMasterForBot(bot):
1910 """Returns the Try Server master for the given bot.
1911
[email protected]0bb112362014-07-26 04:38:321912 It tries to guess the master from the bot name, but may still fail
1913 and return None. There is no longer a default master.
1914 """
1915 # Potentially ambiguous bot names are listed explicitly.
1916 master_map = {
[email protected]0bb112362014-07-26 04:38:321917 'chromium_presubmit': 'tryserver.chromium.linux',
1918 'blink_presubmit': 'tryserver.chromium.linux',
1919 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:411920 }
[email protected]0bb112362014-07-26 04:38:321921 master = master_map.get(bot)
1922 if not master:
sergiyb37fd293f2015-02-26 06:55:011923 if 'linux' in bot or 'android' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:321924 master = 'tryserver.chromium.linux'
1925 elif 'win' in bot:
1926 master = 'tryserver.chromium.win'
1927 elif 'mac' in bot or 'ios' in bot:
1928 master = 'tryserver.chromium.mac'
1929 return master
[email protected]1bfb8322014-04-23 01:02:411930
1931
Paweł Hajdan, Jr55083782014-12-19 20:32:561932def GetDefaultTryConfigs(bots):
1933 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:011934 """
1935
Paweł Hajdan, Jr55083782014-12-19 20:32:561936 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:411937
1938 # Build up the mapping from tryserver master to bot/test.
1939 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:561940 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:411941 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
1942 return out
[email protected]38c6a512013-12-18 23:48:011943
1944
[email protected]ca8d19842009-02-19 16:33:121945def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:541946 results = []
[email protected]1f7b4172010-01-28 01:17:341947 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541948 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:271949 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:341950 input_api,
1951 output_api,
[email protected]2fdd1f362013-01-16 03:56:031952 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:271953
[email protected]3e4eb112011-01-18 03:29:541954 results.extend(input_api.canned_checks.CheckChangeHasBugField(
1955 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:411956 results.extend(input_api.canned_checks.CheckChangeHasDescription(
1957 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541958 return results