blob: b076e42bbfb55b1cced7213b2485bb839d666772 [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(
1687 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1688 (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(
dchenge07de812016-06-20 19:27:171697 'Found changes to IPC files without a security OWNER!',
1698 long_text='\n\n'.join(errors)))
1699
1700 return results
1701
1702
jbriance9e12f162016-11-25 07:57:501703def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311704 """Checks that added or removed lines in non third party affected
1705 header files do not lead to new useless class or struct forward
1706 declaration.
jbriance9e12f162016-11-25 07:57:501707 """
1708 results = []
1709 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1710 input_api.re.MULTILINE)
1711 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1712 input_api.re.MULTILINE)
1713 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311714 if (f.LocalPath().startswith('third_party') and
1715 not f.LocalPath().startswith('third_party/WebKit') and
1716 not f.LocalPath().startswith('third_party\\WebKit')):
1717 continue
1718
jbriance9e12f162016-11-25 07:57:501719 if not f.LocalPath().endswith('.h'):
1720 continue
1721
1722 contents = input_api.ReadFile(f)
1723 fwd_decls = input_api.re.findall(class_pattern, contents)
1724 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1725
1726 useless_fwd_decls = []
1727 for decl in fwd_decls:
1728 count = sum(1 for _ in input_api.re.finditer(
1729 r'\b%s\b' % input_api.re.escape(decl), contents))
1730 if count == 1:
1731 useless_fwd_decls.append(decl)
1732
1733 if not useless_fwd_decls:
1734 continue
1735
1736 for line in f.GenerateScmDiff().splitlines():
1737 if (line.startswith('-') and not line.startswith('--') or
1738 line.startswith('+') and not line.startswith('++')):
1739 for decl in useless_fwd_decls:
1740 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1741 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241742 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501743 (f.LocalPath(), decl)))
1744 useless_fwd_decls.remove(decl)
1745
1746 return results
1747
1748
dskiba88634f4e2015-08-14 23:03:291749def _CheckAndroidToastUsage(input_api, output_api):
1750 """Checks that code uses org.chromium.ui.widget.Toast instead of
1751 android.widget.Toast (Chromium Toast doesn't force hardware
1752 acceleration on low-end devices, saving memory).
1753 """
1754 toast_import_pattern = input_api.re.compile(
1755 r'^import android\.widget\.Toast;$')
1756
1757 errors = []
1758
1759 sources = lambda affected_file: input_api.FilterSourceFile(
1760 affected_file,
1761 black_list=(_EXCLUDED_PATHS +
1762 _TEST_CODE_EXCLUDED_PATHS +
1763 input_api.DEFAULT_BLACK_LIST +
1764 (r'^chromecast[\\\/].*',
1765 r'^remoting[\\\/].*')),
1766 white_list=(r'.*\.java$',))
1767
1768 for f in input_api.AffectedSourceFiles(sources):
1769 for line_num, line in f.ChangedContents():
1770 if toast_import_pattern.search(line):
1771 errors.append("%s:%d" % (f.LocalPath(), line_num))
1772
1773 results = []
1774
1775 if errors:
1776 results.append(output_api.PresubmitError(
1777 'android.widget.Toast usage is detected. Android toasts use hardware'
1778 ' acceleration, and can be\ncostly on low-end devices. Please use'
1779 ' org.chromium.ui.widget.Toast instead.\n'
1780 'Contact [email protected] if you have any questions.',
1781 errors))
1782
1783 return results
1784
1785
dgnaa68d5e2015-06-10 10:08:221786def _CheckAndroidCrLogUsage(input_api, output_api):
1787 """Checks that new logs using org.chromium.base.Log:
1788 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511789 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221790 """
pkotwicza1dd0b002016-05-16 14:41:041791
torne89540622017-03-24 19:41:301792 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041793 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301794 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041795 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301796 # WebView license viewer code cannot depend on //base; used in stub APK.
1797 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1798 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041799 ]
1800
dgnaa68d5e2015-06-10 10:08:221801 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121802 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1803 class_in_base_pattern = input_api.re.compile(
1804 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1805 has_some_log_import_pattern = input_api.re.compile(
1806 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221807 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121808 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221809 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511810 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221811 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221812
Vincent Scheib16d7b272015-09-15 18:09:071813 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221814 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041815 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1816 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121817
dgnaa68d5e2015-06-10 10:08:221818 tag_decl_errors = []
1819 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121820 tag_errors = []
dgn38736db2015-09-18 19:20:511821 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121822 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221823
1824 for f in input_api.AffectedSourceFiles(sources):
1825 file_content = input_api.ReadFile(f)
1826 has_modified_logs = False
1827
1828 # Per line checks
dgn87d9fb62015-06-12 09:15:121829 if (cr_log_import_pattern.search(file_content) or
1830 (class_in_base_pattern.search(file_content) and
1831 not has_some_log_import_pattern.search(file_content))):
1832 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221833 for line_num, line in f.ChangedContents():
1834
1835 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121836 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221837 if match:
1838 has_modified_logs = True
1839
1840 # Make sure it uses "TAG"
1841 if not match.group('tag') == 'TAG':
1842 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121843 else:
1844 # Report non cr Log function calls in changed lines
1845 for line_num, line in f.ChangedContents():
1846 if log_call_pattern.search(line):
1847 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221848
1849 # Per file checks
1850 if has_modified_logs:
1851 # Make sure the tag is using the "cr" prefix and is not too long
1852 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511853 tag_name = match.group('name') if match else None
1854 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221855 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511856 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221857 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511858 elif '.' in tag_name:
1859 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221860
1861 results = []
1862 if tag_decl_errors:
1863 results.append(output_api.PresubmitPromptWarning(
1864 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511865 '"private static final String TAG = "<package tag>".\n'
1866 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221867 tag_decl_errors))
1868
1869 if tag_length_errors:
1870 results.append(output_api.PresubmitError(
1871 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511872 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221873 tag_length_errors))
1874
1875 if tag_errors:
1876 results.append(output_api.PresubmitPromptWarning(
1877 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1878 tag_errors))
1879
dgn87d9fb62015-06-12 09:15:121880 if util_log_errors:
dgn4401aa52015-04-29 16:26:171881 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121882 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1883 util_log_errors))
1884
dgn38736db2015-09-18 19:20:511885 if tag_with_dot_errors:
1886 results.append(output_api.PresubmitPromptWarning(
1887 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1888 tag_with_dot_errors))
1889
dgn4401aa52015-04-29 16:26:171890 return results
1891
1892
yolandyan45001472016-12-21 21:12:421893def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1894 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1895 deprecated_annotation_import_pattern = input_api.re.compile(
1896 r'^import android\.test\.suitebuilder\.annotation\..*;',
1897 input_api.re.MULTILINE)
1898 sources = lambda x: input_api.FilterSourceFile(
1899 x, white_list=(r'.*\.java$',), black_list=None)
1900 errors = []
1901 for f in input_api.AffectedFiles(sources):
1902 for line_num, line in f.ChangedContents():
1903 if deprecated_annotation_import_pattern.search(line):
1904 errors.append("%s:%d" % (f.LocalPath(), line_num))
1905
1906 results = []
1907 if errors:
1908 results.append(output_api.PresubmitError(
1909 'Annotations in android.test.suitebuilder.annotation have been'
1910 ' deprecated since API level 24. Please use android.support.test.filters'
1911 ' from //third_party/android_support_test_runner:runner_java instead.'
1912 ' Contact [email protected] if you have any questions.', errors))
1913 return results
1914
1915
agrieve7b6479d82015-10-07 14:24:221916def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1917 """Checks if MDPI assets are placed in a correct directory."""
1918 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1919 ('/res/drawable/' in f.LocalPath() or
1920 '/res/drawable-ldrtl/' in f.LocalPath()))
1921 errors = []
1922 for f in input_api.AffectedFiles(include_deletes=False,
1923 file_filter=file_filter):
1924 errors.append(' %s' % f.LocalPath())
1925
1926 results = []
1927 if errors:
1928 results.append(output_api.PresubmitError(
1929 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1930 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1931 '/res/drawable-ldrtl/.\n'
1932 'Contact [email protected] if you have questions.', errors))
1933 return results
1934
1935
agrievef32bcc72016-04-04 14:57:401936class PydepsChecker(object):
1937 def __init__(self, input_api, pydeps_files):
1938 self._file_cache = {}
1939 self._input_api = input_api
1940 self._pydeps_files = pydeps_files
1941
1942 def _LoadFile(self, path):
1943 """Returns the list of paths within a .pydeps file relative to //."""
1944 if path not in self._file_cache:
1945 with open(path) as f:
1946 self._file_cache[path] = f.read()
1947 return self._file_cache[path]
1948
1949 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1950 """Returns an interable of paths within the .pydep, relativized to //."""
1951 os_path = self._input_api.os_path
1952 pydeps_dir = os_path.dirname(pydeps_path)
1953 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1954 if not l.startswith('*'))
1955 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1956
1957 def _CreateFilesToPydepsMap(self):
1958 """Returns a map of local_path -> list_of_pydeps."""
1959 ret = {}
1960 for pydep_local_path in self._pydeps_files:
1961 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1962 ret.setdefault(path, []).append(pydep_local_path)
1963 return ret
1964
1965 def ComputeAffectedPydeps(self):
1966 """Returns an iterable of .pydeps files that might need regenerating."""
1967 affected_pydeps = set()
1968 file_to_pydeps_map = None
1969 for f in self._input_api.AffectedFiles(include_deletes=True):
1970 local_path = f.LocalPath()
1971 if local_path == 'DEPS':
1972 return self._pydeps_files
1973 elif local_path.endswith('.pydeps'):
1974 if local_path in self._pydeps_files:
1975 affected_pydeps.add(local_path)
1976 elif local_path.endswith('.py'):
1977 if file_to_pydeps_map is None:
1978 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1979 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1980 return affected_pydeps
1981
1982 def DetermineIfStale(self, pydeps_path):
1983 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411984 import difflib
agrievef32bcc72016-04-04 14:57:401985 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1986 cmd = old_pydeps_data[1][1:].strip()
1987 new_pydeps_data = self._input_api.subprocess.check_output(
1988 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411989 old_contents = old_pydeps_data[2:]
1990 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401991 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411992 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401993
1994
1995def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1996 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001997 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281998 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1999 # Mac, so skip it on other platforms.
2000 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002001 return []
agrievef32bcc72016-04-04 14:57:402002 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2003 is_android = input_api.os_path.exists('third_party/android_tools')
2004 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2005 results = []
2006 # First, check for new / deleted .pydeps.
2007 for f in input_api.AffectedFiles(include_deletes=True):
2008 if f.LocalPath().endswith('.pydeps'):
2009 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2010 results.append(output_api.PresubmitError(
2011 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2012 'remove %s' % f.LocalPath()))
2013 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2014 results.append(output_api.PresubmitError(
2015 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2016 'include %s' % f.LocalPath()))
2017
2018 if results:
2019 return results
2020
2021 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2022
2023 for pydep_path in checker.ComputeAffectedPydeps():
2024 try:
phajdan.jr0d9878552016-11-04 10:49:412025 result = checker.DetermineIfStale(pydep_path)
2026 if result:
2027 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402028 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412029 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2030 'To regenerate, run:\n\n %s' %
2031 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402032 except input_api.subprocess.CalledProcessError as error:
2033 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2034 long_text=error.output)]
2035
2036 return results
2037
2038
glidere61efad2015-02-18 17:39:432039def _CheckSingletonInHeaders(input_api, output_api):
2040 """Checks to make sure no header files have |Singleton<|."""
2041 def FileFilter(affected_file):
2042 # It's ok for base/memory/singleton.h to have |Singleton<|.
2043 black_list = (_EXCLUDED_PATHS +
2044 input_api.DEFAULT_BLACK_LIST +
2045 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2046 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2047
sergeyu34d21222015-09-16 00:11:442048 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432049 files = []
2050 for f in input_api.AffectedSourceFiles(FileFilter):
2051 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2052 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2053 contents = input_api.ReadFile(f)
2054 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242055 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432056 pattern.search(line)):
2057 files.append(f)
2058 break
2059
2060 if files:
yolandyandaabc6d2016-04-18 18:29:392061 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442062 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432063 'Please move them to an appropriate source file so that the ' +
2064 'template gets instantiated in a single compilation unit.',
2065 files) ]
2066 return []
2067
2068
[email protected]fd20b902014-05-09 02:14:532069_DEPRECATED_CSS = [
2070 # Values
2071 ( "-webkit-box", "flex" ),
2072 ( "-webkit-inline-box", "inline-flex" ),
2073 ( "-webkit-flex", "flex" ),
2074 ( "-webkit-inline-flex", "inline-flex" ),
2075 ( "-webkit-min-content", "min-content" ),
2076 ( "-webkit-max-content", "max-content" ),
2077
2078 # Properties
2079 ( "-webkit-background-clip", "background-clip" ),
2080 ( "-webkit-background-origin", "background-origin" ),
2081 ( "-webkit-background-size", "background-size" ),
2082 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442083 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532084
2085 # Functions
2086 ( "-webkit-gradient", "gradient" ),
2087 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2088 ( "-webkit-linear-gradient", "linear-gradient" ),
2089 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2090 ( "-webkit-radial-gradient", "radial-gradient" ),
2091 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2092]
2093
dbeam1ec68ac2016-12-15 05:22:242094def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532095 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252096 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342097 documentation and iOS CSS for dom distiller
2098 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252099 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532100 results = []
dbeam070cfe62014-10-22 06:44:022101 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252102 black_list = (_EXCLUDED_PATHS +
2103 _TEST_CODE_EXCLUDED_PATHS +
2104 input_api.DEFAULT_BLACK_LIST +
2105 (r"^chrome/common/extensions/docs",
2106 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342107 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:052108 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:442109 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252110 r"^native_client_sdk"))
2111 file_filter = lambda f: input_api.FilterSourceFile(
2112 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532113 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2114 for line_num, line in fpath.ChangedContents():
2115 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022116 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532117 results.append(output_api.PresubmitError(
2118 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2119 (fpath.LocalPath(), line_num, deprecated_value, value)))
2120 return results
2121
mohan.reddyf21db962014-10-16 12:26:472122
dbeam070cfe62014-10-22 06:44:022123_DEPRECATED_JS = [
2124 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2125 ( "__defineGetter__", "Object.defineProperty" ),
2126 ( "__defineSetter__", "Object.defineProperty" ),
2127]
2128
dbeam1ec68ac2016-12-15 05:22:242129def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022130 """Make sure that we don't use deprecated JS in Chrome code."""
2131 results = []
2132 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2133 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2134 input_api.DEFAULT_BLACK_LIST)
2135 file_filter = lambda f: input_api.FilterSourceFile(
2136 f, white_list=file_inclusion_pattern, black_list=black_list)
2137 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2138 for lnum, line in fpath.ChangedContents():
2139 for (deprecated, replacement) in _DEPRECATED_JS:
2140 if deprecated in line:
2141 results.append(output_api.PresubmitError(
2142 "%s:%d: Use of deprecated JS %s, use %s instead" %
2143 (fpath.LocalPath(), lnum, deprecated, replacement)))
2144 return results
2145
2146
dbeam1ec68ac2016-12-15 05:22:242147def _CheckForRiskyJsFeatures(input_api, output_api):
2148 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2149 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2150
2151 arrow_lines = []
2152 for f in input_api.AffectedFiles(file_filter=file_filter):
2153 for lnum, line in f.ChangedContents():
2154 if ' => ' in line:
2155 arrow_lines.append((f.LocalPath(), lnum))
2156
2157 if not arrow_lines:
2158 return []
2159
2160 return [output_api.PresubmitPromptWarning("""
2161Use of => operator detected in:
2162%s
2163Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2164https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2165""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2166
2167
rlanday6802cf632017-05-30 17:48:362168def _CheckForRelativeIncludes(input_api, output_api):
2169 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2170 import sys
2171 original_sys_path = sys.path
2172 try:
2173 sys.path = sys.path + [input_api.os_path.join(
2174 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2175 from cpp_checker import CppChecker
2176 finally:
2177 # Restore sys.path to what it was before.
2178 sys.path = original_sys_path
2179
2180 bad_files = {}
2181 for f in input_api.AffectedFiles(include_deletes=False):
2182 if (f.LocalPath().startswith('third_party') and
2183 not f.LocalPath().startswith('third_party/WebKit') and
2184 not f.LocalPath().startswith('third_party\\WebKit')):
2185 continue
2186
2187 if not CppChecker.IsCppFile(f.LocalPath()):
2188 continue
2189
2190 relative_includes = [line for line_num, line in f.ChangedContents()
2191 if "#include" in line and "../" in line]
2192 if not relative_includes:
2193 continue
2194 bad_files[f.LocalPath()] = relative_includes
2195
2196 if not bad_files:
2197 return []
2198
2199 error_descriptions = []
2200 for file_path, bad_lines in bad_files.iteritems():
2201 error_description = file_path
2202 for line in bad_lines:
2203 error_description += '\n ' + line
2204 error_descriptions.append(error_description)
2205
2206 results = []
2207 results.append(output_api.PresubmitError(
2208 'You added one or more relative #include paths (including "../").\n'
2209 'These shouldn\'t be used because they can be used to include headers\n'
2210 'from code that\'s not correctly specified as a dependency in the\n'
2211 'relevant BUILD.gn file(s).',
2212 error_descriptions))
2213
2214 return results
2215
dgnaa68d5e2015-06-10 10:08:222216def _AndroidSpecificOnUploadChecks(input_api, output_api):
2217 """Groups checks that target android code."""
2218 results = []
dgnaa68d5e2015-06-10 10:08:222219 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222220 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292221 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422222 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222223 return results
2224
2225
[email protected]22c9bd72011-03-27 16:47:392226def _CommonChecks(input_api, output_api):
2227 """Checks common to both upload and commit."""
2228 results = []
2229 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382230 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542231 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582232 results.extend(
2233 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192234 results.extend(
[email protected]760deea2013-12-10 19:33:492235 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542236 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182237 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522238 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222239 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442240 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592241 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062242 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122243 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182244 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222245 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302246 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492247 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272248 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032249 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492250 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442251 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272252 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542253 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442254 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392255 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552256 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042257 results.extend(
2258 input_api.canned_checks.CheckChangeHasNoTabs(
2259 input_api,
2260 output_api,
2261 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402262 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162263 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592264 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082265 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242266 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2267 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472268 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042269 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232270 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432271 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402272 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152273 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172274 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502275 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242276 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362277 results.extend(_CheckForRelativeIncludes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242278
2279 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2280 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2281 input_api, output_api,
2282 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382283 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392284 return results
[email protected]1f7b4172010-01-28 01:17:342285
[email protected]b337cb5b2011-01-23 21:24:052286
[email protected]b8079ae4a2012-12-05 19:56:492287def _CheckPatchFiles(input_api, output_api):
2288 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2289 if f.LocalPath().endswith(('.orig', '.rej'))]
2290 if problems:
2291 return [output_api.PresubmitError(
2292 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032293 else:
2294 return []
[email protected]b8079ae4a2012-12-05 19:56:492295
2296
[email protected]b00342e7f2013-03-26 16:21:542297def _DidYouMeanOSMacro(bad_macro):
2298 try:
2299 return {'A': 'OS_ANDROID',
2300 'B': 'OS_BSD',
2301 'C': 'OS_CHROMEOS',
2302 'F': 'OS_FREEBSD',
2303 'L': 'OS_LINUX',
2304 'M': 'OS_MACOSX',
2305 'N': 'OS_NACL',
2306 'O': 'OS_OPENBSD',
2307 'P': 'OS_POSIX',
2308 'S': 'OS_SOLARIS',
2309 'W': 'OS_WIN'}[bad_macro[3].upper()]
2310 except KeyError:
2311 return ''
2312
2313
2314def _CheckForInvalidOSMacrosInFile(input_api, f):
2315 """Check for sensible looking, totally invalid OS macros."""
2316 preprocessor_statement = input_api.re.compile(r'^\s*#')
2317 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2318 results = []
2319 for lnum, line in f.ChangedContents():
2320 if preprocessor_statement.search(line):
2321 for match in os_macro.finditer(line):
2322 if not match.group(1) in _VALID_OS_MACROS:
2323 good = _DidYouMeanOSMacro(match.group(1))
2324 did_you_mean = ' (did you mean %s?)' % good if good else ''
2325 results.append(' %s:%d %s%s' % (f.LocalPath(),
2326 lnum,
2327 match.group(1),
2328 did_you_mean))
2329 return results
2330
2331
2332def _CheckForInvalidOSMacros(input_api, output_api):
2333 """Check all affected files for invalid OS macros."""
2334 bad_macros = []
2335 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472336 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542337 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2338
2339 if not bad_macros:
2340 return []
2341
2342 return [output_api.PresubmitError(
2343 'Possibly invalid OS macro[s] found. Please fix your code\n'
2344 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2345
lliabraa35bab3932014-10-01 12:16:442346
2347def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2348 """Check all affected files for invalid "if defined" macros."""
2349 ALWAYS_DEFINED_MACROS = (
2350 "TARGET_CPU_PPC",
2351 "TARGET_CPU_PPC64",
2352 "TARGET_CPU_68K",
2353 "TARGET_CPU_X86",
2354 "TARGET_CPU_ARM",
2355 "TARGET_CPU_MIPS",
2356 "TARGET_CPU_SPARC",
2357 "TARGET_CPU_ALPHA",
2358 "TARGET_IPHONE_SIMULATOR",
2359 "TARGET_OS_EMBEDDED",
2360 "TARGET_OS_IPHONE",
2361 "TARGET_OS_MAC",
2362 "TARGET_OS_UNIX",
2363 "TARGET_OS_WIN32",
2364 )
2365 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2366 results = []
2367 for lnum, line in f.ChangedContents():
2368 for match in ifdef_macro.finditer(line):
2369 if match.group(1) in ALWAYS_DEFINED_MACROS:
2370 always_defined = ' %s is always defined. ' % match.group(1)
2371 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2372 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2373 lnum,
2374 always_defined,
2375 did_you_mean))
2376 return results
2377
2378
2379def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2380 """Check all affected files for invalid "if defined" macros."""
2381 bad_macros = []
2382 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212383 if f.LocalPath().startswith('third_party/sqlite/'):
2384 continue
lliabraa35bab3932014-10-01 12:16:442385 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2386 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2387
2388 if not bad_macros:
2389 return []
2390
2391 return [output_api.PresubmitError(
2392 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2393 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2394 bad_macros)]
2395
2396
mlamouria82272622014-09-16 18:45:042397def _CheckForIPCRules(input_api, output_api):
2398 """Check for same IPC rules described in
2399 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2400 """
2401 base_pattern = r'IPC_ENUM_TRAITS\('
2402 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2403 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2404
2405 problems = []
2406 for f in input_api.AffectedSourceFiles(None):
2407 local_path = f.LocalPath()
2408 if not local_path.endswith('.h'):
2409 continue
2410 for line_number, line in f.ChangedContents():
2411 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2412 problems.append(
2413 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2414
2415 if problems:
2416 return [output_api.PresubmitPromptWarning(
2417 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2418 else:
2419 return []
2420
[email protected]b00342e7f2013-03-26 16:21:542421
mostynbb639aca52015-01-07 20:31:232422def _CheckForWindowsLineEndings(input_api, output_api):
2423 """Check source code and known ascii text files for Windows style line
2424 endings.
2425 """
earthdok1b5e0ee2015-03-10 15:19:102426 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232427
2428 file_inclusion_pattern = (
2429 known_text_files,
2430 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2431 )
2432
2433 filter = lambda f: input_api.FilterSourceFile(
2434 f, white_list=file_inclusion_pattern, black_list=None)
2435 files = [f.LocalPath() for f in
2436 input_api.AffectedSourceFiles(filter)]
2437
2438 problems = []
2439
2440 for file in files:
2441 fp = open(file, 'r')
2442 for line in fp:
2443 if line.endswith('\r\n'):
2444 problems.append(file)
2445 break
2446 fp.close()
2447
2448 if problems:
2449 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2450 'these files to contain Windows style line endings?\n' +
2451 '\n'.join(problems))]
2452
2453 return []
2454
2455
pastarmovj89f7ee12016-09-20 14:58:132456def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2457 lint_filters=None, verbose_level=None):
2458 """Checks that all source files use SYSLOG properly."""
2459 syslog_files = []
2460 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562461 for line_number, line in f.ChangedContents():
2462 if 'SYSLOG' in line:
2463 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2464
pastarmovj89f7ee12016-09-20 14:58:132465 if syslog_files:
2466 return [output_api.PresubmitPromptWarning(
2467 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2468 ' calls.\nFiles to check:\n', items=syslog_files)]
2469 return []
2470
2471
[email protected]1f7b4172010-01-28 01:17:342472def CheckChangeOnUpload(input_api, output_api):
2473 results = []
2474 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472475 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282476 results.extend(
jam93a6ee792017-02-08 23:59:222477 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192478 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222479 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132480 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162481 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542482 return results
[email protected]ca8d19842009-02-19 16:33:122483
2484
[email protected]1bfb8322014-04-23 01:02:412485def GetTryServerMasterForBot(bot):
2486 """Returns the Try Server master for the given bot.
2487
[email protected]0bb112362014-07-26 04:38:322488 It tries to guess the master from the bot name, but may still fail
2489 and return None. There is no longer a default master.
2490 """
2491 # Potentially ambiguous bot names are listed explicitly.
2492 master_map = {
tandriie5587792016-07-14 00:34:502493 'chromium_presubmit': 'master.tryserver.chromium.linux',
2494 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412495 }
[email protected]0bb112362014-07-26 04:38:322496 master = master_map.get(bot)
2497 if not master:
wnwen4fbaab82016-05-25 12:54:362498 if 'android' in bot:
tandriie5587792016-07-14 00:34:502499 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362500 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502501 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322502 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502503 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322504 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502505 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322506 return master
[email protected]1bfb8322014-04-23 01:02:412507
2508
Paweł Hajdan, Jr55083782014-12-19 20:32:562509def GetDefaultTryConfigs(bots):
2510 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012511 """
2512
Paweł Hajdan, Jr55083782014-12-19 20:32:562513 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412514
2515 # Build up the mapping from tryserver master to bot/test.
2516 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562517 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412518 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2519 return out
[email protected]38c6a512013-12-18 23:48:012520
2521
[email protected]ca8d19842009-02-19 16:33:122522def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542523 results = []
[email protected]1f7b4172010-01-28 01:17:342524 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542525 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272526 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342527 input_api,
2528 output_api,
[email protected]2fdd1f362013-01-16 03:56:032529 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272530
jam93a6ee792017-02-08 23:59:222531 results.extend(
2532 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542533 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2534 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412535 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2536 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542537 return results