blob: 7f09ce510a65b5701e75d8d3d9e7a99fbf6bbb70 [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 (
[email protected]23e6cbc2012-06-16 18:51:20192 'ScopedAllowIO',
193 (
[email protected]e3c945502012-06-26 20:01:49194 'New code should not use ScopedAllowIO. Post a task to the blocking',
195 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20196 ),
[email protected]e3c945502012-06-26 20:01:49197 True,
[email protected]7345da02012-11-27 14:31:49198 (
hajimehoshi2acea432017-03-08 08:55:37199 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08200 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32201 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10202 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22203 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31204 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51205 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
206 "customization_document_browsertest\.cc$",
Asanka Herath2ea5bc12017-05-26 17:30:46207 r"^chrome[\\\/]test[\\\/]ppapi[\\\/]ppapi_filechooser_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09208 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49209 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
210 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25211 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41212 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
213 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25214 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57215 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
216 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48217 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
218 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01219 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25220 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
221 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
222 r"embedded_test_server\.cc$",
223 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
224 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54225 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16226 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53227 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
228 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45229 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
230 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
231 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
232 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
233 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49234 ),
[email protected]23e6cbc2012-06-16 18:51:20235 ),
[email protected]52657f62013-05-20 05:30:31236 (
tomhudsone2c14d552016-05-26 17:07:46237 'setMatrixClip',
238 (
239 'Overriding setMatrixClip() is prohibited; ',
240 'the base function is deprecated. ',
241 ),
242 True,
243 (),
244 ),
245 (
[email protected]52657f62013-05-20 05:30:31246 'SkRefPtr',
247 (
248 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22249 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31250 ),
251 True,
252 (),
253 ),
254 (
255 'SkAutoRef',
256 (
257 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22258 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31259 ),
260 True,
261 (),
262 ),
263 (
264 'SkAutoTUnref',
265 (
266 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22267 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31268 ),
269 True,
270 (),
271 ),
272 (
273 'SkAutoUnref',
274 (
275 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
276 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22277 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31278 ),
279 True,
280 (),
281 ),
[email protected]d89eec82013-12-03 14:10:59282 (
283 r'/HANDLE_EINTR\(.*close',
284 (
285 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
286 'descriptor will be closed, and it is incorrect to retry the close.',
287 'Either call close directly and ignore its return value, or wrap close',
288 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
289 ),
290 True,
291 (),
292 ),
293 (
294 r'/IGNORE_EINTR\((?!.*close)',
295 (
296 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
297 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
298 ),
299 True,
300 (
301 # Files that #define IGNORE_EINTR.
302 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
303 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
304 ),
305 ),
[email protected]ec5b3f02014-04-04 18:43:43306 (
307 r'/v8::Extension\(',
308 (
309 'Do not introduce new v8::Extensions into the code base, use',
310 'gin::Wrappable instead. See http://crbug.com/334679',
311 ),
312 True,
[email protected]f55c90ee62014-04-12 00:50:03313 (
joaodasilva718f87672014-08-30 09:25:49314 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03315 ),
[email protected]ec5b3f02014-04-04 18:43:43316 ),
skyostilf9469f72015-04-20 10:38:52317 (
jame2d1a952016-04-02 00:27:10318 '#pragma comment(lib,',
319 (
320 'Specify libraries to link with in build files and not in the source.',
321 ),
322 True,
323 (),
324 ),
fdorayc4ac18d2017-05-01 21:39:59325 (
326 'BrowserThread::GetBlockingPool',
327 (
328 'Use base/task_scheduler/post_task.h instead of the blocking pool. See',
329 'mapping between both APIs in content/public/browser/browser_thread.h.',
330 'For questions, contact base/task_scheduler/OWNERS.',
331 ),
332 True,
333 (),
334 ),
gabd52c912a2017-05-11 04:15:59335 (
336 'base::NonThreadSafe',
337 (
338 'base::NonThreadSafe is deprecated.',
339 ),
340 True,
341 (),
342 ),
343 (
344 'base::SequenceChecker',
345 (
346 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
347 ),
348 False,
349 (),
350 ),
351 (
352 'base::ThreadChecker',
353 (
354 'Consider using THREAD_CHECKER macros instead of the class directly.',
355 ),
356 False,
357 (),
358 ),
[email protected]127f18ec2012-06-16 05:05:59359)
360
wnwenbdc444e2016-05-25 13:44:15361
mlamouria82272622014-09-16 18:45:04362_IPC_ENUM_TRAITS_DEPRECATED = (
363 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
364 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
365
[email protected]127f18ec2012-06-16 05:05:59366
[email protected]b00342e7f2013-03-26 16:21:54367_VALID_OS_MACROS = (
368 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08369 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54370 'OS_ANDROID',
371 'OS_BSD',
372 'OS_CAT', # For testing.
373 'OS_CHROMEOS',
374 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37375 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54376 'OS_IOS',
377 'OS_LINUX',
378 'OS_MACOSX',
379 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21380 'OS_NACL_NONSFI',
381 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12382 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54383 'OS_OPENBSD',
384 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37385 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54386 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54387 'OS_WIN',
388)
389
390
agrievef32bcc72016-04-04 14:57:40391_ANDROID_SPECIFIC_PYDEPS_FILES = [
392 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04393 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58394 'build/secondary/third_party/android_platform/'
395 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19396 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40397]
398
wnwenbdc444e2016-05-25 13:44:15399
agrievef32bcc72016-04-04 14:57:40400_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40401]
402
wnwenbdc444e2016-05-25 13:44:15403
agrievef32bcc72016-04-04 14:57:40404_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
405
406
[email protected]55459852011-08-10 15:17:19407def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
408 """Attempts to prevent use of functions intended only for testing in
409 non-testing code. For now this is just a best-effort implementation
410 that ignores header files and may have some false positives. A
411 better implementation would probably need a proper C++ parser.
412 """
413 # We only scan .cc files and the like, as the declaration of
414 # for-testing functions in header files are hard to distinguish from
415 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44416 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19417
jochenc0d4808c2015-07-27 09:25:42418 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19419 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09420 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19421 exclusion_pattern = input_api.re.compile(
422 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
423 base_function_pattern, base_function_pattern))
424
425 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44426 black_list = (_EXCLUDED_PATHS +
427 _TEST_CODE_EXCLUDED_PATHS +
428 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19429 return input_api.FilterSourceFile(
430 affected_file,
431 white_list=(file_inclusion_pattern, ),
432 black_list=black_list)
433
434 problems = []
435 for f in input_api.AffectedSourceFiles(FilterFile):
436 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24437 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03438 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46439 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03440 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19441 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03442 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19443
444 if problems:
[email protected]f7051d52013-04-02 18:31:42445 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03446 else:
447 return []
[email protected]55459852011-08-10 15:17:19448
449
[email protected]10689ca2011-09-02 02:31:54450def _CheckNoIOStreamInHeaders(input_api, output_api):
451 """Checks to make sure no .h files include <iostream>."""
452 files = []
453 pattern = input_api.re.compile(r'^#include\s*<iostream>',
454 input_api.re.MULTILINE)
455 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
456 if not f.LocalPath().endswith('.h'):
457 continue
458 contents = input_api.ReadFile(f)
459 if pattern.search(contents):
460 files.append(f)
461
462 if len(files):
yolandyandaabc6d2016-04-18 18:29:39463 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06464 'Do not #include <iostream> in header files, since it inserts static '
465 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54466 '#include <ostream>. See http://crbug.com/94794',
467 files) ]
468 return []
469
470
[email protected]72df4e782012-06-21 16:28:18471def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52472 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18473 problems = []
474 for f in input_api.AffectedFiles():
475 if (not f.LocalPath().endswith(('.cc', '.mm'))):
476 continue
477
478 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04479 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18480 problems.append(' %s:%d' % (f.LocalPath(), line_num))
481
482 if not problems:
483 return []
484 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
485 '\n'.join(problems))]
486
487
danakj61c1aa22015-10-26 19:55:52488def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57489 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52490 errors = []
491 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
492 input_api.re.MULTILINE)
493 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
494 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
495 continue
496 for lnum, line in f.ChangedContents():
497 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17498 errors.append(output_api.PresubmitError(
499 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57500 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17501 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52502 return errors
503
504
mcasasb7440c282015-02-04 14:52:19505def _FindHistogramNameInLine(histogram_name, line):
506 """Tries to find a histogram name or prefix in a line."""
507 if not "affected-histogram" in line:
508 return histogram_name in line
509 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
510 # the histogram_name.
511 if not '"' in line:
512 return False
513 histogram_prefix = line.split('\"')[1]
514 return histogram_prefix in histogram_name
515
516
517def _CheckUmaHistogramChanges(input_api, output_api):
518 """Check that UMA histogram names in touched lines can still be found in other
519 lines of the patch or in histograms.xml. Note that this check would not catch
520 the reverse: changes in histograms.xml not matched in the code itself."""
521 touched_histograms = []
522 histograms_xml_modifications = []
523 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
524 for f in input_api.AffectedFiles():
525 # If histograms.xml itself is modified, keep the modified lines for later.
526 if f.LocalPath().endswith(('histograms.xml')):
527 histograms_xml_modifications = f.ChangedContents()
528 continue
529 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
530 continue
531 for line_num, line in f.ChangedContents():
532 found = pattern.search(line)
533 if found:
534 touched_histograms.append([found.group(1), f, line_num])
535
536 # Search for the touched histogram names in the local modifications to
537 # histograms.xml, and, if not found, on the base histograms.xml file.
538 unmatched_histograms = []
539 for histogram_info in touched_histograms:
540 histogram_name_found = False
541 for line_num, line in histograms_xml_modifications:
542 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
543 if histogram_name_found:
544 break
545 if not histogram_name_found:
546 unmatched_histograms.append(histogram_info)
547
eromanb90c82e7e32015-04-01 15:13:49548 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19549 problems = []
550 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49551 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19552 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45553 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19554 histogram_name_found = False
555 for line in histograms_xml:
556 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
557 if histogram_name_found:
558 break
559 if not histogram_name_found:
560 problems.append(' [%s:%d] %s' %
561 (f.LocalPath(), line_num, histogram_name))
562
563 if not problems:
564 return []
565 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
566 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49567 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19568
wnwenbdc444e2016-05-25 13:44:15569
yolandyandaabc6d2016-04-18 18:29:39570def _CheckFlakyTestUsage(input_api, output_api):
571 """Check that FlakyTest annotation is our own instead of the android one"""
572 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
573 files = []
574 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
575 if f.LocalPath().endswith('Test.java'):
576 if pattern.search(input_api.ReadFile(f)):
577 files.append(f)
578 if len(files):
579 return [output_api.PresubmitError(
580 'Use org.chromium.base.test.util.FlakyTest instead of '
581 'android.test.FlakyTest',
582 files)]
583 return []
mcasasb7440c282015-02-04 14:52:19584
wnwenbdc444e2016-05-25 13:44:15585
[email protected]8ea5d4b2011-09-13 21:49:22586def _CheckNoNewWStrings(input_api, output_api):
587 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27588 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22589 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20590 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57591 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34592 '/win/' in f.LocalPath() or
593 'chrome_elf' in f.LocalPath() or
594 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20595 continue
[email protected]8ea5d4b2011-09-13 21:49:22596
[email protected]a11dbe9b2012-08-07 01:32:58597 allowWString = False
[email protected]b5c24292011-11-28 14:38:20598 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58599 if 'presubmit: allow wstring' in line:
600 allowWString = True
601 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27602 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58603 allowWString = False
604 else:
605 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22606
[email protected]55463aa62011-10-12 00:48:27607 if not problems:
608 return []
609 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58610 ' If you are calling a cross-platform API that accepts a wstring, '
611 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27612 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22613
614
[email protected]2a8ac9c2011-10-19 17:20:44615def _CheckNoDEPSGIT(input_api, output_api):
616 """Make sure .DEPS.git is never modified manually."""
617 if any(f.LocalPath().endswith('.DEPS.git') for f in
618 input_api.AffectedFiles()):
619 return [output_api.PresubmitError(
620 'Never commit changes to .DEPS.git. This file is maintained by an\n'
621 'automated system based on what\'s in DEPS and your changes will be\n'
622 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34623 '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:44624 'for more information')]
625 return []
626
627
tandriief664692014-09-23 14:51:47628def _CheckValidHostsInDEPS(input_api, output_api):
629 """Checks that DEPS file deps are from allowed_hosts."""
630 # Run only if DEPS file has been modified to annoy fewer bystanders.
631 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
632 return []
633 # Outsource work to gclient verify
634 try:
635 input_api.subprocess.check_output(['gclient', 'verify'])
636 return []
637 except input_api.subprocess.CalledProcessError, error:
638 return [output_api.PresubmitError(
639 'DEPS file must have only git dependencies.',
640 long_text=error.output)]
641
642
[email protected]127f18ec2012-06-16 05:05:59643def _CheckNoBannedFunctions(input_api, output_api):
644 """Make sure that banned functions are not used."""
645 warnings = []
646 errors = []
647
wnwenbdc444e2016-05-25 13:44:15648 def IsBlacklisted(affected_file, blacklist):
649 local_path = affected_file.LocalPath()
650 for item in blacklist:
651 if input_api.re.match(item, local_path):
652 return True
653 return False
654
655 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
656 matched = False
657 if func_name[0:1] == '/':
658 regex = func_name[1:]
659 if input_api.re.search(regex, line):
660 matched = True
661 elif func_name in line:
dchenge07de812016-06-20 19:27:17662 matched = True
wnwenbdc444e2016-05-25 13:44:15663 if matched:
dchenge07de812016-06-20 19:27:17664 problems = warnings
wnwenbdc444e2016-05-25 13:44:15665 if error:
dchenge07de812016-06-20 19:27:17666 problems = errors
wnwenbdc444e2016-05-25 13:44:15667 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
668 for message_line in message:
669 problems.append(' %s' % message_line)
670
[email protected]127f18ec2012-06-16 05:05:59671 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
672 for f in input_api.AffectedFiles(file_filter=file_filter):
673 for line_num, line in f.ChangedContents():
674 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15675 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59676
677 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
678 for f in input_api.AffectedFiles(file_filter=file_filter):
679 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49680 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49681 if IsBlacklisted(f, excluded_paths):
682 continue
wnwenbdc444e2016-05-25 13:44:15683 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59684
685 result = []
686 if (warnings):
687 result.append(output_api.PresubmitPromptWarning(
688 'Banned functions were used.\n' + '\n'.join(warnings)))
689 if (errors):
690 result.append(output_api.PresubmitError(
691 'Banned functions were used.\n' + '\n'.join(errors)))
692 return result
693
694
[email protected]6c063c62012-07-11 19:11:06695def _CheckNoPragmaOnce(input_api, output_api):
696 """Make sure that banned functions are not used."""
697 files = []
698 pattern = input_api.re.compile(r'^#pragma\s+once',
699 input_api.re.MULTILINE)
700 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
701 if not f.LocalPath().endswith('.h'):
702 continue
703 contents = input_api.ReadFile(f)
704 if pattern.search(contents):
705 files.append(f)
706
707 if files:
708 return [output_api.PresubmitError(
709 'Do not use #pragma once in header files.\n'
710 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
711 files)]
712 return []
713
[email protected]127f18ec2012-06-16 05:05:59714
[email protected]e7479052012-09-19 00:26:12715def _CheckNoTrinaryTrueFalse(input_api, output_api):
716 """Checks to make sure we don't introduce use of foo ? true : false."""
717 problems = []
718 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
719 for f in input_api.AffectedFiles():
720 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
721 continue
722
723 for line_num, line in f.ChangedContents():
724 if pattern.match(line):
725 problems.append(' %s:%d' % (f.LocalPath(), line_num))
726
727 if not problems:
728 return []
729 return [output_api.PresubmitPromptWarning(
730 'Please consider avoiding the "? true : false" pattern if possible.\n' +
731 '\n'.join(problems))]
732
733
[email protected]55f9f382012-07-31 11:02:18734def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28735 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18736 change. Breaking - rules is an error, breaking ! rules is a
737 warning.
738 """
mohan.reddyf21db962014-10-16 12:26:47739 import sys
[email protected]55f9f382012-07-31 11:02:18740 # We need to wait until we have an input_api object and use this
741 # roundabout construct to import checkdeps because this file is
742 # eval-ed and thus doesn't have __file__.
743 original_sys_path = sys.path
744 try:
745 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47746 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18747 import checkdeps
748 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28749 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18750 from rules import Rule
751 finally:
752 # Restore sys.path to what it was before.
753 sys.path = original_sys_path
754
755 added_includes = []
rhalavati08acd232017-04-03 07:23:28756 added_imports = []
[email protected]55f9f382012-07-31 11:02:18757 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28758 if CppChecker.IsCppFile(f.LocalPath()):
759 changed_lines = [line for line_num, line in f.ChangedContents()]
760 added_includes.append([f.LocalPath(), changed_lines])
761 elif ProtoChecker.IsProtoFile(f.LocalPath()):
762 changed_lines = [line for line_num, line in f.ChangedContents()]
763 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18764
[email protected]26385172013-05-09 23:11:35765 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18766
767 error_descriptions = []
768 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28769 error_subjects = set()
770 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18771 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
772 added_includes):
773 description_with_path = '%s\n %s' % (path, rule_description)
774 if rule_type == Rule.DISALLOW:
775 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28776 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18777 else:
778 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28779 warning_subjects.add("#includes")
780
781 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
782 added_imports):
783 description_with_path = '%s\n %s' % (path, rule_description)
784 if rule_type == Rule.DISALLOW:
785 error_descriptions.append(description_with_path)
786 error_subjects.add("imports")
787 else:
788 warning_descriptions.append(description_with_path)
789 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18790
791 results = []
792 if error_descriptions:
793 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28794 'You added one or more %s that violate checkdeps rules.'
795 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18796 error_descriptions))
797 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42798 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28799 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18800 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28801 '%s? See relevant DEPS file(s) for details and contacts.' %
802 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18803 warning_descriptions))
804 return results
805
806
[email protected]fbcafe5a2012-08-08 15:31:22807def _CheckFilePermissions(input_api, output_api):
808 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15809 if input_api.platform == 'win32':
810 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29811 checkperms_tool = input_api.os_path.join(
812 input_api.PresubmitLocalPath(),
813 'tools', 'checkperms', 'checkperms.py')
814 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47815 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22816 for f in input_api.AffectedFiles():
817 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11818 try:
819 input_api.subprocess.check_output(args)
820 return []
821 except input_api.subprocess.CalledProcessError as error:
822 return [output_api.PresubmitError(
823 'checkperms.py failed:',
824 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22825
826
robertocn832f5992017-01-04 19:01:30827def _CheckTeamTags(input_api, output_api):
828 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
829 checkteamtags_tool = input_api.os_path.join(
830 input_api.PresubmitLocalPath(),
831 'tools', 'checkteamtags', 'checkteamtags.py')
832 args = [input_api.python_executable, checkteamtags_tool,
833 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22834 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30835 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
836 'OWNERS']
837 try:
838 if files:
839 input_api.subprocess.check_output(args + files)
840 return []
841 except input_api.subprocess.CalledProcessError as error:
842 return [output_api.PresubmitError(
843 'checkteamtags.py failed:',
844 long_text=error.output)]
845
846
[email protected]c8278b32012-10-30 20:35:49847def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
848 """Makes sure we don't include ui/aura/window_property.h
849 in header files.
850 """
851 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
852 errors = []
853 for f in input_api.AffectedFiles():
854 if not f.LocalPath().endswith('.h'):
855 continue
856 for line_num, line in f.ChangedContents():
857 if pattern.match(line):
858 errors.append(' %s:%d' % (f.LocalPath(), line_num))
859
860 results = []
861 if errors:
862 results.append(output_api.PresubmitError(
863 'Header files should not include ui/aura/window_property.h', errors))
864 return results
865
866
[email protected]cf9b78f2012-11-14 11:40:28867def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
868 """Checks that the lines in scope occur in the right order.
869
870 1. C system files in alphabetical order
871 2. C++ system files in alphabetical order
872 3. Project's .h files
873 """
874
875 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
876 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
877 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
878
879 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
880
881 state = C_SYSTEM_INCLUDES
882
883 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57884 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28885 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55886 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28887 for line_num, line in scope:
888 if c_system_include_pattern.match(line):
889 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55890 problem_linenums.append((line_num, previous_line_num,
891 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28892 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55893 problem_linenums.append((line_num, previous_line_num,
894 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28895 elif cpp_system_include_pattern.match(line):
896 if state == C_SYSTEM_INCLUDES:
897 state = CPP_SYSTEM_INCLUDES
898 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55899 problem_linenums.append((line_num, previous_line_num,
900 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28901 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55902 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28903 elif custom_include_pattern.match(line):
904 if state != CUSTOM_INCLUDES:
905 state = CUSTOM_INCLUDES
906 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55907 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28908 else:
brucedawson70fadb02015-06-30 17:47:55909 problem_linenums.append((line_num, previous_line_num,
910 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28911 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57912 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28913
914 warnings = []
brucedawson70fadb02015-06-30 17:47:55915 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57916 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55917 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28918 return warnings
919
920
[email protected]ac294a12012-12-06 16:38:43921def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28922 """Checks the #include order for the given file f."""
923
[email protected]2299dcf2012-11-15 19:56:24924 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30925 # Exclude the following includes from the check:
926 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
927 # specific order.
928 # 2) <atlbase.h>, "build/build_config.h"
929 excluded_include_pattern = input_api.re.compile(
930 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24931 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33932 # Match the final or penultimate token if it is xxxtest so we can ignore it
933 # when considering the special first include.
934 test_file_tag_pattern = input_api.re.compile(
935 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11936 if_pattern = input_api.re.compile(
937 r'\s*#\s*(if|elif|else|endif|define|undef).*')
938 # Some files need specialized order of includes; exclude such files from this
939 # check.
940 uncheckable_includes_pattern = input_api.re.compile(
941 r'\s*#include '
942 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28943
944 contents = f.NewContents()
945 warnings = []
946 line_num = 0
947
[email protected]ac294a12012-12-06 16:38:43948 # Handle the special first include. If the first include file is
949 # some/path/file.h, the corresponding including file can be some/path/file.cc,
950 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
951 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33952 # If the included file is some/path/file_platform.h the including file could
953 # also be some/path/file_xxxtest_platform.h.
954 including_file_base_name = test_file_tag_pattern.sub(
955 '', input_api.os_path.basename(f.LocalPath()))
956
[email protected]ac294a12012-12-06 16:38:43957 for line in contents:
958 line_num += 1
959 if system_include_pattern.match(line):
960 # No special first include -> process the line again along with normal
961 # includes.
962 line_num -= 1
963 break
964 match = custom_include_pattern.match(line)
965 if match:
966 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33967 header_basename = test_file_tag_pattern.sub(
968 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
969
970 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24971 # No special first include -> process the line again along with normal
972 # includes.
973 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43974 break
[email protected]cf9b78f2012-11-14 11:40:28975
976 # Split into scopes: Each region between #if and #endif is its own scope.
977 scopes = []
978 current_scope = []
979 for line in contents[line_num:]:
980 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11981 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54982 continue
[email protected]2309b0fa02012-11-16 12:18:27983 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28984 scopes.append(current_scope)
985 current_scope = []
[email protected]962f117e2012-11-22 18:11:56986 elif ((system_include_pattern.match(line) or
987 custom_include_pattern.match(line)) and
988 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28989 current_scope.append((line_num, line))
990 scopes.append(current_scope)
991
992 for scope in scopes:
993 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
994 changed_linenums))
995 return warnings
996
997
998def _CheckIncludeOrder(input_api, output_api):
999 """Checks that the #include order is correct.
1000
1001 1. The corresponding header for source files.
1002 2. C system files in alphabetical order
1003 3. C++ system files in alphabetical order
1004 4. Project's .h files in alphabetical order
1005
[email protected]ac294a12012-12-06 16:38:431006 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
1007 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:281008 """
[email protected]e120b012014-08-15 19:08:351009 def FileFilterIncludeOrder(affected_file):
1010 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
1011 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:281012
1013 warnings = []
[email protected]e120b012014-08-15 19:08:351014 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:081015 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:431016 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
1017 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:281018
1019 results = []
1020 if warnings:
[email protected]f7051d52013-04-02 18:31:421021 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:531022 warnings))
[email protected]cf9b78f2012-11-14 11:40:281023 return results
1024
1025
[email protected]70ca77752012-11-20 03:45:031026def _CheckForVersionControlConflictsInFile(input_api, f):
1027 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1028 errors = []
1029 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231030 if f.LocalPath().endswith('.md'):
1031 # First-level headers in markdown look a lot like version control
1032 # conflict markers. http://daringfireball.net/projects/markdown/basics
1033 continue
[email protected]70ca77752012-11-20 03:45:031034 if pattern.match(line):
1035 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1036 return errors
1037
1038
1039def _CheckForVersionControlConflicts(input_api, output_api):
1040 """Usually this is not intentional and will cause a compile failure."""
1041 errors = []
1042 for f in input_api.AffectedFiles():
1043 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1044
1045 results = []
1046 if errors:
1047 results.append(output_api.PresubmitError(
1048 'Version control conflict markers found, please resolve.', errors))
1049 return results
1050
estadee17314a02017-01-12 16:22:161051def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1052 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1053 errors = []
1054 for f in input_api.AffectedFiles():
1055 for line_num, line in f.ChangedContents():
1056 if pattern.search(line):
1057 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1058
1059 results = []
1060 if errors:
1061 results.append(output_api.PresubmitPromptWarning(
1062 'Found Google support URL addressed by answer number. Please replace with '
1063 'a p= identifier instead. See crbug.com/679462\n', errors))
1064 return results
1065
[email protected]70ca77752012-11-20 03:45:031066
[email protected]06e6d0ff2012-12-11 01:36:441067def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1068 def FilterFile(affected_file):
1069 """Filter function for use with input_api.AffectedSourceFiles,
1070 below. This filters out everything except non-test files from
1071 top-level directories that generally speaking should not hard-code
1072 service URLs (e.g. src/android_webview/, src/content/ and others).
1073 """
1074 return input_api.FilterSourceFile(
1075 affected_file,
[email protected]78bb39d62012-12-11 15:11:561076 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441077 black_list=(_EXCLUDED_PATHS +
1078 _TEST_CODE_EXCLUDED_PATHS +
1079 input_api.DEFAULT_BLACK_LIST))
1080
reillyi38965732015-11-16 18:27:331081 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1082 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461083 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1084 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441085 problems = [] # items are (filename, line_number, line)
1086 for f in input_api.AffectedSourceFiles(FilterFile):
1087 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461088 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441089 problems.append((f.LocalPath(), line_num, line))
1090
1091 if problems:
[email protected]f7051d52013-04-02 18:31:421092 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441093 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581094 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441095 [' %s:%d: %s' % (
1096 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031097 else:
1098 return []
[email protected]06e6d0ff2012-12-11 01:36:441099
1100
[email protected]d2530012013-01-25 16:39:271101def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1102 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311103 The native_client_sdk directory is excluded because it has auto-generated PNG
1104 files for documentation.
[email protected]d2530012013-01-25 16:39:271105 """
[email protected]d2530012013-01-25 16:39:271106 errors = []
binji0dcdf342014-12-12 18:32:311107 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1108 black_list = (r'^native_client_sdk[\\\/]',)
1109 file_filter = lambda f: input_api.FilterSourceFile(
1110 f, white_list=white_list, black_list=black_list)
1111 for f in input_api.AffectedFiles(include_deletes=False,
1112 file_filter=file_filter):
1113 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271114
1115 results = []
1116 if errors:
1117 results.append(output_api.PresubmitError(
1118 'The name of PNG files should not have abbreviations. \n'
1119 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1120 'Contact [email protected] if you have questions.', errors))
1121 return results
1122
1123
Daniel Cheng4dcdb6b2017-04-13 08:30:171124def _ExtractAddRulesFromParsedDeps(parsed_deps):
1125 """Extract the rules that add dependencies from a parsed DEPS file.
1126
1127 Args:
1128 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1129 add_rules = set()
1130 add_rules.update([
1131 rule[1:] for rule in parsed_deps.get('include_rules', [])
1132 if rule.startswith('+') or rule.startswith('!')
1133 ])
1134 for specific_file, rules in parsed_deps.get('specific_include_rules',
1135 {}).iteritems():
1136 add_rules.update([
1137 rule[1:] for rule in rules
1138 if rule.startswith('+') or rule.startswith('!')
1139 ])
1140 return add_rules
1141
1142
1143def _ParseDeps(contents):
1144 """Simple helper for parsing DEPS files."""
1145 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171146 class _VarImpl:
1147
1148 def __init__(self, local_scope):
1149 self._local_scope = local_scope
1150
1151 def Lookup(self, var_name):
1152 """Implements the Var syntax."""
1153 try:
1154 return self._local_scope['vars'][var_name]
1155 except KeyError:
1156 raise Exception('Var is not defined: %s' % var_name)
1157
1158 local_scope = {}
1159 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171160 'Var': _VarImpl(local_scope).Lookup,
1161 }
1162 exec contents in global_scope, local_scope
1163 return local_scope
1164
1165
1166def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081167 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411168 a set of DEPS entries that we should look up.
1169
1170 For a directory (rather than a specific filename) we fake a path to
1171 a specific filename by adding /DEPS. This is chosen as a file that
1172 will seldom or never be subject to per-file include_rules.
1173 """
[email protected]2b438d62013-11-14 17:54:141174 # We ignore deps entries on auto-generated directories.
1175 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081176
Daniel Cheng4dcdb6b2017-04-13 08:30:171177 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1178 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1179
1180 added_deps = new_deps.difference(old_deps)
1181
[email protected]2b438d62013-11-14 17:54:141182 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171183 for added_dep in added_deps:
1184 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1185 continue
1186 # Assume that a rule that ends in .h is a rule for a specific file.
1187 if added_dep.endswith('.h'):
1188 results.add(added_dep)
1189 else:
1190 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081191 return results
1192
1193
[email protected]e871964c2013-05-13 14:14:551194def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1195 """When a dependency prefixed with + is added to a DEPS file, we
1196 want to make sure that the change is reviewed by an OWNER of the
1197 target file or directory, to avoid layering violations from being
1198 introduced. This check verifies that this happens.
1199 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171200 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241201
1202 file_filter = lambda f: not input_api.re.match(
1203 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1204 for f in input_api.AffectedFiles(include_deletes=False,
1205 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551206 filename = input_api.os_path.basename(f.LocalPath())
1207 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171208 virtual_depended_on_files.update(_CalculateAddedDeps(
1209 input_api.os_path,
1210 '\n'.join(f.OldContents()),
1211 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551212
[email protected]e871964c2013-05-13 14:14:551213 if not virtual_depended_on_files:
1214 return []
1215
1216 if input_api.is_committing:
1217 if input_api.tbr:
1218 return [output_api.PresubmitNotifyResult(
1219 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271220 if input_api.dry_run:
1221 return [output_api.PresubmitNotifyResult(
1222 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551223 if not input_api.change.issue:
1224 return [output_api.PresubmitError(
1225 "DEPS approval by OWNERS check failed: this change has "
1226 "no Rietveld issue number, so we can't check it for approvals.")]
1227 output = output_api.PresubmitError
1228 else:
1229 output = output_api.PresubmitNotifyResult
1230
1231 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501232 owner_email, reviewers = (
1233 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1234 input_api,
1235 owners_db.email_regexp,
1236 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551237
1238 owner_email = owner_email or input_api.change.author_email
1239
[email protected]de4f7d22013-05-23 14:27:461240 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511241 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461242 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551243 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1244 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411245
1246 # We strip the /DEPS part that was added by
1247 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1248 # directory.
1249 def StripDeps(path):
1250 start_deps = path.rfind('/DEPS')
1251 if start_deps != -1:
1252 return path[:start_deps]
1253 else:
1254 return path
1255 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551256 for path in missing_files]
1257
1258 if unapproved_dependencies:
1259 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151260 output('You need LGTM from owners of depends-on paths in DEPS that were '
1261 'modified in this CL:\n %s' %
1262 '\n '.join(sorted(unapproved_dependencies)))]
1263 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1264 output_list.append(output(
1265 'Suggested missing target path OWNERS:\n %s' %
1266 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551267 return output_list
1268
1269 return []
1270
1271
[email protected]85218562013-11-22 07:41:401272def _CheckSpamLogging(input_api, output_api):
1273 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1274 black_list = (_EXCLUDED_PATHS +
1275 _TEST_CODE_EXCLUDED_PATHS +
1276 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501277 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191278 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481279 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461280 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121281 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1282 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581283 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161284 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031285 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151286 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1287 r"^chromecast[\\\/]",
1288 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481289 r"^components[\\\/]browser_watcher[\\\/]"
1290 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311291 r"^components[\\\/]html_viewer[\\\/]"
1292 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461293 # TODO(peter): Remove this exception. https://crbug.com/534537
1294 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1295 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251296 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1297 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241298 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111299 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151300 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111301 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521302 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501303 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361304 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311305 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131306 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001307 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441308 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451309 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021310 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351311 r"dump_file_system.cc$",
1312 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401313 source_file_filter = lambda x: input_api.FilterSourceFile(
1314 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1315
thomasanderson625d3932017-03-29 07:16:581316 log_info = set([])
1317 printf = set([])
[email protected]85218562013-11-22 07:41:401318
1319 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581320 for _, line in f.ChangedContents():
1321 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1322 log_info.add(f.LocalPath())
1323 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1324 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371325
thomasanderson625d3932017-03-29 07:16:581326 if input_api.re.search(r"\bprintf\(", line):
1327 printf.add(f.LocalPath())
1328 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1329 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401330
1331 if log_info:
1332 return [output_api.PresubmitError(
1333 'These files spam the console log with LOG(INFO):',
1334 items=log_info)]
1335 if printf:
1336 return [output_api.PresubmitError(
1337 'These files spam the console log with printf/fprintf:',
1338 items=printf)]
1339 return []
1340
1341
[email protected]49aa76a2013-12-04 06:59:161342def _CheckForAnonymousVariables(input_api, output_api):
1343 """These types are all expected to hold locks while in scope and
1344 so should never be anonymous (which causes them to be immediately
1345 destroyed)."""
1346 they_who_must_be_named = [
1347 'base::AutoLock',
1348 'base::AutoReset',
1349 'base::AutoUnlock',
1350 'SkAutoAlphaRestore',
1351 'SkAutoBitmapShaderInstall',
1352 'SkAutoBlitterChoose',
1353 'SkAutoBounderCommit',
1354 'SkAutoCallProc',
1355 'SkAutoCanvasRestore',
1356 'SkAutoCommentBlock',
1357 'SkAutoDescriptor',
1358 'SkAutoDisableDirectionCheck',
1359 'SkAutoDisableOvalCheck',
1360 'SkAutoFree',
1361 'SkAutoGlyphCache',
1362 'SkAutoHDC',
1363 'SkAutoLockColors',
1364 'SkAutoLockPixels',
1365 'SkAutoMalloc',
1366 'SkAutoMaskFreeImage',
1367 'SkAutoMutexAcquire',
1368 'SkAutoPathBoundsUpdate',
1369 'SkAutoPDFRelease',
1370 'SkAutoRasterClipValidate',
1371 'SkAutoRef',
1372 'SkAutoTime',
1373 'SkAutoTrace',
1374 'SkAutoUnref',
1375 ]
1376 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1377 # bad: base::AutoLock(lock.get());
1378 # not bad: base::AutoLock lock(lock.get());
1379 bad_pattern = input_api.re.compile(anonymous)
1380 # good: new base::AutoLock(lock.get())
1381 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1382 errors = []
1383
1384 for f in input_api.AffectedFiles():
1385 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1386 continue
1387 for linenum, line in f.ChangedContents():
1388 if bad_pattern.search(line) and not good_pattern.search(line):
1389 errors.append('%s:%d' % (f.LocalPath(), linenum))
1390
1391 if errors:
1392 return [output_api.PresubmitError(
1393 'These lines create anonymous variables that need to be named:',
1394 items=errors)]
1395 return []
1396
1397
[email protected]5fe0f8742013-11-29 01:04:591398def _CheckCygwinShell(input_api, output_api):
1399 source_file_filter = lambda x: input_api.FilterSourceFile(
1400 x, white_list=(r'.+\.(gyp|gypi)$',))
1401 cygwin_shell = []
1402
1403 for f in input_api.AffectedSourceFiles(source_file_filter):
1404 for linenum, line in f.ChangedContents():
1405 if 'msvs_cygwin_shell' in line:
1406 cygwin_shell.append(f.LocalPath())
1407 break
1408
1409 if cygwin_shell:
1410 return [output_api.PresubmitError(
1411 'These files should not use msvs_cygwin_shell (the default is 0):',
1412 items=cygwin_shell)]
1413 return []
1414
[email protected]85218562013-11-22 07:41:401415
[email protected]999261d2014-03-03 20:08:081416def _CheckUserActionUpdate(input_api, output_api):
1417 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521418 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081419 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521420 # If actions.xml is already included in the changelist, the PRESUBMIT
1421 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081422 return []
1423
[email protected]999261d2014-03-03 20:08:081424 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1425 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521426 current_actions = None
[email protected]999261d2014-03-03 20:08:081427 for f in input_api.AffectedFiles(file_filter=file_filter):
1428 for line_num, line in f.ChangedContents():
1429 match = input_api.re.search(action_re, line)
1430 if match:
[email protected]2f92dec2014-03-07 19:21:521431 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1432 # loaded only once.
1433 if not current_actions:
1434 with open('tools/metrics/actions/actions.xml') as actions_f:
1435 current_actions = actions_f.read()
1436 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081437 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521438 action = 'name="{0}"'.format(action_name)
1439 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081440 return [output_api.PresubmitPromptWarning(
1441 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521442 'tools/metrics/actions/actions.xml. Please run '
1443 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081444 % (f.LocalPath(), line_num, action_name))]
1445 return []
1446
1447
[email protected]99171a92014-06-03 08:44:471448def _GetJSONParseError(input_api, filename, eat_comments=True):
1449 try:
1450 contents = input_api.ReadFile(filename)
1451 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131452 import sys
1453 original_sys_path = sys.path
1454 try:
1455 sys.path = sys.path + [input_api.os_path.join(
1456 input_api.PresubmitLocalPath(),
1457 'tools', 'json_comment_eater')]
1458 import json_comment_eater
1459 finally:
1460 sys.path = original_sys_path
1461 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471462
1463 input_api.json.loads(contents)
1464 except ValueError as e:
1465 return e
1466 return None
1467
1468
1469def _GetIDLParseError(input_api, filename):
1470 try:
1471 contents = input_api.ReadFile(filename)
1472 idl_schema = input_api.os_path.join(
1473 input_api.PresubmitLocalPath(),
1474 'tools', 'json_schema_compiler', 'idl_schema.py')
1475 process = input_api.subprocess.Popen(
1476 [input_api.python_executable, idl_schema],
1477 stdin=input_api.subprocess.PIPE,
1478 stdout=input_api.subprocess.PIPE,
1479 stderr=input_api.subprocess.PIPE,
1480 universal_newlines=True)
1481 (_, error) = process.communicate(input=contents)
1482 return error or None
1483 except ValueError as e:
1484 return e
1485
1486
1487def _CheckParseErrors(input_api, output_api):
1488 """Check that IDL and JSON files do not contain syntax errors."""
1489 actions = {
1490 '.idl': _GetIDLParseError,
1491 '.json': _GetJSONParseError,
1492 }
1493 # These paths contain test data and other known invalid JSON files.
1494 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491495 r'test[\\\/]data[\\\/]',
1496 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471497 ]
1498 # Most JSON files are preprocessed and support comments, but these do not.
1499 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491500 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471501 ]
1502 # Only run IDL checker on files in these directories.
1503 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491504 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1505 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471506 ]
1507
1508 def get_action(affected_file):
1509 filename = affected_file.LocalPath()
1510 return actions.get(input_api.os_path.splitext(filename)[1])
1511
1512 def MatchesFile(patterns, path):
1513 for pattern in patterns:
1514 if input_api.re.search(pattern, path):
1515 return True
1516 return False
1517
1518 def FilterFile(affected_file):
1519 action = get_action(affected_file)
1520 if not action:
1521 return False
1522 path = affected_file.LocalPath()
1523
1524 if MatchesFile(excluded_patterns, path):
1525 return False
1526
1527 if (action == _GetIDLParseError and
1528 not MatchesFile(idl_included_patterns, path)):
1529 return False
1530 return True
1531
1532 results = []
1533 for affected_file in input_api.AffectedFiles(
1534 file_filter=FilterFile, include_deletes=False):
1535 action = get_action(affected_file)
1536 kwargs = {}
1537 if (action == _GetJSONParseError and
1538 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1539 kwargs['eat_comments'] = False
1540 parse_error = action(input_api,
1541 affected_file.AbsoluteLocalPath(),
1542 **kwargs)
1543 if parse_error:
1544 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1545 (affected_file.LocalPath(), parse_error)))
1546 return results
1547
1548
[email protected]760deea2013-12-10 19:33:491549def _CheckJavaStyle(input_api, output_api):
1550 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471551 import sys
[email protected]760deea2013-12-10 19:33:491552 original_sys_path = sys.path
1553 try:
1554 sys.path = sys.path + [input_api.os_path.join(
1555 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1556 import checkstyle
1557 finally:
1558 # Restore sys.path to what it was before.
1559 sys.path = original_sys_path
1560
1561 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091562 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511563 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491564
1565
dchenge07de812016-06-20 19:27:171566def _CheckIpcOwners(input_api, output_api):
1567 """Checks that affected files involving IPC have an IPC OWNERS rule.
1568
1569 Whether or not a file affects IPC is determined by a simple whitelist of
1570 filename patterns."""
1571 file_patterns = [
palmerb19a0932017-01-24 04:00:311572 # Legacy IPC:
dchenge07de812016-06-20 19:27:171573 '*_messages.cc',
1574 '*_messages*.h',
1575 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311576 # Mojo IPC:
dchenge07de812016-06-20 19:27:171577 '*.mojom',
1578 '*_struct_traits*.*',
1579 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311580 '*.typemap',
1581 # Android native IPC:
1582 '*.aidl',
1583 # Blink uses a different file naming convention:
1584 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171585 '*StructTraits*.*',
1586 '*TypeConverter*.*',
1587 ]
1588
scottmg7a6ed5ba2016-11-04 18:22:041589 # These third_party directories do not contain IPCs, but contain files
1590 # matching the above patterns, which trigger false positives.
1591 exclude_paths = [
1592 'third_party/crashpad/*',
1593 ]
1594
dchenge07de812016-06-20 19:27:171595 # Dictionary mapping an OWNERS file path to Patterns.
1596 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1597 # rules ) to a PatternEntry.
1598 # PatternEntry is a dictionary with two keys:
1599 # - 'files': the files that are matched by this pattern
1600 # - 'rules': the per-file rules needed for this pattern
1601 # For example, if we expect OWNERS file to contain rules for *.mojom and
1602 # *_struct_traits*.*, Patterns might look like this:
1603 # {
1604 # '*.mojom': {
1605 # 'files': ...,
1606 # 'rules': [
1607 # 'per-file *.mojom=set noparent',
1608 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1609 # ],
1610 # },
1611 # '*_struct_traits*.*': {
1612 # 'files': ...,
1613 # 'rules': [
1614 # 'per-file *_struct_traits*.*=set noparent',
1615 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1616 # ],
1617 # },
1618 # }
1619 to_check = {}
1620
1621 # Iterate through the affected files to see what we actually need to check
1622 # for. We should only nag patch authors about per-file rules if a file in that
1623 # directory would match that pattern. If a directory only contains *.mojom
1624 # files and no *_messages*.h files, we should only nag about rules for
1625 # *.mojom files.
rockot51249332016-06-23 16:32:251626 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171627 for pattern in file_patterns:
1628 if input_api.fnmatch.fnmatch(
1629 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041630 skip = False
1631 for exclude in exclude_paths:
1632 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1633 skip = True
1634 break
1635 if skip:
1636 continue
dchenge07de812016-06-20 19:27:171637 owners_file = input_api.os_path.join(
1638 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1639 if owners_file not in to_check:
1640 to_check[owners_file] = {}
1641 if pattern not in to_check[owners_file]:
1642 to_check[owners_file][pattern] = {
1643 'files': [],
1644 'rules': [
1645 'per-file %s=set noparent' % pattern,
1646 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1647 ]
1648 }
1649 to_check[owners_file][pattern]['files'].append(f)
1650 break
1651
1652 # Now go through the OWNERS files we collected, filtering out rules that are
1653 # already present in that OWNERS file.
1654 for owners_file, patterns in to_check.iteritems():
1655 try:
1656 with file(owners_file) as f:
1657 lines = set(f.read().splitlines())
1658 for entry in patterns.itervalues():
1659 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1660 ]
1661 except IOError:
1662 # No OWNERS file, so all the rules are definitely missing.
1663 continue
1664
1665 # All the remaining lines weren't found in OWNERS files, so emit an error.
1666 errors = []
1667 for owners_file, patterns in to_check.iteritems():
1668 missing_lines = []
1669 files = []
1670 for pattern, entry in patterns.iteritems():
1671 missing_lines.extend(entry['rules'])
1672 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1673 if missing_lines:
1674 errors.append(
1675 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1676 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1677
1678 results = []
1679 if errors:
vabrf5ce3bf92016-07-11 14:52:411680 if input_api.is_committing:
1681 output = output_api.PresubmitError
1682 else:
1683 output = output_api.PresubmitPromptWarning
1684 results.append(output(
dchenge07de812016-06-20 19:27:171685 'Found changes to IPC files without a security OWNER!',
1686 long_text='\n\n'.join(errors)))
1687
1688 return results
1689
1690
jbriance9e12f162016-11-25 07:57:501691def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311692 """Checks that added or removed lines in non third party affected
1693 header files do not lead to new useless class or struct forward
1694 declaration.
jbriance9e12f162016-11-25 07:57:501695 """
1696 results = []
1697 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1698 input_api.re.MULTILINE)
1699 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1700 input_api.re.MULTILINE)
1701 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311702 if (f.LocalPath().startswith('third_party') and
1703 not f.LocalPath().startswith('third_party/WebKit') and
1704 not f.LocalPath().startswith('third_party\\WebKit')):
1705 continue
1706
jbriance9e12f162016-11-25 07:57:501707 if not f.LocalPath().endswith('.h'):
1708 continue
1709
1710 contents = input_api.ReadFile(f)
1711 fwd_decls = input_api.re.findall(class_pattern, contents)
1712 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1713
1714 useless_fwd_decls = []
1715 for decl in fwd_decls:
1716 count = sum(1 for _ in input_api.re.finditer(
1717 r'\b%s\b' % input_api.re.escape(decl), contents))
1718 if count == 1:
1719 useless_fwd_decls.append(decl)
1720
1721 if not useless_fwd_decls:
1722 continue
1723
1724 for line in f.GenerateScmDiff().splitlines():
1725 if (line.startswith('-') and not line.startswith('--') or
1726 line.startswith('+') and not line.startswith('++')):
1727 for decl in useless_fwd_decls:
1728 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1729 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241730 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501731 (f.LocalPath(), decl)))
1732 useless_fwd_decls.remove(decl)
1733
1734 return results
1735
1736
dskiba88634f4e2015-08-14 23:03:291737def _CheckAndroidToastUsage(input_api, output_api):
1738 """Checks that code uses org.chromium.ui.widget.Toast instead of
1739 android.widget.Toast (Chromium Toast doesn't force hardware
1740 acceleration on low-end devices, saving memory).
1741 """
1742 toast_import_pattern = input_api.re.compile(
1743 r'^import android\.widget\.Toast;$')
1744
1745 errors = []
1746
1747 sources = lambda affected_file: input_api.FilterSourceFile(
1748 affected_file,
1749 black_list=(_EXCLUDED_PATHS +
1750 _TEST_CODE_EXCLUDED_PATHS +
1751 input_api.DEFAULT_BLACK_LIST +
1752 (r'^chromecast[\\\/].*',
1753 r'^remoting[\\\/].*')),
1754 white_list=(r'.*\.java$',))
1755
1756 for f in input_api.AffectedSourceFiles(sources):
1757 for line_num, line in f.ChangedContents():
1758 if toast_import_pattern.search(line):
1759 errors.append("%s:%d" % (f.LocalPath(), line_num))
1760
1761 results = []
1762
1763 if errors:
1764 results.append(output_api.PresubmitError(
1765 'android.widget.Toast usage is detected. Android toasts use hardware'
1766 ' acceleration, and can be\ncostly on low-end devices. Please use'
1767 ' org.chromium.ui.widget.Toast instead.\n'
1768 'Contact [email protected] if you have any questions.',
1769 errors))
1770
1771 return results
1772
1773
dgnaa68d5e2015-06-10 10:08:221774def _CheckAndroidCrLogUsage(input_api, output_api):
1775 """Checks that new logs using org.chromium.base.Log:
1776 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511777 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221778 """
pkotwicza1dd0b002016-05-16 14:41:041779
torne89540622017-03-24 19:41:301780 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041781 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301782 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041783 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301784 # WebView license viewer code cannot depend on //base; used in stub APK.
1785 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1786 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041787 ]
1788
dgnaa68d5e2015-06-10 10:08:221789 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121790 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1791 class_in_base_pattern = input_api.re.compile(
1792 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1793 has_some_log_import_pattern = input_api.re.compile(
1794 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221795 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121796 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221797 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511798 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221799 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221800
Vincent Scheib16d7b272015-09-15 18:09:071801 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221802 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041803 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1804 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121805
dgnaa68d5e2015-06-10 10:08:221806 tag_decl_errors = []
1807 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121808 tag_errors = []
dgn38736db2015-09-18 19:20:511809 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121810 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221811
1812 for f in input_api.AffectedSourceFiles(sources):
1813 file_content = input_api.ReadFile(f)
1814 has_modified_logs = False
1815
1816 # Per line checks
dgn87d9fb62015-06-12 09:15:121817 if (cr_log_import_pattern.search(file_content) or
1818 (class_in_base_pattern.search(file_content) and
1819 not has_some_log_import_pattern.search(file_content))):
1820 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221821 for line_num, line in f.ChangedContents():
1822
1823 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121824 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221825 if match:
1826 has_modified_logs = True
1827
1828 # Make sure it uses "TAG"
1829 if not match.group('tag') == 'TAG':
1830 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121831 else:
1832 # Report non cr Log function calls in changed lines
1833 for line_num, line in f.ChangedContents():
1834 if log_call_pattern.search(line):
1835 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221836
1837 # Per file checks
1838 if has_modified_logs:
1839 # Make sure the tag is using the "cr" prefix and is not too long
1840 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511841 tag_name = match.group('name') if match else None
1842 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221843 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511844 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221845 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511846 elif '.' in tag_name:
1847 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221848
1849 results = []
1850 if tag_decl_errors:
1851 results.append(output_api.PresubmitPromptWarning(
1852 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511853 '"private static final String TAG = "<package tag>".\n'
1854 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221855 tag_decl_errors))
1856
1857 if tag_length_errors:
1858 results.append(output_api.PresubmitError(
1859 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511860 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221861 tag_length_errors))
1862
1863 if tag_errors:
1864 results.append(output_api.PresubmitPromptWarning(
1865 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1866 tag_errors))
1867
dgn87d9fb62015-06-12 09:15:121868 if util_log_errors:
dgn4401aa52015-04-29 16:26:171869 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121870 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1871 util_log_errors))
1872
dgn38736db2015-09-18 19:20:511873 if tag_with_dot_errors:
1874 results.append(output_api.PresubmitPromptWarning(
1875 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1876 tag_with_dot_errors))
1877
dgn4401aa52015-04-29 16:26:171878 return results
1879
1880
yolandyan45001472016-12-21 21:12:421881def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1882 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1883 deprecated_annotation_import_pattern = input_api.re.compile(
1884 r'^import android\.test\.suitebuilder\.annotation\..*;',
1885 input_api.re.MULTILINE)
1886 sources = lambda x: input_api.FilterSourceFile(
1887 x, white_list=(r'.*\.java$',), black_list=None)
1888 errors = []
1889 for f in input_api.AffectedFiles(sources):
1890 for line_num, line in f.ChangedContents():
1891 if deprecated_annotation_import_pattern.search(line):
1892 errors.append("%s:%d" % (f.LocalPath(), line_num))
1893
1894 results = []
1895 if errors:
1896 results.append(output_api.PresubmitError(
1897 'Annotations in android.test.suitebuilder.annotation have been'
1898 ' deprecated since API level 24. Please use android.support.test.filters'
1899 ' from //third_party/android_support_test_runner:runner_java instead.'
1900 ' Contact [email protected] if you have any questions.', errors))
1901 return results
1902
1903
agrieve7b6479d82015-10-07 14:24:221904def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1905 """Checks if MDPI assets are placed in a correct directory."""
1906 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1907 ('/res/drawable/' in f.LocalPath() or
1908 '/res/drawable-ldrtl/' in f.LocalPath()))
1909 errors = []
1910 for f in input_api.AffectedFiles(include_deletes=False,
1911 file_filter=file_filter):
1912 errors.append(' %s' % f.LocalPath())
1913
1914 results = []
1915 if errors:
1916 results.append(output_api.PresubmitError(
1917 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1918 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1919 '/res/drawable-ldrtl/.\n'
1920 'Contact [email protected] if you have questions.', errors))
1921 return results
1922
1923
agrievef32bcc72016-04-04 14:57:401924class PydepsChecker(object):
1925 def __init__(self, input_api, pydeps_files):
1926 self._file_cache = {}
1927 self._input_api = input_api
1928 self._pydeps_files = pydeps_files
1929
1930 def _LoadFile(self, path):
1931 """Returns the list of paths within a .pydeps file relative to //."""
1932 if path not in self._file_cache:
1933 with open(path) as f:
1934 self._file_cache[path] = f.read()
1935 return self._file_cache[path]
1936
1937 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1938 """Returns an interable of paths within the .pydep, relativized to //."""
1939 os_path = self._input_api.os_path
1940 pydeps_dir = os_path.dirname(pydeps_path)
1941 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1942 if not l.startswith('*'))
1943 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1944
1945 def _CreateFilesToPydepsMap(self):
1946 """Returns a map of local_path -> list_of_pydeps."""
1947 ret = {}
1948 for pydep_local_path in self._pydeps_files:
1949 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1950 ret.setdefault(path, []).append(pydep_local_path)
1951 return ret
1952
1953 def ComputeAffectedPydeps(self):
1954 """Returns an iterable of .pydeps files that might need regenerating."""
1955 affected_pydeps = set()
1956 file_to_pydeps_map = None
1957 for f in self._input_api.AffectedFiles(include_deletes=True):
1958 local_path = f.LocalPath()
1959 if local_path == 'DEPS':
1960 return self._pydeps_files
1961 elif local_path.endswith('.pydeps'):
1962 if local_path in self._pydeps_files:
1963 affected_pydeps.add(local_path)
1964 elif local_path.endswith('.py'):
1965 if file_to_pydeps_map is None:
1966 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1967 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1968 return affected_pydeps
1969
1970 def DetermineIfStale(self, pydeps_path):
1971 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411972 import difflib
agrievef32bcc72016-04-04 14:57:401973 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1974 cmd = old_pydeps_data[1][1:].strip()
1975 new_pydeps_data = self._input_api.subprocess.check_output(
1976 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411977 old_contents = old_pydeps_data[2:]
1978 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401979 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411980 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401981
1982
1983def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1984 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001985 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281986 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1987 # Mac, so skip it on other platforms.
1988 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001989 return []
agrievef32bcc72016-04-04 14:57:401990 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1991 is_android = input_api.os_path.exists('third_party/android_tools')
1992 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1993 results = []
1994 # First, check for new / deleted .pydeps.
1995 for f in input_api.AffectedFiles(include_deletes=True):
1996 if f.LocalPath().endswith('.pydeps'):
1997 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1998 results.append(output_api.PresubmitError(
1999 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2000 'remove %s' % f.LocalPath()))
2001 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2002 results.append(output_api.PresubmitError(
2003 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2004 'include %s' % f.LocalPath()))
2005
2006 if results:
2007 return results
2008
2009 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2010
2011 for pydep_path in checker.ComputeAffectedPydeps():
2012 try:
phajdan.jr0d9878552016-11-04 10:49:412013 result = checker.DetermineIfStale(pydep_path)
2014 if result:
2015 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402016 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412017 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2018 'To regenerate, run:\n\n %s' %
2019 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402020 except input_api.subprocess.CalledProcessError as error:
2021 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2022 long_text=error.output)]
2023
2024 return results
2025
2026
glidere61efad2015-02-18 17:39:432027def _CheckSingletonInHeaders(input_api, output_api):
2028 """Checks to make sure no header files have |Singleton<|."""
2029 def FileFilter(affected_file):
2030 # It's ok for base/memory/singleton.h to have |Singleton<|.
2031 black_list = (_EXCLUDED_PATHS +
2032 input_api.DEFAULT_BLACK_LIST +
2033 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2034 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2035
sergeyu34d21222015-09-16 00:11:442036 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432037 files = []
2038 for f in input_api.AffectedSourceFiles(FileFilter):
2039 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2040 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2041 contents = input_api.ReadFile(f)
2042 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242043 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432044 pattern.search(line)):
2045 files.append(f)
2046 break
2047
2048 if files:
yolandyandaabc6d2016-04-18 18:29:392049 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442050 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432051 'Please move them to an appropriate source file so that the ' +
2052 'template gets instantiated in a single compilation unit.',
2053 files) ]
2054 return []
2055
2056
[email protected]fd20b902014-05-09 02:14:532057_DEPRECATED_CSS = [
2058 # Values
2059 ( "-webkit-box", "flex" ),
2060 ( "-webkit-inline-box", "inline-flex" ),
2061 ( "-webkit-flex", "flex" ),
2062 ( "-webkit-inline-flex", "inline-flex" ),
2063 ( "-webkit-min-content", "min-content" ),
2064 ( "-webkit-max-content", "max-content" ),
2065
2066 # Properties
2067 ( "-webkit-background-clip", "background-clip" ),
2068 ( "-webkit-background-origin", "background-origin" ),
2069 ( "-webkit-background-size", "background-size" ),
2070 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442071 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532072
2073 # Functions
2074 ( "-webkit-gradient", "gradient" ),
2075 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2076 ( "-webkit-linear-gradient", "linear-gradient" ),
2077 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2078 ( "-webkit-radial-gradient", "radial-gradient" ),
2079 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2080]
2081
dbeam1ec68ac2016-12-15 05:22:242082def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532083 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252084 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342085 documentation and iOS CSS for dom distiller
2086 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252087 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532088 results = []
dbeam070cfe62014-10-22 06:44:022089 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252090 black_list = (_EXCLUDED_PATHS +
2091 _TEST_CODE_EXCLUDED_PATHS +
2092 input_api.DEFAULT_BLACK_LIST +
2093 (r"^chrome/common/extensions/docs",
2094 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342095 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:052096 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:442097 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252098 r"^native_client_sdk"))
2099 file_filter = lambda f: input_api.FilterSourceFile(
2100 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532101 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2102 for line_num, line in fpath.ChangedContents():
2103 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022104 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532105 results.append(output_api.PresubmitError(
2106 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2107 (fpath.LocalPath(), line_num, deprecated_value, value)))
2108 return results
2109
mohan.reddyf21db962014-10-16 12:26:472110
dbeam070cfe62014-10-22 06:44:022111_DEPRECATED_JS = [
2112 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2113 ( "__defineGetter__", "Object.defineProperty" ),
2114 ( "__defineSetter__", "Object.defineProperty" ),
2115]
2116
dbeam1ec68ac2016-12-15 05:22:242117def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022118 """Make sure that we don't use deprecated JS in Chrome code."""
2119 results = []
2120 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2121 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2122 input_api.DEFAULT_BLACK_LIST)
2123 file_filter = lambda f: input_api.FilterSourceFile(
2124 f, white_list=file_inclusion_pattern, black_list=black_list)
2125 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2126 for lnum, line in fpath.ChangedContents():
2127 for (deprecated, replacement) in _DEPRECATED_JS:
2128 if deprecated in line:
2129 results.append(output_api.PresubmitError(
2130 "%s:%d: Use of deprecated JS %s, use %s instead" %
2131 (fpath.LocalPath(), lnum, deprecated, replacement)))
2132 return results
2133
2134
dbeam1ec68ac2016-12-15 05:22:242135def _CheckForRiskyJsFeatures(input_api, output_api):
2136 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2137 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2138
2139 arrow_lines = []
2140 for f in input_api.AffectedFiles(file_filter=file_filter):
2141 for lnum, line in f.ChangedContents():
2142 if ' => ' in line:
2143 arrow_lines.append((f.LocalPath(), lnum))
2144
2145 if not arrow_lines:
2146 return []
2147
2148 return [output_api.PresubmitPromptWarning("""
2149Use of => operator detected in:
2150%s
2151Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2152https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2153""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2154
2155
rlanday6802cf632017-05-30 17:48:362156def _CheckForRelativeIncludes(input_api, output_api):
2157 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2158 import sys
2159 original_sys_path = sys.path
2160 try:
2161 sys.path = sys.path + [input_api.os_path.join(
2162 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2163 from cpp_checker import CppChecker
2164 finally:
2165 # Restore sys.path to what it was before.
2166 sys.path = original_sys_path
2167
2168 bad_files = {}
2169 for f in input_api.AffectedFiles(include_deletes=False):
2170 if (f.LocalPath().startswith('third_party') and
2171 not f.LocalPath().startswith('third_party/WebKit') and
2172 not f.LocalPath().startswith('third_party\\WebKit')):
2173 continue
2174
2175 if not CppChecker.IsCppFile(f.LocalPath()):
2176 continue
2177
2178 relative_includes = [line for line_num, line in f.ChangedContents()
2179 if "#include" in line and "../" in line]
2180 if not relative_includes:
2181 continue
2182 bad_files[f.LocalPath()] = relative_includes
2183
2184 if not bad_files:
2185 return []
2186
2187 error_descriptions = []
2188 for file_path, bad_lines in bad_files.iteritems():
2189 error_description = file_path
2190 for line in bad_lines:
2191 error_description += '\n ' + line
2192 error_descriptions.append(error_description)
2193
2194 results = []
2195 results.append(output_api.PresubmitError(
2196 'You added one or more relative #include paths (including "../").\n'
2197 'These shouldn\'t be used because they can be used to include headers\n'
2198 'from code that\'s not correctly specified as a dependency in the\n'
2199 'relevant BUILD.gn file(s).',
2200 error_descriptions))
2201
2202 return results
2203
dgnaa68d5e2015-06-10 10:08:222204def _AndroidSpecificOnUploadChecks(input_api, output_api):
2205 """Groups checks that target android code."""
2206 results = []
dgnaa68d5e2015-06-10 10:08:222207 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222208 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292209 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422210 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222211 return results
2212
2213
[email protected]22c9bd72011-03-27 16:47:392214def _CommonChecks(input_api, output_api):
2215 """Checks common to both upload and commit."""
2216 results = []
2217 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382218 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542219 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582220 results.extend(
2221 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192222 results.extend(
[email protected]760deea2013-12-10 19:33:492223 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542224 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182225 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522226 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222227 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442228 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592229 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062230 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122231 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182232 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222233 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302234 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492235 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272236 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032237 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492238 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442239 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272240 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542241 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442242 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392243 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552244 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042245 results.extend(
2246 input_api.canned_checks.CheckChangeHasNoTabs(
2247 input_api,
2248 output_api,
2249 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402250 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162251 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592252 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082253 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242254 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2255 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472256 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042257 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232258 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432259 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402260 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152261 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172262 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502263 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242264 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362265 results.extend(_CheckForRelativeIncludes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242266
2267 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2268 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2269 input_api, output_api,
2270 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382271 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392272 return results
[email protected]1f7b4172010-01-28 01:17:342273
[email protected]b337cb5b2011-01-23 21:24:052274
[email protected]b8079ae4a2012-12-05 19:56:492275def _CheckPatchFiles(input_api, output_api):
2276 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2277 if f.LocalPath().endswith(('.orig', '.rej'))]
2278 if problems:
2279 return [output_api.PresubmitError(
2280 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032281 else:
2282 return []
[email protected]b8079ae4a2012-12-05 19:56:492283
2284
[email protected]b00342e7f2013-03-26 16:21:542285def _DidYouMeanOSMacro(bad_macro):
2286 try:
2287 return {'A': 'OS_ANDROID',
2288 'B': 'OS_BSD',
2289 'C': 'OS_CHROMEOS',
2290 'F': 'OS_FREEBSD',
2291 'L': 'OS_LINUX',
2292 'M': 'OS_MACOSX',
2293 'N': 'OS_NACL',
2294 'O': 'OS_OPENBSD',
2295 'P': 'OS_POSIX',
2296 'S': 'OS_SOLARIS',
2297 'W': 'OS_WIN'}[bad_macro[3].upper()]
2298 except KeyError:
2299 return ''
2300
2301
2302def _CheckForInvalidOSMacrosInFile(input_api, f):
2303 """Check for sensible looking, totally invalid OS macros."""
2304 preprocessor_statement = input_api.re.compile(r'^\s*#')
2305 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2306 results = []
2307 for lnum, line in f.ChangedContents():
2308 if preprocessor_statement.search(line):
2309 for match in os_macro.finditer(line):
2310 if not match.group(1) in _VALID_OS_MACROS:
2311 good = _DidYouMeanOSMacro(match.group(1))
2312 did_you_mean = ' (did you mean %s?)' % good if good else ''
2313 results.append(' %s:%d %s%s' % (f.LocalPath(),
2314 lnum,
2315 match.group(1),
2316 did_you_mean))
2317 return results
2318
2319
2320def _CheckForInvalidOSMacros(input_api, output_api):
2321 """Check all affected files for invalid OS macros."""
2322 bad_macros = []
2323 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472324 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542325 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2326
2327 if not bad_macros:
2328 return []
2329
2330 return [output_api.PresubmitError(
2331 'Possibly invalid OS macro[s] found. Please fix your code\n'
2332 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2333
lliabraa35bab3932014-10-01 12:16:442334
2335def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2336 """Check all affected files for invalid "if defined" macros."""
2337 ALWAYS_DEFINED_MACROS = (
2338 "TARGET_CPU_PPC",
2339 "TARGET_CPU_PPC64",
2340 "TARGET_CPU_68K",
2341 "TARGET_CPU_X86",
2342 "TARGET_CPU_ARM",
2343 "TARGET_CPU_MIPS",
2344 "TARGET_CPU_SPARC",
2345 "TARGET_CPU_ALPHA",
2346 "TARGET_IPHONE_SIMULATOR",
2347 "TARGET_OS_EMBEDDED",
2348 "TARGET_OS_IPHONE",
2349 "TARGET_OS_MAC",
2350 "TARGET_OS_UNIX",
2351 "TARGET_OS_WIN32",
2352 )
2353 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2354 results = []
2355 for lnum, line in f.ChangedContents():
2356 for match in ifdef_macro.finditer(line):
2357 if match.group(1) in ALWAYS_DEFINED_MACROS:
2358 always_defined = ' %s is always defined. ' % match.group(1)
2359 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2360 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2361 lnum,
2362 always_defined,
2363 did_you_mean))
2364 return results
2365
2366
2367def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2368 """Check all affected files for invalid "if defined" macros."""
2369 bad_macros = []
2370 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212371 if f.LocalPath().startswith('third_party/sqlite/'):
2372 continue
lliabraa35bab3932014-10-01 12:16:442373 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2374 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2375
2376 if not bad_macros:
2377 return []
2378
2379 return [output_api.PresubmitError(
2380 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2381 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2382 bad_macros)]
2383
2384
mlamouria82272622014-09-16 18:45:042385def _CheckForIPCRules(input_api, output_api):
2386 """Check for same IPC rules described in
2387 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2388 """
2389 base_pattern = r'IPC_ENUM_TRAITS\('
2390 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2391 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2392
2393 problems = []
2394 for f in input_api.AffectedSourceFiles(None):
2395 local_path = f.LocalPath()
2396 if not local_path.endswith('.h'):
2397 continue
2398 for line_number, line in f.ChangedContents():
2399 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2400 problems.append(
2401 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2402
2403 if problems:
2404 return [output_api.PresubmitPromptWarning(
2405 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2406 else:
2407 return []
2408
[email protected]b00342e7f2013-03-26 16:21:542409
mostynbb639aca52015-01-07 20:31:232410def _CheckForWindowsLineEndings(input_api, output_api):
2411 """Check source code and known ascii text files for Windows style line
2412 endings.
2413 """
earthdok1b5e0ee2015-03-10 15:19:102414 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232415
2416 file_inclusion_pattern = (
2417 known_text_files,
2418 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2419 )
2420
2421 filter = lambda f: input_api.FilterSourceFile(
2422 f, white_list=file_inclusion_pattern, black_list=None)
2423 files = [f.LocalPath() for f in
2424 input_api.AffectedSourceFiles(filter)]
2425
2426 problems = []
2427
2428 for file in files:
2429 fp = open(file, 'r')
2430 for line in fp:
2431 if line.endswith('\r\n'):
2432 problems.append(file)
2433 break
2434 fp.close()
2435
2436 if problems:
2437 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2438 'these files to contain Windows style line endings?\n' +
2439 '\n'.join(problems))]
2440
2441 return []
2442
2443
pastarmovj89f7ee12016-09-20 14:58:132444def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2445 lint_filters=None, verbose_level=None):
2446 """Checks that all source files use SYSLOG properly."""
2447 syslog_files = []
2448 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562449 for line_number, line in f.ChangedContents():
2450 if 'SYSLOG' in line:
2451 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2452
pastarmovj89f7ee12016-09-20 14:58:132453 if syslog_files:
2454 return [output_api.PresubmitPromptWarning(
2455 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2456 ' calls.\nFiles to check:\n', items=syslog_files)]
2457 return []
2458
2459
[email protected]1f7b4172010-01-28 01:17:342460def CheckChangeOnUpload(input_api, output_api):
2461 results = []
2462 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472463 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282464 results.extend(
jam93a6ee792017-02-08 23:59:222465 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192466 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222467 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132468 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162469 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542470 return results
[email protected]ca8d19842009-02-19 16:33:122471
2472
[email protected]1bfb8322014-04-23 01:02:412473def GetTryServerMasterForBot(bot):
2474 """Returns the Try Server master for the given bot.
2475
[email protected]0bb112362014-07-26 04:38:322476 It tries to guess the master from the bot name, but may still fail
2477 and return None. There is no longer a default master.
2478 """
2479 # Potentially ambiguous bot names are listed explicitly.
2480 master_map = {
tandriie5587792016-07-14 00:34:502481 'chromium_presubmit': 'master.tryserver.chromium.linux',
2482 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412483 }
[email protected]0bb112362014-07-26 04:38:322484 master = master_map.get(bot)
2485 if not master:
wnwen4fbaab82016-05-25 12:54:362486 if 'android' in bot:
tandriie5587792016-07-14 00:34:502487 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362488 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502489 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322490 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502491 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322492 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502493 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322494 return master
[email protected]1bfb8322014-04-23 01:02:412495
2496
Paweł Hajdan, Jr55083782014-12-19 20:32:562497def GetDefaultTryConfigs(bots):
2498 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012499 """
2500
Paweł Hajdan, Jr55083782014-12-19 20:32:562501 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412502
2503 # Build up the mapping from tryserver master to bot/test.
2504 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562505 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412506 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2507 return out
[email protected]38c6a512013-12-18 23:48:012508
2509
[email protected]ca8d19842009-02-19 16:33:122510def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542511 results = []
[email protected]1f7b4172010-01-28 01:17:342512 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542513 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272514 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342515 input_api,
2516 output_api,
[email protected]2fdd1f362013-01-16 03:56:032517 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272518
jam93a6ee792017-02-08 23:59:222519 results.extend(
2520 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542521 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2522 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412523 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2524 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542525 return results