blob: 55131cdd3acf92ecb39e109ad0d01b73fae0970e [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",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
vapierb2053f542017-03-09 19:46:1028 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5429 # Test pages for WebRTC telemetry tests.
30 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4031)
[email protected]ca8d19842009-02-19 16:33:1232
wnwenbdc444e2016-05-25 13:44:1533
[email protected]06e6d0ff2012-12-11 01:36:4434# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# 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,
sdefresne1fccb0a2016-12-19 08:10:5344 r'.+_(api|browser|eg|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]7b054982013-11-27 00:44:4750 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4951 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0852 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4953 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4454)
[email protected]ca8d19842009-02-19 16:33:1255
wnwenbdc444e2016-05-25 13:44:1556
[email protected]eea609a2011-11-18 13:10:1257_TEST_ONLY_WARNING = (
58 'You might be calling functions intended only for testing from\n'
59 'production code. It is OK to ignore this warning if you know what\n'
60 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5861 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1262
63
[email protected]cf9b78f2012-11-14 11:40:2864_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4065 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2166 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
67 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2868
wnwenbdc444e2016-05-25 13:44:1569
[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 ),
jif65398702016-10-27 10:19:48143 (
144 r"/\s+UTF8String\s*]",
145 (
146 'The use of -[NSString UTF8String] is dangerous as it can return null',
147 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
148 'Please use |SysNSStringToUTF8| instead.',
149 ),
150 True,
151 ),
[email protected]127f18ec2012-06-16 05:05:59152)
153
154
155_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20156 # Make sure that gtest's FRIEND_TEST() macro is not used; the
157 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30158 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20159 (
thomasandersone7caaa9b2017-03-29 19:22:53160 r'\bNULL\b',
161 (
162 'New code should not use NULL. Use nullptr instead.',
163 ),
164 True,
165 (),
166 ),
167 (
[email protected]23e6cbc2012-06-16 18:51:20168 'FRIEND_TEST(',
169 (
[email protected]e3c945502012-06-26 20:01:49170 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20171 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
172 ),
173 False,
[email protected]7345da02012-11-27 14:31:49174 (),
[email protected]23e6cbc2012-06-16 18:51:20175 ),
176 (
thomasanderson4b569052016-09-14 20:15:53177 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
178 (
179 'Chrome clients wishing to select events on X windows should use',
180 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
181 'you are selecting events from the GPU process, or if you are using',
182 'an XDisplay other than gfx::GetXDisplay().',
183 ),
184 True,
185 (
186 r"^ui[\\\/]gl[\\\/].*\.cc$",
187 r"^media[\\\/]gpu[\\\/].*\.cc$",
188 r"^gpu[\\\/].*\.cc$",
189 ),
190 ),
191 (
thomasandersone043e3ce2017-06-08 00:43:20192 r'XInternAtom|xcb_intern_atom',
193 (
thomasanderson11aa41d2017-06-08 22:22:38194 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20195 ),
196 True,
197 (
thomasanderson11aa41d2017-06-08 22:22:38198 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
199 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20200 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
201 ),
202 ),
203 (
[email protected]23e6cbc2012-06-16 18:51:20204 'ScopedAllowIO',
205 (
satoruxe1396f8a2017-06-01 06:40:39206 'New production code should not use ScopedAllowIO (using it in',
207 'browser tests is fine). Post a task to the blocking pool or the',
208 'FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20209 ),
[email protected]e3c945502012-06-26 20:01:49210 True,
[email protected]7345da02012-11-27 14:31:49211 (
satoruxe1396f8a2017-06-01 06:40:39212 r"^.*browser(|_)test[a-z_]*\.cc$",
hajimehoshi2acea432017-03-08 08:55:37213 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08214 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32215 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10216 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22217 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31218 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
philipj3f9d5bde2014-08-28 14:09:09219 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49220 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
221 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41222 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
223 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25224 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57225 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
226 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48227 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
228 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01229 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25230 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
231 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
232 r"embedded_test_server\.cc$",
233 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
234 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54235 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16236 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53237 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
238 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45239 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
240 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
241 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
242 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
243 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49244 ),
[email protected]23e6cbc2012-06-16 18:51:20245 ),
[email protected]52657f62013-05-20 05:30:31246 (
tomhudsone2c14d552016-05-26 17:07:46247 'setMatrixClip',
248 (
249 'Overriding setMatrixClip() is prohibited; ',
250 'the base function is deprecated. ',
251 ),
252 True,
253 (),
254 ),
255 (
[email protected]52657f62013-05-20 05:30:31256 'SkRefPtr',
257 (
258 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22259 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31260 ),
261 True,
262 (),
263 ),
264 (
265 'SkAutoRef',
266 (
267 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22268 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31269 ),
270 True,
271 (),
272 ),
273 (
274 'SkAutoTUnref',
275 (
276 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22277 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31278 ),
279 True,
280 (),
281 ),
282 (
283 'SkAutoUnref',
284 (
285 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
286 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22287 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31288 ),
289 True,
290 (),
291 ),
[email protected]d89eec82013-12-03 14:10:59292 (
293 r'/HANDLE_EINTR\(.*close',
294 (
295 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
296 'descriptor will be closed, and it is incorrect to retry the close.',
297 'Either call close directly and ignore its return value, or wrap close',
298 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
299 ),
300 True,
301 (),
302 ),
303 (
304 r'/IGNORE_EINTR\((?!.*close)',
305 (
306 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
307 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
308 ),
309 True,
310 (
311 # Files that #define IGNORE_EINTR.
312 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
313 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
314 ),
315 ),
[email protected]ec5b3f02014-04-04 18:43:43316 (
317 r'/v8::Extension\(',
318 (
319 'Do not introduce new v8::Extensions into the code base, use',
320 'gin::Wrappable instead. See http://crbug.com/334679',
321 ),
322 True,
[email protected]f55c90ee62014-04-12 00:50:03323 (
joaodasilva718f87672014-08-30 09:25:49324 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03325 ),
[email protected]ec5b3f02014-04-04 18:43:43326 ),
skyostilf9469f72015-04-20 10:38:52327 (
jame2d1a952016-04-02 00:27:10328 '#pragma comment(lib,',
329 (
330 'Specify libraries to link with in build files and not in the source.',
331 ),
332 True,
333 (),
334 ),
fdorayc4ac18d2017-05-01 21:39:59335 (
336 'BrowserThread::GetBlockingPool',
337 (
338 'Use base/task_scheduler/post_task.h instead of the blocking pool. See',
339 'mapping between both APIs in content/public/browser/browser_thread.h.',
340 'For questions, contact base/task_scheduler/OWNERS.',
341 ),
342 True,
343 (),
344 ),
gabd52c912a2017-05-11 04:15:59345 (
Gabriel Charette664e4482017-06-13 19:55:29346 'BrowserThread::(FILE|FILE_USER_BLOCKING|DB|PROCESS_LAUNCHER|CACHE)',
347 (
348 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
349 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
350 'For questions, contact base/task_scheduler/OWNERS.',
351 ),
352 True,
353 (),
354 ),
355 (
gabd52c912a2017-05-11 04:15:59356 'base::SequenceChecker',
357 (
358 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
359 ),
360 False,
361 (),
362 ),
363 (
364 'base::ThreadChecker',
365 (
366 'Consider using THREAD_CHECKER macros instead of the class directly.',
367 ),
368 False,
369 (),
370 ),
[email protected]127f18ec2012-06-16 05:05:59371)
372
wnwenbdc444e2016-05-25 13:44:15373
mlamouria82272622014-09-16 18:45:04374_IPC_ENUM_TRAITS_DEPRECATED = (
375 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
376 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
377
[email protected]127f18ec2012-06-16 05:05:59378
[email protected]b00342e7f2013-03-26 16:21:54379_VALID_OS_MACROS = (
380 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08381 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54382 'OS_ANDROID',
383 'OS_BSD',
384 'OS_CAT', # For testing.
385 'OS_CHROMEOS',
386 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37387 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54388 'OS_IOS',
389 'OS_LINUX',
390 'OS_MACOSX',
391 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21392 'OS_NACL_NONSFI',
393 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12394 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54395 'OS_OPENBSD',
396 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37397 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54398 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54399 'OS_WIN',
400)
401
402
agrievef32bcc72016-04-04 14:57:40403_ANDROID_SPECIFIC_PYDEPS_FILES = [
404 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04405 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58406 'build/secondary/third_party/android_platform/'
407 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19408 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40409]
410
wnwenbdc444e2016-05-25 13:44:15411
agrievef32bcc72016-04-04 14:57:40412_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40413]
414
wnwenbdc444e2016-05-25 13:44:15415
agrievef32bcc72016-04-04 14:57:40416_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
417
418
[email protected]55459852011-08-10 15:17:19419def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
420 """Attempts to prevent use of functions intended only for testing in
421 non-testing code. For now this is just a best-effort implementation
422 that ignores header files and may have some false positives. A
423 better implementation would probably need a proper C++ parser.
424 """
425 # We only scan .cc files and the like, as the declaration of
426 # for-testing functions in header files are hard to distinguish from
427 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44428 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19429
jochenc0d4808c2015-07-27 09:25:42430 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19431 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09432 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19433 exclusion_pattern = input_api.re.compile(
434 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
435 base_function_pattern, base_function_pattern))
436
437 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44438 black_list = (_EXCLUDED_PATHS +
439 _TEST_CODE_EXCLUDED_PATHS +
440 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19441 return input_api.FilterSourceFile(
442 affected_file,
443 white_list=(file_inclusion_pattern, ),
444 black_list=black_list)
445
446 problems = []
447 for f in input_api.AffectedSourceFiles(FilterFile):
448 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24449 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03450 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46451 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03452 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19453 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03454 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19455
456 if problems:
[email protected]f7051d52013-04-02 18:31:42457 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03458 else:
459 return []
[email protected]55459852011-08-10 15:17:19460
461
[email protected]10689ca2011-09-02 02:31:54462def _CheckNoIOStreamInHeaders(input_api, output_api):
463 """Checks to make sure no .h files include <iostream>."""
464 files = []
465 pattern = input_api.re.compile(r'^#include\s*<iostream>',
466 input_api.re.MULTILINE)
467 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
468 if not f.LocalPath().endswith('.h'):
469 continue
470 contents = input_api.ReadFile(f)
471 if pattern.search(contents):
472 files.append(f)
473
474 if len(files):
yolandyandaabc6d2016-04-18 18:29:39475 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06476 'Do not #include <iostream> in header files, since it inserts static '
477 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54478 '#include <ostream>. See http://crbug.com/94794',
479 files) ]
480 return []
481
482
[email protected]72df4e782012-06-21 16:28:18483def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52484 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18485 problems = []
486 for f in input_api.AffectedFiles():
487 if (not f.LocalPath().endswith(('.cc', '.mm'))):
488 continue
489
490 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04491 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18492 problems.append(' %s:%d' % (f.LocalPath(), line_num))
493
494 if not problems:
495 return []
496 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
497 '\n'.join(problems))]
498
499
danakj61c1aa22015-10-26 19:55:52500def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57501 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52502 errors = []
503 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
504 input_api.re.MULTILINE)
505 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
506 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
507 continue
508 for lnum, line in f.ChangedContents():
509 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17510 errors.append(output_api.PresubmitError(
511 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57512 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17513 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52514 return errors
515
516
mcasasb7440c282015-02-04 14:52:19517def _FindHistogramNameInLine(histogram_name, line):
518 """Tries to find a histogram name or prefix in a line."""
519 if not "affected-histogram" in line:
520 return histogram_name in line
521 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
522 # the histogram_name.
523 if not '"' in line:
524 return False
525 histogram_prefix = line.split('\"')[1]
526 return histogram_prefix in histogram_name
527
528
529def _CheckUmaHistogramChanges(input_api, output_api):
530 """Check that UMA histogram names in touched lines can still be found in other
531 lines of the patch or in histograms.xml. Note that this check would not catch
532 the reverse: changes in histograms.xml not matched in the code itself."""
533 touched_histograms = []
534 histograms_xml_modifications = []
535 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
536 for f in input_api.AffectedFiles():
537 # If histograms.xml itself is modified, keep the modified lines for later.
538 if f.LocalPath().endswith(('histograms.xml')):
539 histograms_xml_modifications = f.ChangedContents()
540 continue
541 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
542 continue
543 for line_num, line in f.ChangedContents():
544 found = pattern.search(line)
545 if found:
546 touched_histograms.append([found.group(1), f, line_num])
547
548 # Search for the touched histogram names in the local modifications to
549 # histograms.xml, and, if not found, on the base histograms.xml file.
550 unmatched_histograms = []
551 for histogram_info in touched_histograms:
552 histogram_name_found = False
553 for line_num, line in histograms_xml_modifications:
554 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
555 if histogram_name_found:
556 break
557 if not histogram_name_found:
558 unmatched_histograms.append(histogram_info)
559
eromanb90c82e7e32015-04-01 15:13:49560 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19561 problems = []
562 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49563 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19564 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45565 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19566 histogram_name_found = False
567 for line in histograms_xml:
568 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
569 if histogram_name_found:
570 break
571 if not histogram_name_found:
572 problems.append(' [%s:%d] %s' %
573 (f.LocalPath(), line_num, histogram_name))
574
575 if not problems:
576 return []
577 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
578 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49579 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19580
wnwenbdc444e2016-05-25 13:44:15581
yolandyandaabc6d2016-04-18 18:29:39582def _CheckFlakyTestUsage(input_api, output_api):
583 """Check that FlakyTest annotation is our own instead of the android one"""
584 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
585 files = []
586 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
587 if f.LocalPath().endswith('Test.java'):
588 if pattern.search(input_api.ReadFile(f)):
589 files.append(f)
590 if len(files):
591 return [output_api.PresubmitError(
592 'Use org.chromium.base.test.util.FlakyTest instead of '
593 'android.test.FlakyTest',
594 files)]
595 return []
mcasasb7440c282015-02-04 14:52:19596
wnwenbdc444e2016-05-25 13:44:15597
[email protected]8ea5d4b2011-09-13 21:49:22598def _CheckNoNewWStrings(input_api, output_api):
599 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27600 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22601 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20602 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57603 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34604 '/win/' in f.LocalPath() or
605 'chrome_elf' in f.LocalPath() or
606 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20607 continue
[email protected]8ea5d4b2011-09-13 21:49:22608
[email protected]a11dbe9b2012-08-07 01:32:58609 allowWString = False
[email protected]b5c24292011-11-28 14:38:20610 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58611 if 'presubmit: allow wstring' in line:
612 allowWString = True
613 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27614 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58615 allowWString = False
616 else:
617 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22618
[email protected]55463aa62011-10-12 00:48:27619 if not problems:
620 return []
621 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58622 ' If you are calling a cross-platform API that accepts a wstring, '
623 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27624 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22625
626
[email protected]2a8ac9c2011-10-19 17:20:44627def _CheckNoDEPSGIT(input_api, output_api):
628 """Make sure .DEPS.git is never modified manually."""
629 if any(f.LocalPath().endswith('.DEPS.git') for f in
630 input_api.AffectedFiles()):
631 return [output_api.PresubmitError(
632 'Never commit changes to .DEPS.git. This file is maintained by an\n'
633 'automated system based on what\'s in DEPS and your changes will be\n'
634 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34635 '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:44636 'for more information')]
637 return []
638
639
tandriief664692014-09-23 14:51:47640def _CheckValidHostsInDEPS(input_api, output_api):
641 """Checks that DEPS file deps are from allowed_hosts."""
642 # Run only if DEPS file has been modified to annoy fewer bystanders.
643 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
644 return []
645 # Outsource work to gclient verify
646 try:
647 input_api.subprocess.check_output(['gclient', 'verify'])
648 return []
649 except input_api.subprocess.CalledProcessError, error:
650 return [output_api.PresubmitError(
651 'DEPS file must have only git dependencies.',
652 long_text=error.output)]
653
654
[email protected]127f18ec2012-06-16 05:05:59655def _CheckNoBannedFunctions(input_api, output_api):
656 """Make sure that banned functions are not used."""
657 warnings = []
658 errors = []
659
wnwenbdc444e2016-05-25 13:44:15660 def IsBlacklisted(affected_file, blacklist):
661 local_path = affected_file.LocalPath()
662 for item in blacklist:
663 if input_api.re.match(item, local_path):
664 return True
665 return False
666
667 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
668 matched = False
669 if func_name[0:1] == '/':
670 regex = func_name[1:]
671 if input_api.re.search(regex, line):
672 matched = True
673 elif func_name in line:
dchenge07de812016-06-20 19:27:17674 matched = True
wnwenbdc444e2016-05-25 13:44:15675 if matched:
dchenge07de812016-06-20 19:27:17676 problems = warnings
wnwenbdc444e2016-05-25 13:44:15677 if error:
dchenge07de812016-06-20 19:27:17678 problems = errors
wnwenbdc444e2016-05-25 13:44:15679 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
680 for message_line in message:
681 problems.append(' %s' % message_line)
682
[email protected]127f18ec2012-06-16 05:05:59683 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
684 for f in input_api.AffectedFiles(file_filter=file_filter):
685 for line_num, line in f.ChangedContents():
686 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15687 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59688
689 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
690 for f in input_api.AffectedFiles(file_filter=file_filter):
691 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49692 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49693 if IsBlacklisted(f, excluded_paths):
694 continue
wnwenbdc444e2016-05-25 13:44:15695 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59696
697 result = []
698 if (warnings):
699 result.append(output_api.PresubmitPromptWarning(
700 'Banned functions were used.\n' + '\n'.join(warnings)))
701 if (errors):
702 result.append(output_api.PresubmitError(
703 'Banned functions were used.\n' + '\n'.join(errors)))
704 return result
705
706
[email protected]6c063c62012-07-11 19:11:06707def _CheckNoPragmaOnce(input_api, output_api):
708 """Make sure that banned functions are not used."""
709 files = []
710 pattern = input_api.re.compile(r'^#pragma\s+once',
711 input_api.re.MULTILINE)
712 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
713 if not f.LocalPath().endswith('.h'):
714 continue
715 contents = input_api.ReadFile(f)
716 if pattern.search(contents):
717 files.append(f)
718
719 if files:
720 return [output_api.PresubmitError(
721 'Do not use #pragma once in header files.\n'
722 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
723 files)]
724 return []
725
[email protected]127f18ec2012-06-16 05:05:59726
[email protected]e7479052012-09-19 00:26:12727def _CheckNoTrinaryTrueFalse(input_api, output_api):
728 """Checks to make sure we don't introduce use of foo ? true : false."""
729 problems = []
730 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
731 for f in input_api.AffectedFiles():
732 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
733 continue
734
735 for line_num, line in f.ChangedContents():
736 if pattern.match(line):
737 problems.append(' %s:%d' % (f.LocalPath(), line_num))
738
739 if not problems:
740 return []
741 return [output_api.PresubmitPromptWarning(
742 'Please consider avoiding the "? true : false" pattern if possible.\n' +
743 '\n'.join(problems))]
744
745
[email protected]55f9f382012-07-31 11:02:18746def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28747 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18748 change. Breaking - rules is an error, breaking ! rules is a
749 warning.
750 """
mohan.reddyf21db962014-10-16 12:26:47751 import sys
[email protected]55f9f382012-07-31 11:02:18752 # We need to wait until we have an input_api object and use this
753 # roundabout construct to import checkdeps because this file is
754 # eval-ed and thus doesn't have __file__.
755 original_sys_path = sys.path
756 try:
757 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47758 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18759 import checkdeps
760 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28761 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18762 from rules import Rule
763 finally:
764 # Restore sys.path to what it was before.
765 sys.path = original_sys_path
766
767 added_includes = []
rhalavati08acd232017-04-03 07:23:28768 added_imports = []
[email protected]55f9f382012-07-31 11:02:18769 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28770 if CppChecker.IsCppFile(f.LocalPath()):
771 changed_lines = [line for line_num, line in f.ChangedContents()]
772 added_includes.append([f.LocalPath(), changed_lines])
773 elif ProtoChecker.IsProtoFile(f.LocalPath()):
774 changed_lines = [line for line_num, line in f.ChangedContents()]
775 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18776
[email protected]26385172013-05-09 23:11:35777 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18778
779 error_descriptions = []
780 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28781 error_subjects = set()
782 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18783 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
784 added_includes):
785 description_with_path = '%s\n %s' % (path, rule_description)
786 if rule_type == Rule.DISALLOW:
787 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28788 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18789 else:
790 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28791 warning_subjects.add("#includes")
792
793 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
794 added_imports):
795 description_with_path = '%s\n %s' % (path, rule_description)
796 if rule_type == Rule.DISALLOW:
797 error_descriptions.append(description_with_path)
798 error_subjects.add("imports")
799 else:
800 warning_descriptions.append(description_with_path)
801 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18802
803 results = []
804 if error_descriptions:
805 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28806 'You added one or more %s that violate checkdeps rules.'
807 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18808 error_descriptions))
809 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42810 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28811 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18812 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28813 '%s? See relevant DEPS file(s) for details and contacts.' %
814 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18815 warning_descriptions))
816 return results
817
818
[email protected]fbcafe5a2012-08-08 15:31:22819def _CheckFilePermissions(input_api, output_api):
820 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15821 if input_api.platform == 'win32':
822 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29823 checkperms_tool = input_api.os_path.join(
824 input_api.PresubmitLocalPath(),
825 'tools', 'checkperms', 'checkperms.py')
826 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47827 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22828 for f in input_api.AffectedFiles():
829 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11830 try:
831 input_api.subprocess.check_output(args)
832 return []
833 except input_api.subprocess.CalledProcessError as error:
834 return [output_api.PresubmitError(
835 'checkperms.py failed:',
836 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22837
838
robertocn832f5992017-01-04 19:01:30839def _CheckTeamTags(input_api, output_api):
840 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
841 checkteamtags_tool = input_api.os_path.join(
842 input_api.PresubmitLocalPath(),
843 'tools', 'checkteamtags', 'checkteamtags.py')
844 args = [input_api.python_executable, checkteamtags_tool,
845 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22846 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30847 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
848 'OWNERS']
849 try:
850 if files:
851 input_api.subprocess.check_output(args + files)
852 return []
853 except input_api.subprocess.CalledProcessError as error:
854 return [output_api.PresubmitError(
855 'checkteamtags.py failed:',
856 long_text=error.output)]
857
858
[email protected]c8278b32012-10-30 20:35:49859def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
860 """Makes sure we don't include ui/aura/window_property.h
861 in header files.
862 """
863 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
864 errors = []
865 for f in input_api.AffectedFiles():
866 if not f.LocalPath().endswith('.h'):
867 continue
868 for line_num, line in f.ChangedContents():
869 if pattern.match(line):
870 errors.append(' %s:%d' % (f.LocalPath(), line_num))
871
872 results = []
873 if errors:
874 results.append(output_api.PresubmitError(
875 'Header files should not include ui/aura/window_property.h', errors))
876 return results
877
878
[email protected]cf9b78f2012-11-14 11:40:28879def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
880 """Checks that the lines in scope occur in the right order.
881
882 1. C system files in alphabetical order
883 2. C++ system files in alphabetical order
884 3. Project's .h files
885 """
886
887 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
888 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
889 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
890
891 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
892
893 state = C_SYSTEM_INCLUDES
894
895 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57896 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28897 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55898 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28899 for line_num, line in scope:
900 if c_system_include_pattern.match(line):
901 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55902 problem_linenums.append((line_num, previous_line_num,
903 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28904 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55905 problem_linenums.append((line_num, previous_line_num,
906 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28907 elif cpp_system_include_pattern.match(line):
908 if state == C_SYSTEM_INCLUDES:
909 state = CPP_SYSTEM_INCLUDES
910 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55911 problem_linenums.append((line_num, previous_line_num,
912 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28913 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55914 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28915 elif custom_include_pattern.match(line):
916 if state != CUSTOM_INCLUDES:
917 state = CUSTOM_INCLUDES
918 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55919 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28920 else:
brucedawson70fadb02015-06-30 17:47:55921 problem_linenums.append((line_num, previous_line_num,
922 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28923 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57924 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28925
926 warnings = []
brucedawson70fadb02015-06-30 17:47:55927 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57928 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55929 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28930 return warnings
931
932
[email protected]ac294a12012-12-06 16:38:43933def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28934 """Checks the #include order for the given file f."""
935
[email protected]2299dcf2012-11-15 19:56:24936 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30937 # Exclude the following includes from the check:
938 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
939 # specific order.
940 # 2) <atlbase.h>, "build/build_config.h"
941 excluded_include_pattern = input_api.re.compile(
942 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24943 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33944 # Match the final or penultimate token if it is xxxtest so we can ignore it
945 # when considering the special first include.
946 test_file_tag_pattern = input_api.re.compile(
947 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11948 if_pattern = input_api.re.compile(
949 r'\s*#\s*(if|elif|else|endif|define|undef).*')
950 # Some files need specialized order of includes; exclude such files from this
951 # check.
952 uncheckable_includes_pattern = input_api.re.compile(
953 r'\s*#include '
954 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28955
956 contents = f.NewContents()
957 warnings = []
958 line_num = 0
959
[email protected]ac294a12012-12-06 16:38:43960 # Handle the special first include. If the first include file is
961 # some/path/file.h, the corresponding including file can be some/path/file.cc,
962 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
963 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33964 # If the included file is some/path/file_platform.h the including file could
965 # also be some/path/file_xxxtest_platform.h.
966 including_file_base_name = test_file_tag_pattern.sub(
967 '', input_api.os_path.basename(f.LocalPath()))
968
[email protected]ac294a12012-12-06 16:38:43969 for line in contents:
970 line_num += 1
971 if system_include_pattern.match(line):
972 # No special first include -> process the line again along with normal
973 # includes.
974 line_num -= 1
975 break
976 match = custom_include_pattern.match(line)
977 if match:
978 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33979 header_basename = test_file_tag_pattern.sub(
980 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
981
982 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24983 # No special first include -> process the line again along with normal
984 # includes.
985 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43986 break
[email protected]cf9b78f2012-11-14 11:40:28987
988 # Split into scopes: Each region between #if and #endif is its own scope.
989 scopes = []
990 current_scope = []
991 for line in contents[line_num:]:
992 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11993 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54994 continue
[email protected]2309b0fa02012-11-16 12:18:27995 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28996 scopes.append(current_scope)
997 current_scope = []
[email protected]962f117e2012-11-22 18:11:56998 elif ((system_include_pattern.match(line) or
999 custom_include_pattern.match(line)) and
1000 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:281001 current_scope.append((line_num, line))
1002 scopes.append(current_scope)
1003
1004 for scope in scopes:
1005 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
1006 changed_linenums))
1007 return warnings
1008
1009
1010def _CheckIncludeOrder(input_api, output_api):
1011 """Checks that the #include order is correct.
1012
1013 1. The corresponding header for source files.
1014 2. C system files in alphabetical order
1015 3. C++ system files in alphabetical order
1016 4. Project's .h files in alphabetical order
1017
[email protected]ac294a12012-12-06 16:38:431018 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
1019 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:281020 """
[email protected]e120b012014-08-15 19:08:351021 def FileFilterIncludeOrder(affected_file):
1022 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
1023 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:281024
1025 warnings = []
[email protected]e120b012014-08-15 19:08:351026 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:081027 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:431028 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
1029 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:281030
1031 results = []
1032 if warnings:
[email protected]f7051d52013-04-02 18:31:421033 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:531034 warnings))
[email protected]cf9b78f2012-11-14 11:40:281035 return results
1036
1037
[email protected]70ca77752012-11-20 03:45:031038def _CheckForVersionControlConflictsInFile(input_api, f):
1039 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1040 errors = []
1041 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231042 if f.LocalPath().endswith('.md'):
1043 # First-level headers in markdown look a lot like version control
1044 # conflict markers. http://daringfireball.net/projects/markdown/basics
1045 continue
[email protected]70ca77752012-11-20 03:45:031046 if pattern.match(line):
1047 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1048 return errors
1049
1050
1051def _CheckForVersionControlConflicts(input_api, output_api):
1052 """Usually this is not intentional and will cause a compile failure."""
1053 errors = []
1054 for f in input_api.AffectedFiles():
1055 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1056
1057 results = []
1058 if errors:
1059 results.append(output_api.PresubmitError(
1060 'Version control conflict markers found, please resolve.', errors))
1061 return results
1062
estadee17314a02017-01-12 16:22:161063def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1064 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1065 errors = []
1066 for f in input_api.AffectedFiles():
1067 for line_num, line in f.ChangedContents():
1068 if pattern.search(line):
1069 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1070
1071 results = []
1072 if errors:
1073 results.append(output_api.PresubmitPromptWarning(
1074 'Found Google support URL addressed by answer number. Please replace with '
1075 'a p= identifier instead. See crbug.com/679462\n', errors))
1076 return results
1077
[email protected]70ca77752012-11-20 03:45:031078
[email protected]06e6d0ff2012-12-11 01:36:441079def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1080 def FilterFile(affected_file):
1081 """Filter function for use with input_api.AffectedSourceFiles,
1082 below. This filters out everything except non-test files from
1083 top-level directories that generally speaking should not hard-code
1084 service URLs (e.g. src/android_webview/, src/content/ and others).
1085 """
1086 return input_api.FilterSourceFile(
1087 affected_file,
[email protected]78bb39d62012-12-11 15:11:561088 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441089 black_list=(_EXCLUDED_PATHS +
1090 _TEST_CODE_EXCLUDED_PATHS +
1091 input_api.DEFAULT_BLACK_LIST))
1092
reillyi38965732015-11-16 18:27:331093 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1094 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461095 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1096 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441097 problems = [] # items are (filename, line_number, line)
1098 for f in input_api.AffectedSourceFiles(FilterFile):
1099 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461100 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441101 problems.append((f.LocalPath(), line_num, line))
1102
1103 if problems:
[email protected]f7051d52013-04-02 18:31:421104 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441105 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581106 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441107 [' %s:%d: %s' % (
1108 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031109 else:
1110 return []
[email protected]06e6d0ff2012-12-11 01:36:441111
1112
[email protected]d2530012013-01-25 16:39:271113def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1114 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311115 The native_client_sdk directory is excluded because it has auto-generated PNG
1116 files for documentation.
[email protected]d2530012013-01-25 16:39:271117 """
[email protected]d2530012013-01-25 16:39:271118 errors = []
binji0dcdf342014-12-12 18:32:311119 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1120 black_list = (r'^native_client_sdk[\\\/]',)
1121 file_filter = lambda f: input_api.FilterSourceFile(
1122 f, white_list=white_list, black_list=black_list)
1123 for f in input_api.AffectedFiles(include_deletes=False,
1124 file_filter=file_filter):
1125 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271126
1127 results = []
1128 if errors:
1129 results.append(output_api.PresubmitError(
1130 'The name of PNG files should not have abbreviations. \n'
1131 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1132 'Contact [email protected] if you have questions.', errors))
1133 return results
1134
1135
Daniel Cheng4dcdb6b2017-04-13 08:30:171136def _ExtractAddRulesFromParsedDeps(parsed_deps):
1137 """Extract the rules that add dependencies from a parsed DEPS file.
1138
1139 Args:
1140 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1141 add_rules = set()
1142 add_rules.update([
1143 rule[1:] for rule in parsed_deps.get('include_rules', [])
1144 if rule.startswith('+') or rule.startswith('!')
1145 ])
1146 for specific_file, rules in parsed_deps.get('specific_include_rules',
1147 {}).iteritems():
1148 add_rules.update([
1149 rule[1:] for rule in rules
1150 if rule.startswith('+') or rule.startswith('!')
1151 ])
1152 return add_rules
1153
1154
1155def _ParseDeps(contents):
1156 """Simple helper for parsing DEPS files."""
1157 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171158 class _VarImpl:
1159
1160 def __init__(self, local_scope):
1161 self._local_scope = local_scope
1162
1163 def Lookup(self, var_name):
1164 """Implements the Var syntax."""
1165 try:
1166 return self._local_scope['vars'][var_name]
1167 except KeyError:
1168 raise Exception('Var is not defined: %s' % var_name)
1169
1170 local_scope = {}
1171 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171172 'Var': _VarImpl(local_scope).Lookup,
1173 }
1174 exec contents in global_scope, local_scope
1175 return local_scope
1176
1177
1178def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081179 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411180 a set of DEPS entries that we should look up.
1181
1182 For a directory (rather than a specific filename) we fake a path to
1183 a specific filename by adding /DEPS. This is chosen as a file that
1184 will seldom or never be subject to per-file include_rules.
1185 """
[email protected]2b438d62013-11-14 17:54:141186 # We ignore deps entries on auto-generated directories.
1187 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081188
Daniel Cheng4dcdb6b2017-04-13 08:30:171189 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1190 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1191
1192 added_deps = new_deps.difference(old_deps)
1193
[email protected]2b438d62013-11-14 17:54:141194 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171195 for added_dep in added_deps:
1196 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1197 continue
1198 # Assume that a rule that ends in .h is a rule for a specific file.
1199 if added_dep.endswith('.h'):
1200 results.add(added_dep)
1201 else:
1202 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081203 return results
1204
1205
[email protected]e871964c2013-05-13 14:14:551206def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1207 """When a dependency prefixed with + is added to a DEPS file, we
1208 want to make sure that the change is reviewed by an OWNER of the
1209 target file or directory, to avoid layering violations from being
1210 introduced. This check verifies that this happens.
1211 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171212 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241213
1214 file_filter = lambda f: not input_api.re.match(
1215 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1216 for f in input_api.AffectedFiles(include_deletes=False,
1217 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551218 filename = input_api.os_path.basename(f.LocalPath())
1219 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171220 virtual_depended_on_files.update(_CalculateAddedDeps(
1221 input_api.os_path,
1222 '\n'.join(f.OldContents()),
1223 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551224
[email protected]e871964c2013-05-13 14:14:551225 if not virtual_depended_on_files:
1226 return []
1227
1228 if input_api.is_committing:
1229 if input_api.tbr:
1230 return [output_api.PresubmitNotifyResult(
1231 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271232 if input_api.dry_run:
1233 return [output_api.PresubmitNotifyResult(
1234 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551235 if not input_api.change.issue:
1236 return [output_api.PresubmitError(
1237 "DEPS approval by OWNERS check failed: this change has "
1238 "no Rietveld issue number, so we can't check it for approvals.")]
1239 output = output_api.PresubmitError
1240 else:
1241 output = output_api.PresubmitNotifyResult
1242
1243 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501244 owner_email, reviewers = (
1245 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1246 input_api,
1247 owners_db.email_regexp,
1248 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551249
1250 owner_email = owner_email or input_api.change.author_email
1251
[email protected]de4f7d22013-05-23 14:27:461252 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511253 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461254 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551255 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1256 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411257
1258 # We strip the /DEPS part that was added by
1259 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1260 # directory.
1261 def StripDeps(path):
1262 start_deps = path.rfind('/DEPS')
1263 if start_deps != -1:
1264 return path[:start_deps]
1265 else:
1266 return path
1267 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551268 for path in missing_files]
1269
1270 if unapproved_dependencies:
1271 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151272 output('You need LGTM from owners of depends-on paths in DEPS that were '
1273 'modified in this CL:\n %s' %
1274 '\n '.join(sorted(unapproved_dependencies)))]
1275 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1276 output_list.append(output(
1277 'Suggested missing target path OWNERS:\n %s' %
1278 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551279 return output_list
1280
1281 return []
1282
1283
[email protected]85218562013-11-22 07:41:401284def _CheckSpamLogging(input_api, output_api):
1285 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1286 black_list = (_EXCLUDED_PATHS +
1287 _TEST_CODE_EXCLUDED_PATHS +
1288 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501289 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191290 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481291 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461292 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121293 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1294 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581295 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161296 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031297 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151298 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1299 r"^chromecast[\\\/]",
1300 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481301 r"^components[\\\/]browser_watcher[\\\/]"
1302 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311303 r"^components[\\\/]html_viewer[\\\/]"
1304 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461305 # TODO(peter): Remove this exception. https://crbug.com/534537
1306 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1307 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251308 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1309 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241310 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111311 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151312 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111313 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521314 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501315 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361316 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311317 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131318 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001319 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441320 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451321 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021322 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351323 r"dump_file_system.cc$",
1324 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401325 source_file_filter = lambda x: input_api.FilterSourceFile(
1326 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1327
thomasanderson625d3932017-03-29 07:16:581328 log_info = set([])
1329 printf = set([])
[email protected]85218562013-11-22 07:41:401330
1331 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581332 for _, line in f.ChangedContents():
1333 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1334 log_info.add(f.LocalPath())
1335 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1336 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371337
thomasanderson625d3932017-03-29 07:16:581338 if input_api.re.search(r"\bprintf\(", line):
1339 printf.add(f.LocalPath())
1340 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1341 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401342
1343 if log_info:
1344 return [output_api.PresubmitError(
1345 'These files spam the console log with LOG(INFO):',
1346 items=log_info)]
1347 if printf:
1348 return [output_api.PresubmitError(
1349 'These files spam the console log with printf/fprintf:',
1350 items=printf)]
1351 return []
1352
1353
[email protected]49aa76a2013-12-04 06:59:161354def _CheckForAnonymousVariables(input_api, output_api):
1355 """These types are all expected to hold locks while in scope and
1356 so should never be anonymous (which causes them to be immediately
1357 destroyed)."""
1358 they_who_must_be_named = [
1359 'base::AutoLock',
1360 'base::AutoReset',
1361 'base::AutoUnlock',
1362 'SkAutoAlphaRestore',
1363 'SkAutoBitmapShaderInstall',
1364 'SkAutoBlitterChoose',
1365 'SkAutoBounderCommit',
1366 'SkAutoCallProc',
1367 'SkAutoCanvasRestore',
1368 'SkAutoCommentBlock',
1369 'SkAutoDescriptor',
1370 'SkAutoDisableDirectionCheck',
1371 'SkAutoDisableOvalCheck',
1372 'SkAutoFree',
1373 'SkAutoGlyphCache',
1374 'SkAutoHDC',
1375 'SkAutoLockColors',
1376 'SkAutoLockPixels',
1377 'SkAutoMalloc',
1378 'SkAutoMaskFreeImage',
1379 'SkAutoMutexAcquire',
1380 'SkAutoPathBoundsUpdate',
1381 'SkAutoPDFRelease',
1382 'SkAutoRasterClipValidate',
1383 'SkAutoRef',
1384 'SkAutoTime',
1385 'SkAutoTrace',
1386 'SkAutoUnref',
1387 ]
1388 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1389 # bad: base::AutoLock(lock.get());
1390 # not bad: base::AutoLock lock(lock.get());
1391 bad_pattern = input_api.re.compile(anonymous)
1392 # good: new base::AutoLock(lock.get())
1393 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1394 errors = []
1395
1396 for f in input_api.AffectedFiles():
1397 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1398 continue
1399 for linenum, line in f.ChangedContents():
1400 if bad_pattern.search(line) and not good_pattern.search(line):
1401 errors.append('%s:%d' % (f.LocalPath(), linenum))
1402
1403 if errors:
1404 return [output_api.PresubmitError(
1405 'These lines create anonymous variables that need to be named:',
1406 items=errors)]
1407 return []
1408
1409
[email protected]5fe0f8742013-11-29 01:04:591410def _CheckCygwinShell(input_api, output_api):
1411 source_file_filter = lambda x: input_api.FilterSourceFile(
1412 x, white_list=(r'.+\.(gyp|gypi)$',))
1413 cygwin_shell = []
1414
1415 for f in input_api.AffectedSourceFiles(source_file_filter):
1416 for linenum, line in f.ChangedContents():
1417 if 'msvs_cygwin_shell' in line:
1418 cygwin_shell.append(f.LocalPath())
1419 break
1420
1421 if cygwin_shell:
1422 return [output_api.PresubmitError(
1423 'These files should not use msvs_cygwin_shell (the default is 0):',
1424 items=cygwin_shell)]
1425 return []
1426
[email protected]85218562013-11-22 07:41:401427
[email protected]999261d2014-03-03 20:08:081428def _CheckUserActionUpdate(input_api, output_api):
1429 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521430 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081431 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521432 # If actions.xml is already included in the changelist, the PRESUBMIT
1433 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081434 return []
1435
[email protected]999261d2014-03-03 20:08:081436 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1437 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521438 current_actions = None
[email protected]999261d2014-03-03 20:08:081439 for f in input_api.AffectedFiles(file_filter=file_filter):
1440 for line_num, line in f.ChangedContents():
1441 match = input_api.re.search(action_re, line)
1442 if match:
[email protected]2f92dec2014-03-07 19:21:521443 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1444 # loaded only once.
1445 if not current_actions:
1446 with open('tools/metrics/actions/actions.xml') as actions_f:
1447 current_actions = actions_f.read()
1448 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081449 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521450 action = 'name="{0}"'.format(action_name)
1451 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081452 return [output_api.PresubmitPromptWarning(
1453 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521454 'tools/metrics/actions/actions.xml. Please run '
1455 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081456 % (f.LocalPath(), line_num, action_name))]
1457 return []
1458
1459
[email protected]99171a92014-06-03 08:44:471460def _GetJSONParseError(input_api, filename, eat_comments=True):
1461 try:
1462 contents = input_api.ReadFile(filename)
1463 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131464 import sys
1465 original_sys_path = sys.path
1466 try:
1467 sys.path = sys.path + [input_api.os_path.join(
1468 input_api.PresubmitLocalPath(),
1469 'tools', 'json_comment_eater')]
1470 import json_comment_eater
1471 finally:
1472 sys.path = original_sys_path
1473 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471474
1475 input_api.json.loads(contents)
1476 except ValueError as e:
1477 return e
1478 return None
1479
1480
1481def _GetIDLParseError(input_api, filename):
1482 try:
1483 contents = input_api.ReadFile(filename)
1484 idl_schema = input_api.os_path.join(
1485 input_api.PresubmitLocalPath(),
1486 'tools', 'json_schema_compiler', 'idl_schema.py')
1487 process = input_api.subprocess.Popen(
1488 [input_api.python_executable, idl_schema],
1489 stdin=input_api.subprocess.PIPE,
1490 stdout=input_api.subprocess.PIPE,
1491 stderr=input_api.subprocess.PIPE,
1492 universal_newlines=True)
1493 (_, error) = process.communicate(input=contents)
1494 return error or None
1495 except ValueError as e:
1496 return e
1497
1498
1499def _CheckParseErrors(input_api, output_api):
1500 """Check that IDL and JSON files do not contain syntax errors."""
1501 actions = {
1502 '.idl': _GetIDLParseError,
1503 '.json': _GetJSONParseError,
1504 }
1505 # These paths contain test data and other known invalid JSON files.
1506 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491507 r'test[\\\/]data[\\\/]',
1508 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471509 ]
1510 # Most JSON files are preprocessed and support comments, but these do not.
1511 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491512 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471513 ]
1514 # Only run IDL checker on files in these directories.
1515 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491516 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1517 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471518 ]
1519
1520 def get_action(affected_file):
1521 filename = affected_file.LocalPath()
1522 return actions.get(input_api.os_path.splitext(filename)[1])
1523
1524 def MatchesFile(patterns, path):
1525 for pattern in patterns:
1526 if input_api.re.search(pattern, path):
1527 return True
1528 return False
1529
1530 def FilterFile(affected_file):
1531 action = get_action(affected_file)
1532 if not action:
1533 return False
1534 path = affected_file.LocalPath()
1535
1536 if MatchesFile(excluded_patterns, path):
1537 return False
1538
1539 if (action == _GetIDLParseError and
1540 not MatchesFile(idl_included_patterns, path)):
1541 return False
1542 return True
1543
1544 results = []
1545 for affected_file in input_api.AffectedFiles(
1546 file_filter=FilterFile, include_deletes=False):
1547 action = get_action(affected_file)
1548 kwargs = {}
1549 if (action == _GetJSONParseError and
1550 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1551 kwargs['eat_comments'] = False
1552 parse_error = action(input_api,
1553 affected_file.AbsoluteLocalPath(),
1554 **kwargs)
1555 if parse_error:
1556 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1557 (affected_file.LocalPath(), parse_error)))
1558 return results
1559
1560
[email protected]760deea2013-12-10 19:33:491561def _CheckJavaStyle(input_api, output_api):
1562 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471563 import sys
[email protected]760deea2013-12-10 19:33:491564 original_sys_path = sys.path
1565 try:
1566 sys.path = sys.path + [input_api.os_path.join(
1567 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1568 import checkstyle
1569 finally:
1570 # Restore sys.path to what it was before.
1571 sys.path = original_sys_path
1572
1573 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091574 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511575 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491576
1577
dchenge07de812016-06-20 19:27:171578def _CheckIpcOwners(input_api, output_api):
1579 """Checks that affected files involving IPC have an IPC OWNERS rule.
1580
1581 Whether or not a file affects IPC is determined by a simple whitelist of
1582 filename patterns."""
1583 file_patterns = [
palmerb19a0932017-01-24 04:00:311584 # Legacy IPC:
dchenge07de812016-06-20 19:27:171585 '*_messages.cc',
1586 '*_messages*.h',
1587 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311588 # Mojo IPC:
dchenge07de812016-06-20 19:27:171589 '*.mojom',
1590 '*_struct_traits*.*',
1591 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311592 '*.typemap',
1593 # Android native IPC:
1594 '*.aidl',
1595 # Blink uses a different file naming convention:
1596 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171597 '*StructTraits*.*',
1598 '*TypeConverter*.*',
1599 ]
1600
scottmg7a6ed5ba2016-11-04 18:22:041601 # These third_party directories do not contain IPCs, but contain files
1602 # matching the above patterns, which trigger false positives.
1603 exclude_paths = [
1604 'third_party/crashpad/*',
1605 ]
1606
dchenge07de812016-06-20 19:27:171607 # Dictionary mapping an OWNERS file path to Patterns.
1608 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1609 # rules ) to a PatternEntry.
1610 # PatternEntry is a dictionary with two keys:
1611 # - 'files': the files that are matched by this pattern
1612 # - 'rules': the per-file rules needed for this pattern
1613 # For example, if we expect OWNERS file to contain rules for *.mojom and
1614 # *_struct_traits*.*, Patterns might look like this:
1615 # {
1616 # '*.mojom': {
1617 # 'files': ...,
1618 # 'rules': [
1619 # 'per-file *.mojom=set noparent',
1620 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1621 # ],
1622 # },
1623 # '*_struct_traits*.*': {
1624 # 'files': ...,
1625 # 'rules': [
1626 # 'per-file *_struct_traits*.*=set noparent',
1627 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1628 # ],
1629 # },
1630 # }
1631 to_check = {}
1632
1633 # Iterate through the affected files to see what we actually need to check
1634 # for. We should only nag patch authors about per-file rules if a file in that
1635 # directory would match that pattern. If a directory only contains *.mojom
1636 # files and no *_messages*.h files, we should only nag about rules for
1637 # *.mojom files.
rockot51249332016-06-23 16:32:251638 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171639 for pattern in file_patterns:
1640 if input_api.fnmatch.fnmatch(
1641 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041642 skip = False
1643 for exclude in exclude_paths:
1644 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1645 skip = True
1646 break
1647 if skip:
1648 continue
dchenge07de812016-06-20 19:27:171649 owners_file = input_api.os_path.join(
1650 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1651 if owners_file not in to_check:
1652 to_check[owners_file] = {}
1653 if pattern not in to_check[owners_file]:
1654 to_check[owners_file][pattern] = {
1655 'files': [],
1656 'rules': [
1657 'per-file %s=set noparent' % pattern,
1658 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1659 ]
1660 }
1661 to_check[owners_file][pattern]['files'].append(f)
1662 break
1663
1664 # Now go through the OWNERS files we collected, filtering out rules that are
1665 # already present in that OWNERS file.
1666 for owners_file, patterns in to_check.iteritems():
1667 try:
1668 with file(owners_file) as f:
1669 lines = set(f.read().splitlines())
1670 for entry in patterns.itervalues():
1671 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1672 ]
1673 except IOError:
1674 # No OWNERS file, so all the rules are definitely missing.
1675 continue
1676
1677 # All the remaining lines weren't found in OWNERS files, so emit an error.
1678 errors = []
1679 for owners_file, patterns in to_check.iteritems():
1680 missing_lines = []
1681 files = []
1682 for pattern, entry in patterns.iteritems():
1683 missing_lines.extend(entry['rules'])
1684 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1685 if missing_lines:
1686 errors.append(
Daniel Cheng52111692017-06-14 08:00:591687 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171688 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1689
1690 results = []
1691 if errors:
vabrf5ce3bf92016-07-11 14:52:411692 if input_api.is_committing:
1693 output = output_api.PresubmitError
1694 else:
1695 output = output_api.PresubmitPromptWarning
1696 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591697 'Found OWNERS files that need to be updated for IPC security ' +
1698 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171699 long_text='\n\n'.join(errors)))
1700
1701 return results
1702
1703
jbriance9e12f162016-11-25 07:57:501704def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311705 """Checks that added or removed lines in non third party affected
1706 header files do not lead to new useless class or struct forward
1707 declaration.
jbriance9e12f162016-11-25 07:57:501708 """
1709 results = []
1710 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1711 input_api.re.MULTILINE)
1712 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1713 input_api.re.MULTILINE)
1714 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311715 if (f.LocalPath().startswith('third_party') and
1716 not f.LocalPath().startswith('third_party/WebKit') and
1717 not f.LocalPath().startswith('third_party\\WebKit')):
1718 continue
1719
jbriance9e12f162016-11-25 07:57:501720 if not f.LocalPath().endswith('.h'):
1721 continue
1722
1723 contents = input_api.ReadFile(f)
1724 fwd_decls = input_api.re.findall(class_pattern, contents)
1725 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1726
1727 useless_fwd_decls = []
1728 for decl in fwd_decls:
1729 count = sum(1 for _ in input_api.re.finditer(
1730 r'\b%s\b' % input_api.re.escape(decl), contents))
1731 if count == 1:
1732 useless_fwd_decls.append(decl)
1733
1734 if not useless_fwd_decls:
1735 continue
1736
1737 for line in f.GenerateScmDiff().splitlines():
1738 if (line.startswith('-') and not line.startswith('--') or
1739 line.startswith('+') and not line.startswith('++')):
1740 for decl in useless_fwd_decls:
1741 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1742 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241743 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501744 (f.LocalPath(), decl)))
1745 useless_fwd_decls.remove(decl)
1746
1747 return results
1748
1749
dskiba88634f4e2015-08-14 23:03:291750def _CheckAndroidToastUsage(input_api, output_api):
1751 """Checks that code uses org.chromium.ui.widget.Toast instead of
1752 android.widget.Toast (Chromium Toast doesn't force hardware
1753 acceleration on low-end devices, saving memory).
1754 """
1755 toast_import_pattern = input_api.re.compile(
1756 r'^import android\.widget\.Toast;$')
1757
1758 errors = []
1759
1760 sources = lambda affected_file: input_api.FilterSourceFile(
1761 affected_file,
1762 black_list=(_EXCLUDED_PATHS +
1763 _TEST_CODE_EXCLUDED_PATHS +
1764 input_api.DEFAULT_BLACK_LIST +
1765 (r'^chromecast[\\\/].*',
1766 r'^remoting[\\\/].*')),
1767 white_list=(r'.*\.java$',))
1768
1769 for f in input_api.AffectedSourceFiles(sources):
1770 for line_num, line in f.ChangedContents():
1771 if toast_import_pattern.search(line):
1772 errors.append("%s:%d" % (f.LocalPath(), line_num))
1773
1774 results = []
1775
1776 if errors:
1777 results.append(output_api.PresubmitError(
1778 'android.widget.Toast usage is detected. Android toasts use hardware'
1779 ' acceleration, and can be\ncostly on low-end devices. Please use'
1780 ' org.chromium.ui.widget.Toast instead.\n'
1781 'Contact [email protected] if you have any questions.',
1782 errors))
1783
1784 return results
1785
1786
dgnaa68d5e2015-06-10 10:08:221787def _CheckAndroidCrLogUsage(input_api, output_api):
1788 """Checks that new logs using org.chromium.base.Log:
1789 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511790 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221791 """
pkotwicza1dd0b002016-05-16 14:41:041792
torne89540622017-03-24 19:41:301793 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041794 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301795 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041796 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301797 # WebView license viewer code cannot depend on //base; used in stub APK.
1798 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1799 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041800 ]
1801
dgnaa68d5e2015-06-10 10:08:221802 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121803 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1804 class_in_base_pattern = input_api.re.compile(
1805 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1806 has_some_log_import_pattern = input_api.re.compile(
1807 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221808 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121809 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221810 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511811 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221812 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221813
Vincent Scheib16d7b272015-09-15 18:09:071814 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221815 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041816 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1817 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121818
dgnaa68d5e2015-06-10 10:08:221819 tag_decl_errors = []
1820 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121821 tag_errors = []
dgn38736db2015-09-18 19:20:511822 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121823 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221824
1825 for f in input_api.AffectedSourceFiles(sources):
1826 file_content = input_api.ReadFile(f)
1827 has_modified_logs = False
1828
1829 # Per line checks
dgn87d9fb62015-06-12 09:15:121830 if (cr_log_import_pattern.search(file_content) or
1831 (class_in_base_pattern.search(file_content) and
1832 not has_some_log_import_pattern.search(file_content))):
1833 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221834 for line_num, line in f.ChangedContents():
1835
1836 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121837 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221838 if match:
1839 has_modified_logs = True
1840
1841 # Make sure it uses "TAG"
1842 if not match.group('tag') == 'TAG':
1843 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121844 else:
1845 # Report non cr Log function calls in changed lines
1846 for line_num, line in f.ChangedContents():
1847 if log_call_pattern.search(line):
1848 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221849
1850 # Per file checks
1851 if has_modified_logs:
1852 # Make sure the tag is using the "cr" prefix and is not too long
1853 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511854 tag_name = match.group('name') if match else None
1855 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221856 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511857 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221858 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511859 elif '.' in tag_name:
1860 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221861
1862 results = []
1863 if tag_decl_errors:
1864 results.append(output_api.PresubmitPromptWarning(
1865 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511866 '"private static final String TAG = "<package tag>".\n'
1867 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221868 tag_decl_errors))
1869
1870 if tag_length_errors:
1871 results.append(output_api.PresubmitError(
1872 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511873 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221874 tag_length_errors))
1875
1876 if tag_errors:
1877 results.append(output_api.PresubmitPromptWarning(
1878 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1879 tag_errors))
1880
dgn87d9fb62015-06-12 09:15:121881 if util_log_errors:
dgn4401aa52015-04-29 16:26:171882 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121883 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1884 util_log_errors))
1885
dgn38736db2015-09-18 19:20:511886 if tag_with_dot_errors:
1887 results.append(output_api.PresubmitPromptWarning(
1888 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1889 tag_with_dot_errors))
1890
dgn4401aa52015-04-29 16:26:171891 return results
1892
1893
yolandyan45001472016-12-21 21:12:421894def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1895 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1896 deprecated_annotation_import_pattern = input_api.re.compile(
1897 r'^import android\.test\.suitebuilder\.annotation\..*;',
1898 input_api.re.MULTILINE)
1899 sources = lambda x: input_api.FilterSourceFile(
1900 x, white_list=(r'.*\.java$',), black_list=None)
1901 errors = []
1902 for f in input_api.AffectedFiles(sources):
1903 for line_num, line in f.ChangedContents():
1904 if deprecated_annotation_import_pattern.search(line):
1905 errors.append("%s:%d" % (f.LocalPath(), line_num))
1906
1907 results = []
1908 if errors:
1909 results.append(output_api.PresubmitError(
1910 'Annotations in android.test.suitebuilder.annotation have been'
1911 ' deprecated since API level 24. Please use android.support.test.filters'
1912 ' from //third_party/android_support_test_runner:runner_java instead.'
1913 ' Contact [email protected] if you have any questions.', errors))
1914 return results
1915
1916
agrieve7b6479d82015-10-07 14:24:221917def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1918 """Checks if MDPI assets are placed in a correct directory."""
1919 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1920 ('/res/drawable/' in f.LocalPath() or
1921 '/res/drawable-ldrtl/' in f.LocalPath()))
1922 errors = []
1923 for f in input_api.AffectedFiles(include_deletes=False,
1924 file_filter=file_filter):
1925 errors.append(' %s' % f.LocalPath())
1926
1927 results = []
1928 if errors:
1929 results.append(output_api.PresubmitError(
1930 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1931 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1932 '/res/drawable-ldrtl/.\n'
1933 'Contact [email protected] if you have questions.', errors))
1934 return results
1935
1936
agrievef32bcc72016-04-04 14:57:401937class PydepsChecker(object):
1938 def __init__(self, input_api, pydeps_files):
1939 self._file_cache = {}
1940 self._input_api = input_api
1941 self._pydeps_files = pydeps_files
1942
1943 def _LoadFile(self, path):
1944 """Returns the list of paths within a .pydeps file relative to //."""
1945 if path not in self._file_cache:
1946 with open(path) as f:
1947 self._file_cache[path] = f.read()
1948 return self._file_cache[path]
1949
1950 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1951 """Returns an interable of paths within the .pydep, relativized to //."""
1952 os_path = self._input_api.os_path
1953 pydeps_dir = os_path.dirname(pydeps_path)
1954 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1955 if not l.startswith('*'))
1956 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1957
1958 def _CreateFilesToPydepsMap(self):
1959 """Returns a map of local_path -> list_of_pydeps."""
1960 ret = {}
1961 for pydep_local_path in self._pydeps_files:
1962 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1963 ret.setdefault(path, []).append(pydep_local_path)
1964 return ret
1965
1966 def ComputeAffectedPydeps(self):
1967 """Returns an iterable of .pydeps files that might need regenerating."""
1968 affected_pydeps = set()
1969 file_to_pydeps_map = None
1970 for f in self._input_api.AffectedFiles(include_deletes=True):
1971 local_path = f.LocalPath()
1972 if local_path == 'DEPS':
1973 return self._pydeps_files
1974 elif local_path.endswith('.pydeps'):
1975 if local_path in self._pydeps_files:
1976 affected_pydeps.add(local_path)
1977 elif local_path.endswith('.py'):
1978 if file_to_pydeps_map is None:
1979 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1980 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1981 return affected_pydeps
1982
1983 def DetermineIfStale(self, pydeps_path):
1984 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411985 import difflib
agrievef32bcc72016-04-04 14:57:401986 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1987 cmd = old_pydeps_data[1][1:].strip()
1988 new_pydeps_data = self._input_api.subprocess.check_output(
1989 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411990 old_contents = old_pydeps_data[2:]
1991 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401992 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411993 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401994
1995
1996def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1997 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001998 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281999 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2000 # Mac, so skip it on other platforms.
2001 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002002 return []
agrievef32bcc72016-04-04 14:57:402003 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2004 is_android = input_api.os_path.exists('third_party/android_tools')
2005 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2006 results = []
2007 # First, check for new / deleted .pydeps.
2008 for f in input_api.AffectedFiles(include_deletes=True):
2009 if f.LocalPath().endswith('.pydeps'):
2010 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2011 results.append(output_api.PresubmitError(
2012 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2013 'remove %s' % f.LocalPath()))
2014 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2015 results.append(output_api.PresubmitError(
2016 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2017 'include %s' % f.LocalPath()))
2018
2019 if results:
2020 return results
2021
2022 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2023
2024 for pydep_path in checker.ComputeAffectedPydeps():
2025 try:
phajdan.jr0d9878552016-11-04 10:49:412026 result = checker.DetermineIfStale(pydep_path)
2027 if result:
2028 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402029 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412030 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2031 'To regenerate, run:\n\n %s' %
2032 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402033 except input_api.subprocess.CalledProcessError as error:
2034 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2035 long_text=error.output)]
2036
2037 return results
2038
2039
glidere61efad2015-02-18 17:39:432040def _CheckSingletonInHeaders(input_api, output_api):
2041 """Checks to make sure no header files have |Singleton<|."""
2042 def FileFilter(affected_file):
2043 # It's ok for base/memory/singleton.h to have |Singleton<|.
2044 black_list = (_EXCLUDED_PATHS +
2045 input_api.DEFAULT_BLACK_LIST +
2046 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2047 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2048
sergeyu34d21222015-09-16 00:11:442049 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432050 files = []
2051 for f in input_api.AffectedSourceFiles(FileFilter):
2052 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2053 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2054 contents = input_api.ReadFile(f)
2055 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242056 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432057 pattern.search(line)):
2058 files.append(f)
2059 break
2060
2061 if files:
yolandyandaabc6d2016-04-18 18:29:392062 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442063 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432064 'Please move them to an appropriate source file so that the ' +
2065 'template gets instantiated in a single compilation unit.',
2066 files) ]
2067 return []
2068
2069
[email protected]fd20b902014-05-09 02:14:532070_DEPRECATED_CSS = [
2071 # Values
2072 ( "-webkit-box", "flex" ),
2073 ( "-webkit-inline-box", "inline-flex" ),
2074 ( "-webkit-flex", "flex" ),
2075 ( "-webkit-inline-flex", "inline-flex" ),
2076 ( "-webkit-min-content", "min-content" ),
2077 ( "-webkit-max-content", "max-content" ),
2078
2079 # Properties
2080 ( "-webkit-background-clip", "background-clip" ),
2081 ( "-webkit-background-origin", "background-origin" ),
2082 ( "-webkit-background-size", "background-size" ),
2083 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442084 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532085
2086 # Functions
2087 ( "-webkit-gradient", "gradient" ),
2088 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2089 ( "-webkit-linear-gradient", "linear-gradient" ),
2090 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2091 ( "-webkit-radial-gradient", "radial-gradient" ),
2092 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2093]
2094
dbeam1ec68ac2016-12-15 05:22:242095def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532096 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252097 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342098 documentation and iOS CSS for dom distiller
2099 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252100 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532101 results = []
dbeam070cfe62014-10-22 06:44:022102 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252103 black_list = (_EXCLUDED_PATHS +
2104 _TEST_CODE_EXCLUDED_PATHS +
2105 input_api.DEFAULT_BLACK_LIST +
2106 (r"^chrome/common/extensions/docs",
2107 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342108 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:052109 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:442110 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252111 r"^native_client_sdk"))
2112 file_filter = lambda f: input_api.FilterSourceFile(
2113 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532114 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2115 for line_num, line in fpath.ChangedContents():
2116 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022117 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532118 results.append(output_api.PresubmitError(
2119 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2120 (fpath.LocalPath(), line_num, deprecated_value, value)))
2121 return results
2122
mohan.reddyf21db962014-10-16 12:26:472123
dbeam070cfe62014-10-22 06:44:022124_DEPRECATED_JS = [
2125 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2126 ( "__defineGetter__", "Object.defineProperty" ),
2127 ( "__defineSetter__", "Object.defineProperty" ),
2128]
2129
dbeam1ec68ac2016-12-15 05:22:242130def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022131 """Make sure that we don't use deprecated JS in Chrome code."""
2132 results = []
2133 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2134 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2135 input_api.DEFAULT_BLACK_LIST)
2136 file_filter = lambda f: input_api.FilterSourceFile(
2137 f, white_list=file_inclusion_pattern, black_list=black_list)
2138 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2139 for lnum, line in fpath.ChangedContents():
2140 for (deprecated, replacement) in _DEPRECATED_JS:
2141 if deprecated in line:
2142 results.append(output_api.PresubmitError(
2143 "%s:%d: Use of deprecated JS %s, use %s instead" %
2144 (fpath.LocalPath(), lnum, deprecated, replacement)))
2145 return results
2146
2147
dbeam1ec68ac2016-12-15 05:22:242148def _CheckForRiskyJsFeatures(input_api, output_api):
2149 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2150 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2151
2152 arrow_lines = []
2153 for f in input_api.AffectedFiles(file_filter=file_filter):
2154 for lnum, line in f.ChangedContents():
2155 if ' => ' in line:
2156 arrow_lines.append((f.LocalPath(), lnum))
2157
2158 if not arrow_lines:
2159 return []
2160
2161 return [output_api.PresubmitPromptWarning("""
2162Use of => operator detected in:
2163%s
2164Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2165https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2166""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2167
2168
rlanday6802cf632017-05-30 17:48:362169def _CheckForRelativeIncludes(input_api, output_api):
2170 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2171 import sys
2172 original_sys_path = sys.path
2173 try:
2174 sys.path = sys.path + [input_api.os_path.join(
2175 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2176 from cpp_checker import CppChecker
2177 finally:
2178 # Restore sys.path to what it was before.
2179 sys.path = original_sys_path
2180
2181 bad_files = {}
2182 for f in input_api.AffectedFiles(include_deletes=False):
2183 if (f.LocalPath().startswith('third_party') and
2184 not f.LocalPath().startswith('third_party/WebKit') and
2185 not f.LocalPath().startswith('third_party\\WebKit')):
2186 continue
2187
2188 if not CppChecker.IsCppFile(f.LocalPath()):
2189 continue
2190
2191 relative_includes = [line for line_num, line in f.ChangedContents()
2192 if "#include" in line and "../" in line]
2193 if not relative_includes:
2194 continue
2195 bad_files[f.LocalPath()] = relative_includes
2196
2197 if not bad_files:
2198 return []
2199
2200 error_descriptions = []
2201 for file_path, bad_lines in bad_files.iteritems():
2202 error_description = file_path
2203 for line in bad_lines:
2204 error_description += '\n ' + line
2205 error_descriptions.append(error_description)
2206
2207 results = []
2208 results.append(output_api.PresubmitError(
2209 'You added one or more relative #include paths (including "../").\n'
2210 'These shouldn\'t be used because they can be used to include headers\n'
2211 'from code that\'s not correctly specified as a dependency in the\n'
2212 'relevant BUILD.gn file(s).',
2213 error_descriptions))
2214
2215 return results
2216
dgnaa68d5e2015-06-10 10:08:222217def _AndroidSpecificOnUploadChecks(input_api, output_api):
2218 """Groups checks that target android code."""
2219 results = []
dgnaa68d5e2015-06-10 10:08:222220 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222221 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292222 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422223 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222224 return results
2225
2226
[email protected]22c9bd72011-03-27 16:47:392227def _CommonChecks(input_api, output_api):
2228 """Checks common to both upload and commit."""
2229 results = []
2230 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382231 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542232 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582233 results.extend(
2234 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192235 results.extend(
[email protected]760deea2013-12-10 19:33:492236 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542237 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182238 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522239 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222240 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442241 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592242 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062243 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122244 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182245 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222246 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302247 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492248 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272249 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032250 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492251 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442252 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272253 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542254 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442255 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392256 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552257 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042258 results.extend(
2259 input_api.canned_checks.CheckChangeHasNoTabs(
2260 input_api,
2261 output_api,
2262 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402263 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162264 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592265 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082266 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242267 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2268 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472269 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042270 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232271 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432272 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402273 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152274 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172275 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502276 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242277 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362278 results.extend(_CheckForRelativeIncludes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242279
2280 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2281 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2282 input_api, output_api,
2283 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382284 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392285 return results
[email protected]1f7b4172010-01-28 01:17:342286
[email protected]b337cb5b2011-01-23 21:24:052287
[email protected]b8079ae4a2012-12-05 19:56:492288def _CheckPatchFiles(input_api, output_api):
2289 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2290 if f.LocalPath().endswith(('.orig', '.rej'))]
2291 if problems:
2292 return [output_api.PresubmitError(
2293 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032294 else:
2295 return []
[email protected]b8079ae4a2012-12-05 19:56:492296
2297
[email protected]b00342e7f2013-03-26 16:21:542298def _DidYouMeanOSMacro(bad_macro):
2299 try:
2300 return {'A': 'OS_ANDROID',
2301 'B': 'OS_BSD',
2302 'C': 'OS_CHROMEOS',
2303 'F': 'OS_FREEBSD',
2304 'L': 'OS_LINUX',
2305 'M': 'OS_MACOSX',
2306 'N': 'OS_NACL',
2307 'O': 'OS_OPENBSD',
2308 'P': 'OS_POSIX',
2309 'S': 'OS_SOLARIS',
2310 'W': 'OS_WIN'}[bad_macro[3].upper()]
2311 except KeyError:
2312 return ''
2313
2314
2315def _CheckForInvalidOSMacrosInFile(input_api, f):
2316 """Check for sensible looking, totally invalid OS macros."""
2317 preprocessor_statement = input_api.re.compile(r'^\s*#')
2318 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2319 results = []
2320 for lnum, line in f.ChangedContents():
2321 if preprocessor_statement.search(line):
2322 for match in os_macro.finditer(line):
2323 if not match.group(1) in _VALID_OS_MACROS:
2324 good = _DidYouMeanOSMacro(match.group(1))
2325 did_you_mean = ' (did you mean %s?)' % good if good else ''
2326 results.append(' %s:%d %s%s' % (f.LocalPath(),
2327 lnum,
2328 match.group(1),
2329 did_you_mean))
2330 return results
2331
2332
2333def _CheckForInvalidOSMacros(input_api, output_api):
2334 """Check all affected files for invalid OS macros."""
2335 bad_macros = []
2336 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472337 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542338 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2339
2340 if not bad_macros:
2341 return []
2342
2343 return [output_api.PresubmitError(
2344 'Possibly invalid OS macro[s] found. Please fix your code\n'
2345 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2346
lliabraa35bab3932014-10-01 12:16:442347
2348def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2349 """Check all affected files for invalid "if defined" macros."""
2350 ALWAYS_DEFINED_MACROS = (
2351 "TARGET_CPU_PPC",
2352 "TARGET_CPU_PPC64",
2353 "TARGET_CPU_68K",
2354 "TARGET_CPU_X86",
2355 "TARGET_CPU_ARM",
2356 "TARGET_CPU_MIPS",
2357 "TARGET_CPU_SPARC",
2358 "TARGET_CPU_ALPHA",
2359 "TARGET_IPHONE_SIMULATOR",
2360 "TARGET_OS_EMBEDDED",
2361 "TARGET_OS_IPHONE",
2362 "TARGET_OS_MAC",
2363 "TARGET_OS_UNIX",
2364 "TARGET_OS_WIN32",
2365 )
2366 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2367 results = []
2368 for lnum, line in f.ChangedContents():
2369 for match in ifdef_macro.finditer(line):
2370 if match.group(1) in ALWAYS_DEFINED_MACROS:
2371 always_defined = ' %s is always defined. ' % match.group(1)
2372 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2373 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2374 lnum,
2375 always_defined,
2376 did_you_mean))
2377 return results
2378
2379
2380def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2381 """Check all affected files for invalid "if defined" macros."""
2382 bad_macros = []
2383 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212384 if f.LocalPath().startswith('third_party/sqlite/'):
2385 continue
lliabraa35bab3932014-10-01 12:16:442386 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2387 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2388
2389 if not bad_macros:
2390 return []
2391
2392 return [output_api.PresubmitError(
2393 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2394 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2395 bad_macros)]
2396
2397
mlamouria82272622014-09-16 18:45:042398def _CheckForIPCRules(input_api, output_api):
2399 """Check for same IPC rules described in
2400 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2401 """
2402 base_pattern = r'IPC_ENUM_TRAITS\('
2403 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2404 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2405
2406 problems = []
2407 for f in input_api.AffectedSourceFiles(None):
2408 local_path = f.LocalPath()
2409 if not local_path.endswith('.h'):
2410 continue
2411 for line_number, line in f.ChangedContents():
2412 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2413 problems.append(
2414 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2415
2416 if problems:
2417 return [output_api.PresubmitPromptWarning(
2418 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2419 else:
2420 return []
2421
[email protected]b00342e7f2013-03-26 16:21:542422
mostynbb639aca52015-01-07 20:31:232423def _CheckForWindowsLineEndings(input_api, output_api):
2424 """Check source code and known ascii text files for Windows style line
2425 endings.
2426 """
earthdok1b5e0ee2015-03-10 15:19:102427 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232428
2429 file_inclusion_pattern = (
2430 known_text_files,
2431 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2432 )
2433
2434 filter = lambda f: input_api.FilterSourceFile(
2435 f, white_list=file_inclusion_pattern, black_list=None)
2436 files = [f.LocalPath() for f in
2437 input_api.AffectedSourceFiles(filter)]
2438
2439 problems = []
2440
2441 for file in files:
2442 fp = open(file, 'r')
2443 for line in fp:
2444 if line.endswith('\r\n'):
2445 problems.append(file)
2446 break
2447 fp.close()
2448
2449 if problems:
2450 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2451 'these files to contain Windows style line endings?\n' +
2452 '\n'.join(problems))]
2453
2454 return []
2455
2456
pastarmovj89f7ee12016-09-20 14:58:132457def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2458 lint_filters=None, verbose_level=None):
2459 """Checks that all source files use SYSLOG properly."""
2460 syslog_files = []
2461 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562462 for line_number, line in f.ChangedContents():
2463 if 'SYSLOG' in line:
2464 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2465
pastarmovj89f7ee12016-09-20 14:58:132466 if syslog_files:
2467 return [output_api.PresubmitPromptWarning(
2468 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2469 ' calls.\nFiles to check:\n', items=syslog_files)]
2470 return []
2471
2472
[email protected]1f7b4172010-01-28 01:17:342473def CheckChangeOnUpload(input_api, output_api):
2474 results = []
2475 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472476 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282477 results.extend(
jam93a6ee792017-02-08 23:59:222478 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192479 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222480 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132481 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162482 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542483 return results
[email protected]ca8d19842009-02-19 16:33:122484
2485
[email protected]1bfb8322014-04-23 01:02:412486def GetTryServerMasterForBot(bot):
2487 """Returns the Try Server master for the given bot.
2488
[email protected]0bb112362014-07-26 04:38:322489 It tries to guess the master from the bot name, but may still fail
2490 and return None. There is no longer a default master.
2491 """
2492 # Potentially ambiguous bot names are listed explicitly.
2493 master_map = {
tandriie5587792016-07-14 00:34:502494 'chromium_presubmit': 'master.tryserver.chromium.linux',
2495 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412496 }
[email protected]0bb112362014-07-26 04:38:322497 master = master_map.get(bot)
2498 if not master:
wnwen4fbaab82016-05-25 12:54:362499 if 'android' in bot:
tandriie5587792016-07-14 00:34:502500 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362501 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502502 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322503 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502504 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322505 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502506 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322507 return master
[email protected]1bfb8322014-04-23 01:02:412508
2509
Paweł Hajdan, Jr55083782014-12-19 20:32:562510def GetDefaultTryConfigs(bots):
2511 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012512 """
2513
Paweł Hajdan, Jr55083782014-12-19 20:32:562514 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412515
2516 # Build up the mapping from tryserver master to bot/test.
2517 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562518 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412519 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2520 return out
[email protected]38c6a512013-12-18 23:48:012521
2522
[email protected]ca8d19842009-02-19 16:33:122523def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542524 results = []
[email protected]1f7b4172010-01-28 01:17:342525 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542526 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272527 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342528 input_api,
2529 output_api,
[email protected]2fdd1f362013-01-16 03:56:032530 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272531
jam93a6ee792017-02-08 23:59:222532 results.extend(
2533 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542534 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2535 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412536 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2537 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542538 return results